Skip to content

Commit ed2d1f5

Browse files
committed
Allow failure; refactoring
1 parent 0ebb9e9 commit ed2d1f5

File tree

1 file changed

+46
-76
lines changed

1 file changed

+46
-76
lines changed

libraries/InternalFileSytem/src/flash/flash_nrf5x.c

Lines changed: 46 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@
2828
#include "nrf_soc.h"
2929
#include "delay.h"
3030
#include "rtos.h"
31-
#include "assert.h"
32-
3331

3432
#ifdef NRF52840_XXAA
3533
#define BOOTLOADER_ADDR 0xF4000
@@ -59,6 +57,34 @@ void flash_nrf5x_event_cb (uint32_t event)
5957
}
6058
}
6159

60+
// How many retry attempts when performing flash write operations
61+
#define MAX_RETRY 20
62+
63+
// Check whether a flash operation was successful, or should be repeated
64+
static bool retry_flash_op (uint32_t op_result, bool sd_enabled) {
65+
// If busy
66+
if (op_result == NRF_ERROR_BUSY) {
67+
delay(1);
68+
return true; // Retry
69+
}
70+
71+
// Unspecified error
72+
if (op_result != NRF_SUCCESS)
73+
return true; // Retry
74+
75+
// If the soft device is enabled, flash operations run async
76+
// The callback (flash_nrf5x_event_cb) will give semaphore when the flash operation is complete
77+
// The callback also checks for NRF_EVT_FLASH_OPERATION_ERROR, which is not available to us otherwise
78+
if (sd_enabled) {
79+
xSemaphoreTake(_sem, portMAX_DELAY);
80+
if (_flash_op_failed)
81+
return true; // Retry
82+
}
83+
84+
// Success
85+
return false;
86+
}
87+
6288
// Flash Abstraction Layer
6389
static bool fal_erase (uint32_t addr);
6490
static uint32_t fal_program (uint32_t dst, void const * src, uint32_t len);
@@ -124,31 +150,13 @@ static bool fal_erase (uint32_t addr)
124150
uint8_t sd_en = 0;
125151
(void) sd_softdevice_is_enabled(&sd_en);
126152

127-
// Make multiple attempts
128-
for (uint8_t attempt = 0;;) {
129-
// Attempt to erase
130-
uint32_t err = sd_flash_page_erase(addr / FLASH_NRF52_PAGE_SIZE);
131-
// Retry if busy
132-
if (err == NRF_ERROR_BUSY) {
133-
delay(1);
134-
continue;
135-
}
136-
// Count genuine attempts
137-
attempt++;
138-
// If using softdevice, erase is async, so we wait here
139-
if (sd_en) xSemaphoreTake(_sem, portMAX_DELAY);
140-
// If erase failed
141-
if (_flash_op_failed) {
142-
assert(attempt < 10); // Something went horribly wrong.. protect the flash
143-
continue; // Try again
144-
}
145-
// Catch any other odd results
146-
VERIFY_STATUS(err, 0);
147-
// Success
148-
break;
153+
// Make multiple attempts to erase
154+
uint8_t attempt = 0;
155+
while (retry_flash_op(sd_flash_page_erase(addr / FLASH_NRF52_PAGE_SIZE), sd_en)) {
156+
if (++attempt > MAX_RETRY)
157+
return false; // Failure
149158
}
150-
151-
return true;
159+
return true; // Success
152160
}
153161

154162
static uint32_t fal_program (uint32_t dst, void const * src, uint32_t len)
@@ -164,63 +172,25 @@ static uint32_t fal_program (uint32_t dst, void const * src, uint32_t len)
164172
// https://devzone.nordicsemi.com/f/nordic-q-a/40088/sd_flash_write-cause-nrf_fault_id_sd_assert
165173
// Workaround: write half page at a time.
166174
#if NRF52832_XXAA
167-
while ( NRF_ERROR_BUSY == (err = sd_flash_write((uint32_t*) dst, (uint32_t const *) src, len/4)) )
168-
{
169-
delay(1);
175+
uint8_t attempt = 0;
176+
while (retry_flash_op(sd_flash_write((uint32_t*) dst, (uint32_t const *) src, len/4), sd_en)) {
177+
if (++attempt > MAX_RETRY)
178+
return 0; // Failure
170179
}
171-
VERIFY_STATUS(err, 0);
172-
173-
if ( sd_en ) xSemaphoreTake(_sem, portMAX_DELAY);
174180
#else
175181

176182
// First part of block
177-
// ------------------
178-
for (uint8_t attempt = 0;;) {
179-
// Attempt to write
180-
uint32_t err = sd_flash_write((uint32_t*) dst, (uint32_t const *) src, len/8);
181-
// Retry if busy
182-
if (err == NRF_ERROR_BUSY) {
183-
delay(1);
184-
continue;
185-
}
186-
// Count genuine attempts
187-
attempt++;
188-
// If using softdevice, write is async, so we wait here
189-
if (sd_en) xSemaphoreTake(_sem, portMAX_DELAY);
190-
// If write failed
191-
if (_flash_op_failed) {
192-
assert(attempt < 10); // Something went horribly wrong.. protect the flash
193-
continue; // Try again
194-
}
195-
// Catch any other odd results
196-
VERIFY_STATUS(err, 0);
197-
// Success
198-
break;
183+
uint8_t attempt = 0;
184+
while (retry_flash_op(sd_flash_write((uint32_t*) dst, (uint32_t const *) src, len/8), sd_en)) {
185+
if (++attempt > MAX_RETRY)
186+
return 0; // Failure
199187
}
200188

201189
// Second part of block
202-
// --------------------
203-
for (uint8_t attempt = 0;;) {
204-
// Attempt to write
205-
uint32_t err = sd_flash_write((uint32_t*) (dst+ len/2), (uint32_t const *) (src + len/2), len/8);
206-
// Retry if busy
207-
if (err == NRF_ERROR_BUSY) {
208-
delay(1);
209-
continue;
210-
}
211-
// Count genuine attempts
212-
attempt++;
213-
// If using softdevice, write is async, so we wait here
214-
if (sd_en) xSemaphoreTake(_sem, portMAX_DELAY);
215-
// If write failed
216-
if (_flash_op_failed) {
217-
assert(attempt < 10); // Something went horribly wrong.. protect the flash
218-
continue; // Try again
219-
}
220-
// Catch any other odd results
221-
VERIFY_STATUS(err, 0);
222-
// Success
223-
break;
190+
attempt = 0;
191+
while (retry_flash_op(sd_flash_write((uint32_t*) (dst+ len/2), (uint32_t const *) (src + len/2), len/8), sd_en)) {
192+
if (++attempt > MAX_RETRY)
193+
return 0; // Failure
224194
}
225195
#endif
226196

0 commit comments

Comments
 (0)