38
38
#include "nrf_nvmc.h"
39
39
40
40
#ifdef BLUETOOTH_SD
41
+ #include "ble_drv.h"
41
42
#include "nrf_sdm.h"
42
43
#endif
43
44
@@ -71,26 +72,15 @@ uint32_t supervisor_flash_get_block_count(void) {
71
72
}
72
73
73
74
#ifdef BLUETOOTH_SD
74
- STATIC bool wait_for_flash_operation (void ) {
75
- do {
75
+ STATIC void sd_flash_operation_start (void ) {
76
+ sd_flash_operation_status = SD_FLASH_OPERATION_IN_PROGRESS ;
77
+ }
78
+
79
+ STATIC sd_flash_operation_status_t sd_flash_operation_wait_until_done (void ) {
80
+ while (sd_flash_operation_status == SD_FLASH_OPERATION_IN_PROGRESS ) {
76
81
sd_app_evt_wait ();
77
- uint32_t evt_id ;
78
- uint32_t result = sd_evt_get (& evt_id );
79
- if (result == NRF_SUCCESS ) {
80
- switch (evt_id ) {
81
- case NRF_EVT_FLASH_OPERATION_SUCCESS :
82
- return true;
83
-
84
- case NRF_EVT_FLASH_OPERATION_ERROR :
85
- return false;
86
-
87
- default :
88
- // Some other event. Wait for a flash event.
89
- continue ;
90
- }
91
- }
92
- return false;
93
- } while (true);
82
+ }
83
+ return sd_flash_operation_status ;
94
84
}
95
85
#endif
96
86
@@ -101,27 +91,55 @@ void supervisor_flash_flush(void) {
101
91
if (memcmp (_flash_cache , (void * )_flash_page_addr , FL_PAGE_SZ ) != 0 ) {
102
92
103
93
#ifdef BLUETOOTH_SD
104
- uint8_t sd_en = 0 ;
105
- (void ) sd_softdevice_is_enabled (& sd_en );
106
-
107
- if (sd_en ) {
108
- sd_flash_page_erase (_flash_page_addr / FL_PAGE_SZ );
109
- wait_for_flash_operation (); // TODO: handle error return.
110
- sd_flash_write ((uint32_t * )_flash_page_addr , (uint32_t * )_flash_cache , FL_PAGE_SZ / sizeof (uint32_t ));
111
- wait_for_flash_operation ();
112
- } else {
94
+ uint8_t sd_en = 0 ;
95
+ (void ) sd_softdevice_is_enabled (& sd_en );
96
+
97
+ if (sd_en ) {
98
+ uint32_t err_code ;
99
+ sd_flash_operation_status_t status ;
100
+
101
+ sd_flash_operation_start ();
102
+ err_code = sd_flash_page_erase (_flash_page_addr / FL_PAGE_SZ );
103
+ if (err_code != NRF_SUCCESS ) {
104
+ mp_raise_OSError_msg_varg (translate ("Flash erase failed to start, err 0x%04x" ), err_code );
105
+ }
106
+ status = sd_flash_operation_wait_until_done ();
107
+ if (status == SD_FLASH_OPERATION_ERROR ) {
108
+ mp_raise_OSError_msg (translate ("Flash erase failed" ));
109
+ }
110
+
111
+ // Divide a full page into parts, because writing a full page causes an assertion failure.
112
+ // See https://devzone.nordicsemi.com/f/nordic-q-a/40088/sd_flash_write-cause-nrf_fault_id_sd_assert/
113
+ const size_t BLOCK_PARTS = 2 ;
114
+ size_t words_to_write = FL_PAGE_SZ / sizeof (uint32_t ) / BLOCK_PARTS ;
115
+ for (size_t i = 0 ; i < BLOCK_PARTS ; i ++ ) {
116
+ sd_flash_operation_start ();
117
+ err_code = sd_flash_write (((uint32_t * )_flash_page_addr ) + i * words_to_write ,
118
+ (uint32_t * )_flash_cache + i * words_to_write ,
119
+ words_to_write );
120
+ if (err_code != NRF_SUCCESS ) {
121
+ mp_raise_OSError_msg_varg (translate ("Flash write failed to start, err 0x%04x" ), err_code );
122
+ }
123
+ status = sd_flash_operation_wait_until_done ();
124
+ if (status == SD_FLASH_OPERATION_ERROR ) {
125
+ mp_raise_OSError_msg (translate ("Flash write failed" ));
126
+ }
127
+ }
128
+ } else {
113
129
#endif
114
- nrf_nvmc_page_erase (_flash_page_addr );
115
- nrf_nvmc_write_words (_flash_page_addr , (uint32_t * )_flash_cache , FL_PAGE_SZ / sizeof (uint32_t ));
130
+ nrf_nvmc_page_erase (_flash_page_addr );
131
+ nrf_nvmc_write_words (_flash_page_addr , (uint32_t * )_flash_cache , FL_PAGE_SZ / sizeof (uint32_t ));
116
132
#ifdef BLUETOOTH_SD
117
- }
133
+ }
118
134
#endif
119
135
120
- _flash_page_addr = NO_CACHE ;
121
136
}
137
+ _flash_page_addr = NO_CACHE ;
122
138
}
123
139
124
140
mp_uint_t supervisor_flash_read_blocks (uint8_t * dest , uint32_t block , uint32_t num_blocks ) {
141
+ // Must write out anything in cache before trying to read.
142
+ supervisor_flash_flush ();
125
143
uint32_t src = lba2addr (block );
126
144
memcpy (dest , (uint8_t * ) src , FILESYSTEM_BLOCK_SIZE * num_blocks );
127
145
return 0 ; // success
@@ -139,9 +157,11 @@ mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t lba, uint32
139
157
supervisor_flash_flush ();
140
158
141
159
_flash_page_addr = page_addr ;
160
+ // Copy the current contents of the entire page into the cache.
142
161
memcpy (_flash_cache , (void * )page_addr , FL_PAGE_SZ );
143
162
}
144
163
164
+ // Overwrite part or all of the page cache with the src data.
145
165
memcpy (_flash_cache + (addr & (FL_PAGE_SZ - 1 )), src , count * FILESYSTEM_BLOCK_SIZE );
146
166
147
167
// adjust for next run
0 commit comments