Skip to content

Commit 076fd6a

Browse files
mped-oticoncarlescufi
authored andcommitted
bluetooth: controller: Document mem, memq, util
Adds documentation-commentary to some infrastructure used by the LL. It is a long-term effort to better document the LL. Notably ticker and mayfly require more documentation; this will be done later. Signed-off-by: Mark Ruvald Pedersen <[email protected]>
1 parent 2b63cfb commit 076fd6a

File tree

5 files changed

+140
-22
lines changed

5 files changed

+140
-22
lines changed

subsys/bluetooth/controller/util/mem.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ void mem_init(void *mem_pool, u16_t mem_size, u16_t mem_count,
1717
{
1818
*mem_head = mem_pool;
1919

20-
/* Store free mem_count after the list's next pointer at an aligned
21-
* memory location to ensure atomic read/write (in ARM for now).
20+
/* Store free mem_count after the list's next pointer at an 32-bit
21+
* aligned memory location to ensure atomic read/write (in ARM for now).
2222
*/
2323
*((u16_t *)MROUND((u8_t *)mem_pool + sizeof(mem_pool))) = mem_count;
2424

@@ -107,6 +107,10 @@ u16_t mem_index_get(void *mem, void *mem_pool, u16_t mem_size)
107107
return ((u16_t)((u8_t *)mem - (u8_t *)mem_pool) / mem_size);
108108
}
109109

110+
/**
111+
* @brief Copy bytes in reverse
112+
* @details Example: [ 0x11 0x22 0x33 ] -> [ 0x33 0x22 0x11 ]
113+
*/
110114
void mem_rcopy(u8_t *dst, u8_t const *src, u16_t len)
111115
{
112116
src += len;
@@ -115,6 +119,10 @@ void mem_rcopy(u8_t *dst, u8_t const *src, u16_t len)
115119
}
116120
}
117121

