Skip to content

Commit 8008227

Browse files
authored
Merge pull request #6124 from marcuschangarm/nrf52_flash_fix
Make NRF52 flash work with SoftDevice
2 parents 45b4062 + 0a1cae9 commit 8008227

File tree

2 files changed

+105
-21
lines changed

2 files changed

+105
-21
lines changed

targets/TARGET_NORDIC/TARGET_NRF5/flash_api.c

Lines changed: 104 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,79 +36,163 @@
3636
*
3737
*/
3838

39-
#include "flash_api.h"
39+
#if DEVICE_FLASH
40+
41+
#include "hal/flash_api.h"
42+
#include "hal/lp_ticker_api.h"
43+
44+
#include "nrf_drv_common.h"
4045
#include "nrf_nvmc.h"
4146
#include "nrf_soc.h"
42-
#include "nrf_sdm.h"
4347

44-
#if DEVICE_FLASH
48+
#define WORD_WRITE_TIMEOUT_US (1 * 1000) // Max. value from datasheet: 338 us
49+
#define PAGE_ERASE_TIMEOUT_US (200 * 1000) // Max. value from datasheet: 89.7 ms
50+
51+
/* Macro for testing if the SoftDevice is active, regardless of whether the
52+
* application is build with the SoftDevice or not.
53+
*/
54+
#if defined(SOFTDEVICE_PRESENT)
55+
#include "nrf_sdm.h"
56+
static uint8_t wrapper(void) {
57+
uint8_t softdevice_is_enabled;
58+
ret_code_t result = sd_softdevice_is_enabled(&softdevice_is_enabled);
59+
return ((result == NRF_SUCCESS) && (softdevice_is_enabled == 1));
60+
}
61+
#define NRF_HAL_SD_IS_ENABLED() wrapper()
62+
#else
63+
#define NRF_HAL_SD_IS_ENABLED() 0
64+
#endif
4565

