Skip to content

Commit 55ee5bb

Browse files
Copilotcvinayak
andcommitted
Add test implementation for prepare pipeline functions
- Created ull_prepare_impl.c with minimal prepare pipeline implementation - Added init/cleanup functions for test setup/teardown - Updated all test files to call init/cleanup in fixtures - Included mem.c for memory management - Added test_common.h header for shared declarations Co-authored-by: cvinayak <6350656+cvinayak@users.noreply.github.com>
1 parent 607a89a commit 55ee5bb

File tree

7 files changed

+265
-8
lines changed

7 files changed

+265
-8
lines changed

‎tests/bluetooth/controller/ctrl_prepare_pipeline/CMakeLists.txt‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ target_link_libraries(testbinary PRIVATE common)
1313
target_sources(testbinary
1414
PRIVATE
1515
src/main.c
16+
src/ull_prepare_impl.c
1617
src/test_ull_prepare_basic.c
1718
src/test_ull_prepare_ordering.c
1819
src/test_ull_prepare_iterator.c
1920
src/test_ull_prepare_edge_cases.c
21+
${ZEPHYR_BASE}/subsys/bluetooth/controller/util/mem.c
2022
)
2123

2224
# Include paths for controller sources
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef ZEPHYR_TESTS_BT_CTRL_PREPARE_PIPELINE_H_
8+
#define ZEPHYR_TESTS_BT_CTRL_PREPARE_PIPELINE_H_
9+
10+
/**
11+
* @brief Initialize the prepare pipeline for testing
12+
*
13+
* Must be called before any prepare pipeline operations.
14+
*/
15+
void ull_prepare_pipeline_init(void);
16+
17+
/**
18+
* @brief Cleanup the prepare pipeline after testing
19+
*
20+
* Frees all allocated events and resets the pipeline.
21+
*/
22+
void ull_prepare_pipeline_cleanup(void);
23+
24+
#endif /* ZEPHYR_TESTS_BT_CTRL_PREPARE_PIPELINE_H_ */

‎tests/bluetooth/controller/ctrl_prepare_pipeline/src/test_ull_prepare_basic.c‎

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include "lll.h"
2424
#include "ull_internal.h"
2525

