Skip to content

Commit 011d888

Browse files
cvinayakgmarull
authored andcommitted
[nrf fromlist] drivers: flash: nrf: Fix ticker stop synchronization
Fix usage fault due to spurious ticker timeout expiry post enqueuing of ticker stop operation. Use ticker operation callback to handle completion of ticker stop operation and then give the semaphore to thread to notifying the completion of flash operation. Signed-off-by: Vinayak Kariappa Chettimada <[email protected]> (cherry picked from commit d6b567ccffea4d65708896d12ffbcd463cabeb60) Signed-off-by: Vinayak Kariappa Chettimada <[email protected]>
1 parent 300f3bd commit 011d888

File tree

1 file changed

+59
-30
lines changed

1 file changed

+59
-30
lines changed

drivers/flash/soc_flash_nrf_ticker.c

Lines changed: 59 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,37 @@ struct ticker_sync_context {
3535

3636
static struct ticker_sync_context _ticker_sync_context;
3737

38-
3938
/* semaphore for synchronization of flash operations */
4039
static struct k_sem sem_sync;
4140

42-
static inline int _ticker_stop(uint8_t inst_idx, uint8_t u_id, uint8_t tic_id)
41+
static void ticker_stop_work_cb(uint32_t status, void *param)
4342
{
44-
int ret = ticker_stop(inst_idx, u_id, tic_id, NULL, NULL);
43+
__ASSERT((status == TICKER_STATUS_SUCCESS ||
44+
status == TICKER_STATUS_FAILURE),
45+
"Failed to stop work ticker, ticker job busy.\n");
4546

46-
if (ret != TICKER_STATUS_SUCCESS &&
47-
ret != TICKER_STATUS_BUSY) {
48-
__ASSERT(0, "Failed to stop ticker.\n");
49-
}
47+
/* notify thread that data is available */
48+
k_sem_give(&sem_sync);
49+
}
50+
51+
static void ticker_stop_prepare_cb(uint32_t status, void *param)
52+
{
53+
uint8_t instance_index;
54+
uint8_t ticker_id;
55+
uint32_t ret;
56+
57+
__ASSERT(status == TICKER_STATUS_SUCCESS,
58+
"Failed to stop prepare ticker.\n");
5059

51-
return ret;
60+
/* Get the ticker instance and ticker id for flash operations */
61+
ll_timeslice_ticker_id_get(&instance_index, &ticker_id);
62+
63+
/* Stop the work ticker, from ULL_LOW context */
64+
ret = ticker_stop(instance_index, 2U, (ticker_id + 1U),
65+
ticker_stop_work_cb, NULL);
66+
__ASSERT((ret == TICKER_STATUS_SUCCESS ||
67+
ret == TICKER_STATUS_BUSY),
68+
"Failed to request the work ticker to stop.\n");
5269
}
5370

5471
static void time_slot_callback_work(uint32_t ticks_at_expire,
@@ -58,8 +75,6 @@ static void time_slot_callback_work(uint32_t ticks_at_expire,
5875
void *context)
5976
{
6077
struct flash_op_desc *op_desc;
61-
uint8_t instance_index;
62-
uint8_t ticker_id;
6378
int rc;
6479

6580
__ASSERT(ll_radio_state_is_idle(),
@@ -68,15 +83,21 @@ static void time_slot_callback_work(uint32_t ticks_at_expire,
6883
op_desc = context;
6984
rc = op_desc->handler(op_desc->context);
7085
if (rc != FLASH_OP_ONGOING) {
86+
uint8_t instance_index;
87+
uint8_t ticker_id;
88+
uint32_t ret;
89+
90+
/* Get the ticker instance and ticker id for flash operations */
7191
ll_timeslice_ticker_id_get(&instance_index, &ticker_id);
7292

73-
/* Stop the time slot ticker */
74-
_ticker_stop(instance_index, 0, ticker_id);
93+
/* Stop the prepare ticker, from ULL_HIGH context */
94+
ret = ticker_stop(instance_index, 0U, ticker_id,
95+
ticker_stop_prepare_cb, NULL);
96+
__ASSERT((ret == TICKER_STATUS_SUCCESS ||
97+
ret == TICKER_STATUS_BUSY),
98+
"Failed to stop ticker.\n");
7599

76100
_ticker_sync_context.result = (rc == FLASH_OP_DONE) ? 0 : rc;
77-
78-
/* notify thread that data is available */
79-
k_sem_give(&sem_sync);
80101
}
81102
}
82103

@@ -85,15 +106,16 @@ static void time_slot_delay(uint32_t ticks_at_expire, uint32_t ticks_delay,
85106
{
86107
uint8_t instance_index;
87108
uint8_t ticker_id;
88-
int err;
109+
uint32_t ret;
89110

111+
/* Get the ticker instance and ticker id for flash operations */
90112
ll_timeslice_ticker_id_get(&instance_index, &ticker_id);
91113

92-
/* start a secondary one-shot ticker after ticks_delay,
114+
/* Start a secondary one-shot ticker after ticks_delay,
93115
* this will let any radio role to gracefully abort and release the
94116
* Radio h/w.
95117
*/
96-
err = ticker_start(instance_index, /* Radio instance ticker */
118+
ret = ticker_start(instance_index, /* Radio instance ticker */
97119
1, /* user id for link layer ULL_HIGH */
98120
/* (MAYFLY_CALL_ID_WORKER) */
99121
(ticker_id + 1), /* ticker_id */
@@ -109,14 +131,16 @@ static void time_slot_delay(uint32_t ticks_at_expire, uint32_t ticks_delay,
109131
NULL, /* no op callback */
110132
NULL);
111133

112-
if (err != TICKER_STATUS_SUCCESS && err != TICKER_STATUS_BUSY) {
134+
if (ret != TICKER_STATUS_SUCCESS && ret != TICKER_STATUS_BUSY) {
135+
/* Failed to enqueue the ticker start operation request */
113136
_ticker_sync_context.result = 0;
114137

115-
/* abort flash timeslots */
116-
_ticker_stop(instance_index, 0, ticker_id);
117-
118-
/* notify thread that data is available */
119-
k_sem_give(&sem_sync);
138+
/* Abort flash prepare ticker, from ULL_HIGH context */
139+
ret = ticker_stop(instance_index, 0U, ticker_id,
140+
ticker_stop_prepare_cb, NULL);
141+
__ASSERT((ret == TICKER_STATUS_SUCCESS ||
142+
ret == TICKER_STATUS_BUSY),
143+
"Failed to stop ticker.\n");
120144
}
121145
}
122146

@@ -159,7 +183,6 @@ int nrf_flash_sync_init(void)
159183

160184
void nrf_flash_sync_set_context(uint32_t duration)
161185
{
162-
163186
/* FLASH_SYNC_SWITCHING_TIME is delay which is always added by
164187
* the slot calling mechanism
165188
*/
@@ -171,12 +194,14 @@ int nrf_flash_sync_exe(struct flash_op_desc *op_desc)
171194
{
172195
uint8_t instance_index;
173196
uint8_t ticker_id;
197+
uint32_t ret;
174198
int result;
175-
uint32_t err;
176199

200+
/* Get the ticker instance and ticker id for flash operations */
177201
ll_timeslice_ticker_id_get(&instance_index, &ticker_id);
178202

179-
err = ticker_start(instance_index,
203+
/* Start periodic flash operation prepare time slots */
204+
ret = ticker_start(instance_index,
180205
3, /* user id for thread mode */
181206
/* (MAYFLY_CALL_ID_PROGRAM) */
182207
ticker_id, /* flash ticker id */
@@ -194,11 +219,15 @@ int nrf_flash_sync_exe(struct flash_op_desc *op_desc)
194219
NULL, /* no op callback */
195220
NULL);
196221

197-
if (err != TICKER_STATUS_SUCCESS && err != TICKER_STATUS_BUSY) {
222+
if (ret != TICKER_STATUS_SUCCESS && ret != TICKER_STATUS_BUSY) {
223+
/* Failed to enqueue the ticker start operation request */
198224
result = -ECANCELED;
199225
} else if (k_sem_take(&sem_sync, K_MSEC(FLASH_TIMEOUT_MS)) != 0) {
200-
/* Stop any scheduled jobs */
201-
_ticker_stop(instance_index, 3, ticker_id);
226+
/* Stop any scheduled jobs, from thread context */
227+
ret = ticker_stop(instance_index, 3U, ticker_id, NULL, NULL);
228+
__ASSERT((ret == TICKER_STATUS_SUCCESS ||
229+
ret == TICKER_STATUS_BUSY),
230+
"Failed to stop ticker.\n");
202231

203232
/* wait for operation's complete overrun*/
204233
result = -ETIMEDOUT;

0 commit comments

Comments
 (0)