4666
int32_t flash_init(flash_t *obj)
4767
{
4868
(void)(obj);
49-
uint8_t sd_enabled;
50-
if ((sd_softdevice_is_enabled(&sd_enabled) == NRF_SUCCESS) && sd_enabled == 1) {
51-
return -1;
69+
70+
/* Initialize low power ticker. Used for timeouts. */
71+
static bool first_init = true;
72+
73+
if (first_init) {
74+
first_init = false;
75+
lp_ticker_init();
5276
}
77+
5378
return 0;
5479
}
5580

5681
int32_t flash_free(flash_t *obj)
5782
{
5883
(void)(obj);
84+
5985
return 0;
6086
}
6187

6288
int32_t flash_erase_sector(flash_t *obj, uint32_t address)
6389
{
6490
(void)(obj);
65-
uint8_t sd_enabled;
66-
if ((sd_softdevice_is_enabled(&sd_enabled) == NRF_SUCCESS) && sd_enabled == 1) {
67-
return -1;
91+
92+
/* Return value defaults to error. */
93+
uint32_t result = NRF_ERROR_BUSY;
94+
95+
if (NRF_HAL_SD_IS_ENABLED()) {
96+
97+
/* Convert address to page number. */
98+
uint32_t page_number = address / NRF_FICR->CODEPAGESIZE;
99+
100+
/* Setup stop watch for timeout. */
101+
uint32_t start_us = lp_ticker_read();
102+
uint32_t now_us = start_us;
103+
104+
/* Retry if flash is busy until timeout is reached. */
105+
while (((now_us - start_us) < PAGE_ERASE_TIMEOUT_US) &&
106+
(result == NRF_ERROR_BUSY)) {
107+
108+
result = sd_flash_page_erase(page_number);
109+
110+
/* Read timeout timer. */
111+
now_us = lp_ticker_read();
112+
}
113+
114+
} else {
115+
116+
/* Raw API doesn't return error code, assume success. */
117+
nrf_nvmc_page_erase(address);
118+
result = NRF_SUCCESS;
68119
}
69-
nrf_nvmc_page_erase(address);
70-
return 0;
120+
121+
/* Convert Nordic error code to mbed HAL error code. */
122+
return (result == NRF_SUCCESS) ? 0 : -1;
71123
}
72124

73125
int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size)
74126
{
75-
uint8_t sd_enabled;
76-
if ((sd_softdevice_is_enabled(&sd_enabled) == NRF_SUCCESS) && sd_enabled == 1) {
77-
return -1;
127+
(void)(obj);
128+
129+
/* Return value defaults to error. */
130+
uint32_t result = NRF_ERROR_BUSY;
131+
132+
/* Convert size to words. */
133+
uint32_t words = size / sizeof(uint32_t);
134+
135+
if (NRF_HAL_SD_IS_ENABLED()) {
136+
137+
/* Setup stop watch for timeout. */
138+
uint32_t start_us = lp_ticker_read();
139+
uint32_t now_us = start_us;
140+
141+
/* Retry if flash is busy until timeout is reached. */
142+
while (((now_us - start_us) < (words * WORD_WRITE_TIMEOUT_US)) &&
143+
(result == NRF_ERROR_BUSY)) {
144+
145+
result = sd_flash_write((uint32_t *) address, (const uint32_t *) data, words);
146+
147+
/* Read timeout timer. */
148+
now_us = lp_ticker_read();
149+
}
150+
151+
} else {
152+
/* We will use *_words function to speed up flashing code. Word means 32bit -> 4B
153+
* or sizeof(uint32_t).
154+
*/
155+
nrf_nvmc_write_words(address, (const uint32_t *) data, words);
156+
result = NRF_SUCCESS;
78157
}
79-
/* We will use *_words function to speed up flashing code. Word means 32bit -> 4B
80-
* or sizeof(uint32_t).
81-
*/
82-
nrf_nvmc_write_words(address, (const uint32_t *) data, (size / sizeof(uint32_t)));
83-
return 0;
158+
159+
/* Convert Nordic error code to mbed HAL error code. */
160+
return (result == NRF_SUCCESS) ? 0 : -1;
84161
}
85162

86163
uint32_t flash_get_size(const flash_t *obj)
87164
{
88165
(void)(obj);
166+
89167
/* Just count flash size. */
90168
return NRF_FICR->CODESIZE * NRF_FICR->CODEPAGESIZE;
91169
}
92170

93171
uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address)
94172
{
95173
(void)(obj);
174+
96175
/* Test if passed address is in flash space. */
97176
if (address < flash_get_size(obj)) {
98177
return NRF_FICR->CODEPAGESIZE;
99178
}
179+
100180
/* Something goes wrong, return invalid size error code. */
101181
return MBED_FLASH_INVALID_SIZE;
102182
}
103183

104184
uint32_t flash_get_page_size(const flash_t *obj)
105185
{
106186
(void)(obj);
107-
return NRF_FICR->CODEPAGESIZE;
187+
188+
/* Return minimum writeable size. Note that this is different from the erase page size. */
189+
return 4;
108190
}
109191

110192
uint32_t flash_get_start_address(const flash_t *obj)
111193
{
194+
(void)(obj);
195+
112196
return 0;
113197
}
114198

targets/targets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3471,7 +3471,7 @@
34713471
"supported_form_factors": ["ARDUINO"],
34723472
"inherits": ["MCU_NRF52"],
34733473
"macros_add": ["BOARD_PCA10040", "NRF52_PAN_12", "NRF52_PAN_15", "NRF52_PAN_58", "NRF52_PAN_55", "NRF52_PAN_54", "NRF52_PAN_31", "NRF52_PAN_30", "NRF52_PAN_51", "NRF52_PAN_36", "NRF52_PAN_53", "S132", "CONFIG_GPIO_AS_PINRESET", "BLE_STACK_SUPPORT_REQD", "SWI_DISABLE0", "NRF52_PAN_20", "NRF52_PAN_64", "NRF52_PAN_62", "NRF52_PAN_63"],
3474-
"device_has_add": ["ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"],
3474+
"device_has_add": ["ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "FLASH"],
34753475
"release_versions": ["2", "5"],
34763476
"device_name": "nRF52832_xxAA"
34773477
},

0 commit comments

Comments
 (0)