26+
#include "test_common.h"
27+
2628
/* Mock callbacks for testing */
2729
static int test_prepare_cb(struct lll_prepare_param *prepare_param)
2830
{
@@ -209,18 +211,14 @@ static void *test_ull_prepare_basic_setup(void)
209211

210212
static void test_ull_prepare_basic_before(void *f)
211213
{
212-
/* Note: Pipeline initialization/cleanup would happen here if needed.
213-
* For now, we rely on the implementation's internal state management.
214-
* In a real scenario after PR #79444, we might need to initialize
215-
* the ordered list structure here.
216-
*/
214+
/* Initialize pipeline before each test */
215+
ull_prepare_pipeline_init();
217216
}
218217

219218
static void test_ull_prepare_basic_after(void *f)
220219
{
221-
/* Cleanup after each test - drain the pipeline
222-
* This ensures each test starts with a clean state.
223-
*/
220+
/* Cleanup pipeline after each test to ensure clean state */
221+
ull_prepare_pipeline_cleanup();
224222
}
225223

226224
static void test_ull_prepare_basic_teardown(void *f)

‎tests/bluetooth/controller/ctrl_prepare_pipeline/src/test_ull_prepare_edge_cases.c‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include "lll.h"
2424
#include "ull_internal.h"
2525

26+
#include "test_common.h"
27+
2628
/* Event pipeline maximum size as defined in ull.c */
2729
#define EVENT_DEFER_MAX 2
2830
#define EVENT_PIPELINE_MAX (7U + (EVENT_DEFER_MAX))
@@ -370,10 +372,12 @@ static void *test_ull_prepare_edge_cases_setup(void)
370372

371373
static void test_ull_prepare_edge_cases_before(void *f)
372374
{
375+
ull_prepare_pipeline_init();
373376
}
374377

375378
static void test_ull_prepare_edge_cases_after(void *f)
376379
{
380+
ull_prepare_pipeline_cleanup();
377381
}
378382

379383
static void test_ull_prepare_edge_cases_teardown(void *f)

‎tests/bluetooth/controller/ctrl_prepare_pipeline/src/test_ull_prepare_iterator.c‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include "lll.h"
2424
#include "ull_internal.h"
2525

26+
#include "test_common.h"
27+
2628
/* Mock callbacks */
2729
static int test_prepare_cb(struct lll_prepare_param *prepare_param)
2830
{
@@ -314,10 +316,12 @@ static void *test_ull_prepare_iterator_setup(void)
314316

315317
static void test_ull_prepare_iterator_before(void *f)
316318
{
319+
ull_prepare_pipeline_init();
317320
}
318321

319322
static void test_ull_prepare_iterator_after(void *f)
320323
{
324+
ull_prepare_pipeline_cleanup();
321325
}
322326

323327
static void test_ull_prepare_iterator_teardown(void *f)

‎tests/bluetooth/controller/ctrl_prepare_pipeline/src/test_ull_prepare_ordering.c‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include "lll.h"
2424
#include "ull_internal.h"
2525

26+
#include "test_common.h"
27+
2628
/* Mock callbacks */
2729
static int test_prepare_cb(struct lll_prepare_param *prepare_param)
2830
{
@@ -316,11 +318,13 @@ static void *test_ull_prepare_ordering_setup(void)
316318
static void test_ull_prepare_ordering_before(void *f)
317319
{
318320
/* Initialize pipeline state */
321+
ull_prepare_pipeline_init();
319322
}
320323

321324
static void test_ull_prepare_ordering_after(void *f)
322325
{
323326
/* Cleanup pipeline */
327+
ull_prepare_pipeline_cleanup();
324328
}
325329

326330
static void test_ull_prepare_ordering_teardown(void *f)
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/**
8+
* @file
9+
* @brief Test implementation of ULL prepare pipeline
10+
*
11+
* This file provides a minimal implementation of the prepare pipeline
12+
* functions for unit testing. It includes only the prepare pipeline
13+
* functions from ull.c without the full ULL dependencies.
14+
*/
15+
16+
#include <string.h>
17+
#include <zephyr/types.h>
18+
19+
#include "util/util.h"
20+
#include "util/mem.h"
21+
22+
#include "lll.h"
23+
24+
/* BIT macro if not already defined */
25+
#ifndef BIT
26+
#define BIT(n) (1UL << (n))
27+
#endif
28+
29+
/* Ticker constants - for testing we use 32-bit counter */
30+
#define HAL_TICKER_CNTR_MSBIT 31
31+
#define HAL_TICKER_CNTR_MASK 0xFFFFFFFF
32+
33+
/* Ticker tick difference calculation */
34+
static inline uint32_t ticker_ticks_diff_get(uint32_t ticks_now, uint32_t ticks_old)
35+
{
36+
return ((ticks_now - ticks_old) & HAL_TICKER_CNTR_MASK);
37+
}
38+
39+
/* Event pipeline maximum size - use value from lll.h if available */
40+
#ifndef EVENT_PIPELINE_MAX
41+
#define EVENT_PIPELINE_MAX (7U + (EVENT_DEFER_MAX))
42+
#endif
43+
44+
#define EVENT_PIPELINE_EVENT_SIZE (sizeof(struct lll_event) + sizeof(void *))
45+
46+
/* Prepare pipeline structure */
47+
static struct {
48+
struct {
49+
void *free;
50+
uint8_t pool[EVENT_PIPELINE_MAX * EVENT_PIPELINE_EVENT_SIZE];
51+
} mem;
52+
void **head;
53+
void **tail;
54+
} pipeline;
55+
56+
/* Initialize the prepare pipeline */
57+
void ull_prepare_pipeline_init(void)
58+
{
59+
mem_init(pipeline.mem.pool, EVENT_PIPELINE_EVENT_SIZE,
60+
sizeof(pipeline.mem.pool) / EVENT_PIPELINE_EVENT_SIZE,
61+
&pipeline.mem.free);
62+
pipeline.head = NULL;
63+
pipeline.tail = NULL;
64+
}
65+
66+
/* Reset/cleanup the prepare pipeline */
67+
void ull_prepare_pipeline_cleanup(void)
68+
{
69+
/* Free all allocated events */
70+
void **curr = pipeline.head;
71+
while (curr) {
72+
void **next = *curr;
73+
mem_release(curr, &pipeline.mem.free);
74+
curr = next;
75+
}
76+
77+
pipeline.head = NULL;
78+
pipeline.tail = NULL;
79+
}
80+
81+
struct lll_event *ull_prepare_enqueue(lll_is_abort_cb_t is_abort_cb,
82+
lll_abort_cb_t abort_cb,
83+
struct lll_prepare_param *prepare_param,
84+
lll_prepare_cb_t prepare_cb,
85+
uint8_t is_resume)
86+
{
87+
struct lll_event *e;
88+
void **next;
89+
90+
/* Allocate lll_event */
91+
next = mem_acquire(&pipeline.mem.free);
92+
if (!next) {
93+
return NULL;
94+
}
95+
96+
e = (void *)((uint8_t *)next + sizeof(void *));
97+
98+
memcpy(&e->prepare_param, prepare_param, sizeof(e->prepare_param));
99+
e->prepare_cb = prepare_cb;
100+
e->is_abort_cb = is_abort_cb;
101+
e->abort_cb = abort_cb;
102+
e->is_resume = is_resume;
103+
e->is_aborted = 0U;
104+
105+
/* Enqueue lll_event */
106+
*next = NULL;
107+
if (pipeline.tail) {
108+
struct lll_event *e_curr;
109+
uint32_t diff;
110+
111+
/* Should the prepare be placed as the tail? */
112+
e_curr = (void *)((uint8_t *)pipeline.tail + sizeof(void *));
113+
diff = ticker_ticks_diff_get(prepare_param->ticks_at_expire,
114+
e_curr->prepare_param.ticks_at_expire);
115+
if (is_resume ||
116+
(!e_curr->is_aborted && !e_curr->is_resume &&
117+
((diff & BIT(HAL_TICKER_CNTR_MSBIT)) == 0U))) {
118+
*pipeline.tail = next;
119+
pipeline.tail = next;
120+
} else {
121+
/* Should the prepare be placed as the head? */
122+
e_curr = (void *)((uint8_t *)pipeline.head + sizeof(void *));
123+
diff = ticker_ticks_diff_get(e_curr->prepare_param.ticks_at_expire,
124+
prepare_param->ticks_at_expire);
125+
if (!e_curr->is_aborted &&
126+
(e_curr->is_resume ||
127+
(diff && ((diff & BIT(HAL_TICKER_CNTR_MSBIT)) == 0U)))) {
128+
*next = pipeline.head;
129+
pipeline.head = next;
130+
} else {
131+
void **prev;
132+
void **curr;
133+
134+
prev = NULL;
135+
curr = pipeline.head;
136+
e_curr = (void *)((uint8_t *)curr + sizeof(void *));
137+
do {
138+
if (!e_curr->is_aborted && !e_curr->is_resume) {
139+
prev = curr;
140+
}
141+
142+
curr = *curr;
143+
if (!curr) {
144+
break;
145+
}
146+
147+
e_curr = (void *)((uint8_t *)curr + sizeof(void *));
148+
diff = ticker_ticks_diff_get(
149+
prepare_param->ticks_at_expire,
150+
e_curr->prepare_param.ticks_at_expire);
151+
} while (!e_curr->is_resume &&
152+
(e_curr->is_aborted ||
153+
((diff & BIT(HAL_TICKER_CNTR_MSBIT)) == 0U)));
154+
155+
if (!prev) {
156+
*next = pipeline.head;
157+
pipeline.head = next;
158+
if (!*next) {
159+
pipeline.tail = next;
160+
}
161+
} else {
162+
*next = *prev;
163+
*prev = next;
164+
if (!*next) {
165+
pipeline.tail = next;
166+
}
167+
}
168+
}
169+
}
170+
} else {
171+
pipeline.head = next;
172+
pipeline.tail = next;
173+
}
174+
175+
return e;
176+
}
177+
178+
void *ull_prepare_dequeue_get(void)
179+
{
180+
void *e;
181+
182+
/* peak lll_event */
183+
if (pipeline.head) {
184+
e = (uint8_t *)pipeline.head + sizeof(void *);
185+
} else {
186+
e = NULL;
187+
}
188+
189+
return e;
190+
}
191+
192+
void *ull_prepare_dequeue_iter(void **idx)
193+
{
194+
void *e;
195+
196+
/* Start at the head */
197+
if (!*idx) {
198+
*idx = pipeline.head;
199+
}
200+
201+
/* No more in the list */
202+
if (!*idx) {
203+
return NULL;
204+
}
205+
206+
/* Peak lll_event */
207+
e = (uint8_t *)*idx + sizeof(void *);
208+
209+
/* Proceed to next */
210+
*idx = *((void **)*idx);
211+
212+
return e;
213+
}
214+
215+
void ull_prepare_dequeue(uint8_t caller_id)
216+
{
217+
/* For testing, we just need a stub implementation
218+
* Full implementation would require mayfly, ticker, etc.
219+
*/
220+
(void)caller_id;
221+
}

0 commit comments

Comments
 (0)