122+
/**
123+
* @brief Determine if src[0..len-1] contains one or more non-zero bytes
124+
* @return 0 if all bytes are zero; otherwise 1
125+
*/
118126
u8_t mem_nz(u8_t *src, u16_t len)
119127
{
120128
while (len--) {
@@ -126,6 +134,9 @@ u8_t mem_nz(u8_t *src, u16_t len)
126134
return 0;
127135
}
128136

137+
/**
138+
* @brief Unit test
139+
*/
129140
u32_t mem_ut(void)
130141
{
131142
#define BLOCK_SIZE MROUND(10)

subsys/bluetooth/controller/util/mem.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,34 @@
66
*/
77

88
#ifndef MALIGN
9+
/**
10+
* @brief Force compiler to place memory at-least on a x-byte boundary
11+
* @details Compiler extension. Supported by GCC and Clang
12+
*/
913
#define MALIGN(x) __attribute__((aligned(x)))
1014
#endif
1115

1216
#ifndef MROUND
17+
/**
18+
* @brief Round up to nearest multiple of 4, for unsigned integers
19+
* @details
20+
* The addition of 3 forces x into the next multiple of 4. This is responsible
21+
* for the rounding in the the next step, to be Up.
22+
* For ANDing of ~3: We observe y & (~3) == (y>>2)<<2, and we recognize
23+
* (y>>2) as a floored division, which is almost undone by the left-shift. The
24+
* flooring can't be undone so have achieved a rounding.
25+
*
26+
* Examples:
27+
* MROUND( 0) = 0
28+
* MROUND( 1) = 4
29+
* MROUND( 2) = 4
30+
* MROUND( 3) = 4
31+
* MROUND( 4) = 4
32+
* MROUND( 5) = 8
33+
* MROUND( 8) = 8
34+
* MROUND( 9) = 12
35+
* MROUND(13) = 16
36+
*/
1337
#define MROUND(x) (((u32_t)(x)+3) & (~((u32_t)3)))
1438
#endif
1539

subsys/bluetooth/controller/util/memq.c

Lines changed: 86 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,66 @@
55
* SPDX-License-Identifier: Apache-2.0
66
*/
77

8+
/**
9+
* FIFO-style "memory queue" permitting enqueue at tail and dequeue from head.
10+
* Element's payload is a pointer to arbitrary memory.
11+
*
12+
* Implemented as a singly-linked list, with always one-more element.
13+
* The linked list must always contain at least one link-element, as emptiness
14+
* is given by head == tail.
15+
* For a queue to be valid, it must be initialized with an initial link-element.
16+
*
17+
* Invariant: The tail element's mem pointer is DontCare.
18+
*
19+
* Note that at enqueue, memory is not coupled with its accompanying
20+
* link-element, but the link-element before it!
21+
*
22+
* Call | State after call
23+
* ------------------------+-------------------------------
24+
* memq_init(I,H,T) | H -> I[] <- T
25+
* memq_enqueue(A,a,T); | H -> I[a] -> A[] <- T
26+
* memq_enqueue(B,b,T); | H -> I[a] -> A[b] -> B[] <- T
27+
* memq_dequeue(T,H,dest); | H -> A[b] -> B[] <- T # I and a as return and dest
28+
*
29+
* where H is the pointer to Head link-element (oldest element).
30+
* where T is the pointer to Tail link-element (newest element).
31+
* where I[] means the initial link-element, whose mem pointer is DontCare.
32+
* where A[b] means the A'th link-element, whose mem pointer is b.
33+
*/
34+
835
#include <zephyr/types.h>
936
#include <stddef.h>
1037

1138
#include "memq.h"
1239

13-
inline memq_link_t *memq_peek(memq_link_t *head, memq_link_t *tail, void **mem);
14-
40+
/**
41+
* @brief Initialize a memory queue to be empty and valid.
42+
*
43+
* @param link[in] Initial link-element. Not associated with any mem
44+
* @param head[out] Head of queue. Will be updated
45+
* @param tail[out] Tail of queue. Will be updated
46+
* @return Initial link-element
47+
*/
1548
memq_link_t *memq_init(memq_link_t *link, memq_link_t **head, memq_link_t **tail)
1649
{
17-
/* head and tail pointer to the initial link */
50+
/* Head and tail pointer to the initial link - forms an empty queue */
1851
*head = *tail = link;
1952

2053
return link;
2154
}
2255

56+
/**
57+
* @brief De-initialize a memory queue to be empty and invalid.
58+
*
59+
* @param head[in,out] Head of queue. Will be updated
60+
* @param tail[in,out] Tail of queue. Will be updated
61+
* @return If empty, return initial link-element. Otherwise NULL
62+
*/
2363
memq_link_t *memq_deinit(memq_link_t **head, memq_link_t **tail)
2464
{
2565
memq_link_t *link;
2666

27-
/* if head and tail are not equal, then queue is not empty */
67+
/* If head and tail are not equal, then queue is not empty */
2868
if (*head != *tail) {
2969
return NULL;
3070
}
@@ -35,47 +75,75 @@ memq_link_t *memq_deinit(memq_link_t **head, memq_link_t **tail)
3575
return link;
3676
}
3777

78+
/**
79+
* @brief Enqueue at the tail of the queue
80+
* @details Enqueue is destructive so tail will change to new tail
81+
*
82+
* @param link[in] Element to become the new tail. Not associated mem
83+
* @param mem[in] Memory buffer. Will be owned by old tail
84+
* @param tail[in,out] Tail of queue. Will be updated to point to link
85+
* @return New tail
86+
*/
3887
memq_link_t *memq_enqueue(memq_link_t *link, void *mem, memq_link_t **tail)
3988
{
40-
/* make the current tail link's next point to new link */
89+
/* Let the old tail element point to the new tail element */
4190
(*tail)->next = link;
4291

43-
/* assign mem to current tail link's mem */
92+
/* Let the old tail element point the the new memory */
4493
(*tail)->mem = mem;
4594

46-
/* increment the tail! */
95+
/* Update the tail-pointer to point to the new tail element.
96+
* The new tail-element is not expected to point to anything sensible
97+
*/
4798
*tail = link;
4899

49100
return link;
50101
}
51102

103+
/**
104+
* @brief Non-destructive peek of head of queue.
105+
*
106+
* @param head[in] Pointer to head link-element of queue
107+
* @param tail[in] Pointer to tail link-element of queue
108+
* @param mem[out] The memory pointed to by head-element
109+
* @return head or NULL if queue is empty
110+
*/
52111
memq_link_t *memq_peek(memq_link_t *head, memq_link_t *tail, void **mem)
53112
{
54-
/* if head and tail are equal, then queue empty */
113+
/* If head and tail are equal, then queue empty */
55114
if (head == tail) {
56115
return NULL;
57116
}
58117

59-
/* extract the link's mem */
118+
/* Extract the head link-element's memory */
60119
if (mem) {
61120
*mem = head->mem;
62121
}
63122

64-
return head;
123+
return head; /* queue was not empty */
65124
}
66125

126+
/**
127+
* @brief Remove and returns the head of queue.
128+
* @details Dequeue is destructive so head will change to new head
129+
*
130+
* @param tail[in] Pointer to tail link-element of queue
131+
* @param head[in,out] Pointer to head link-element of queue. Will be updated
132+
* @param mem[out] The memory pointed to by head-element
133+
* @return head or NULL if queue is empty
134+
*/
67135
memq_link_t *memq_dequeue(memq_link_t *tail, memq_link_t **head, void **mem)
68136
{
69-
memq_link_t *link;
137+
memq_link_t *old_head;
70138

71-
/* use memq peek to get the link and mem */
72-
link = memq_peek(*head, tail, mem);
73-
if (!link) {
74-
return link;
139+
/* Use memq peek to get the old head and its mem */
140+
old_head = memq_peek(*head, tail, mem);
141+
if (old_head == NULL) {
142+
return NULL; /* queue is empty */
75143
}
76144

77-
/* increment the head to next link node */
78-
*head = link->next;
145+
/* Update the head-pointer to point to the new head element */
146+
*head = old_head->next;
79147

80-
return link;
148+
return old_head;
81149
}

subsys/bluetooth/controller/util/memq.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@
55
* SPDX-License-Identifier: Apache-2.0
66
*/
77

8+
/**
9+
* @brief Element of a memory-queue
10+
* @details Elements form a linked list, and as payload carries a pointer
11+
*/
812
struct _memq_link {
9-
struct _memq_link *next;
10-
void *mem;
13+
struct _memq_link *next; /* permit chaining */
14+
void *mem; /* payload */
1115
};
1216

1317
typedef struct _memq_link memq_link_t;

subsys/bluetooth/controller/util/util.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,17 @@
88
#include <zephyr/types.h>
99
#include "util.h"
1010

11+
/**
12+
* @brief Population count: Count the number of bits set to 1
13+
* @details
14+
* TODO: Faster methods available at [1].
15+
* [1] http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
16+
*
17+
* @param octets Data to count over
18+
* @param octets_len Must not be bigger than 255/8 = 31 bytes
19+
*
20+
* @return popcnt of 'octets'
21+
*/
1122
u8_t util_ones_count_get(u8_t *octets, u8_t octets_len)
1223
{
1324
u8_t one_count = 0U;

0 commit comments

Comments
 (0)