Skip to content

nrf: fix internal flash writes #1661

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 89 additions & 73 deletions locale/ID.po

Large diffs are not rendered by default.

162 changes: 89 additions & 73 deletions locale/circuitpython.pot

Large diffs are not rendered by default.

162 changes: 89 additions & 73 deletions locale/de_DE.po

Large diffs are not rendered by default.

162 changes: 89 additions & 73 deletions locale/en_US.po

Large diffs are not rendered by default.

162 changes: 89 additions & 73 deletions locale/en_x_pirate.po

Large diffs are not rendered by default.

162 changes: 89 additions & 73 deletions locale/es.po

Large diffs are not rendered by default.

162 changes: 89 additions & 73 deletions locale/fil.po

Large diffs are not rendered by default.

162 changes: 89 additions & 73 deletions locale/fr.po

Large diffs are not rendered by default.

162 changes: 89 additions & 73 deletions locale/it_IT.po

Large diffs are not rendered by default.

162 changes: 89 additions & 73 deletions locale/pt_BR.po

Large diffs are not rendered by default.

35 changes: 23 additions & 12 deletions ports/nrf/bluetooth/ble_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,16 @@

nrf_nvic_state_t nrf_nvic_state = { 0 };

// Flag indicating progress of internal flash operation.
sd_flash_operation_status_t sd_flash_operation_status;

__attribute__((aligned(4)))
static uint8_t m_ble_evt_buf[sizeof(ble_evt_t) + (BLE_GATT_ATT_MTU_DEFAULT)];

void ble_drv_reset() {
// Linked list items will be gc'd.
MP_STATE_VM(ble_drv_evt_handler_entries) = NULL;
sd_flash_operation_status = SD_FLASH_OPERATION_DONE;
}

void ble_drv_add_event_handler(ble_drv_evt_handler_t func, void *param) {
Expand Down Expand Up @@ -85,22 +89,29 @@ extern void tusb_hal_nrf_power_event (uint32_t event);
void SD_EVT_IRQHandler(void) {
uint32_t evt_id;
while (sd_evt_get(&evt_id) != NRF_ERROR_NOT_FOUND) {
// sd_evt_handler(evt_id);

switch (evt_id) {
// usb power event
case NRF_EVT_POWER_USB_DETECTED:
case NRF_EVT_POWER_USB_POWER_READY:
case NRF_EVT_POWER_USB_REMOVED: {
int32_t usbevt = (evt_id == NRF_EVT_POWER_USB_DETECTED ) ? NRFX_POWER_USB_EVT_DETECTED:
(evt_id == NRF_EVT_POWER_USB_POWER_READY) ? NRFX_POWER_USB_EVT_READY :
(evt_id == NRF_EVT_POWER_USB_REMOVED ) ? NRFX_POWER_USB_EVT_REMOVED : -1;

tusb_hal_nrf_power_event(usbevt);
}
case NRF_EVT_POWER_USB_DETECTED:
case NRF_EVT_POWER_USB_POWER_READY:
case NRF_EVT_POWER_USB_REMOVED: {
int32_t usbevt = (evt_id == NRF_EVT_POWER_USB_DETECTED ) ? NRFX_POWER_USB_EVT_DETECTED:
(evt_id == NRF_EVT_POWER_USB_POWER_READY) ? NRFX_POWER_USB_EVT_READY :
(evt_id == NRF_EVT_POWER_USB_REMOVED ) ? NRFX_POWER_USB_EVT_REMOVED : -1;

tusb_hal_nrf_power_event(usbevt);
}
break;

default: break;
// Set flag indicating that a flash operation has finished.
case NRF_EVT_FLASH_OPERATION_SUCCESS:
sd_flash_operation_status = SD_FLASH_OPERATION_DONE;
break;
case NRF_EVT_FLASH_OPERATION_ERROR:
sd_flash_operation_status = SD_FLASH_OPERATION_ERROR;
break;

default:
break;
}
}

Expand Down
9 changes: 9 additions & 0 deletions ports/nrf/bluetooth/ble_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@

typedef void (*ble_drv_evt_handler_t)(ble_evt_t*, void*);

typedef enum {
SD_FLASH_OPERATION_DONE,
SD_FLASH_OPERATION_IN_PROGRESS,
SD_FLASH_OPERATION_ERROR,
} sd_flash_operation_status_t;

// Flag indicating progress of internal flash operation.
extern sd_flash_operation_status_t sd_flash_operation_status;

typedef struct ble_drv_evt_handler_entry {
struct ble_drv_evt_handler_entry *next;
void *param;
Expand Down
2 changes: 1 addition & 1 deletion ports/nrf/nrfx
Submodule nrfx updated 232 files
84 changes: 52 additions & 32 deletions ports/nrf/supervisor/internal_flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "nrf_nvmc.h"

#ifdef BLUETOOTH_SD
#include "ble_drv.h"
#include "nrf_sdm.h"
#endif

Expand Down Expand Up @@ -71,26 +72,15 @@ uint32_t supervisor_flash_get_block_count(void) {
}

#ifdef BLUETOOTH_SD
STATIC bool wait_for_flash_operation(void) {
do {
STATIC void sd_flash_operation_start(void) {
sd_flash_operation_status = SD_FLASH_OPERATION_IN_PROGRESS;
}

STATIC sd_flash_operation_status_t sd_flash_operation_wait_until_done(void) {
while (sd_flash_operation_status == SD_FLASH_OPERATION_IN_PROGRESS) {
sd_app_evt_wait();
uint32_t evt_id;
uint32_t result = sd_evt_get(&evt_id);
if (result == NRF_SUCCESS) {
switch (evt_id) {
case NRF_EVT_FLASH_OPERATION_SUCCESS:
return true;

case NRF_EVT_FLASH_OPERATION_ERROR:
return false;

default:
// Some other event. Wait for a flash event.
continue;
}
}
return false;
} while (true);
}
return sd_flash_operation_status;
}
#endif

Expand All @@ -101,27 +91,55 @@ void supervisor_flash_flush(void) {
if (memcmp(_flash_cache, (void *)_flash_page_addr, FL_PAGE_SZ) != 0) {

#ifdef BLUETOOTH_SD
uint8_t sd_en = 0;
(void) sd_softdevice_is_enabled(&sd_en);

if (sd_en) {
sd_flash_page_erase(_flash_page_addr / FL_PAGE_SZ);
wait_for_flash_operation(); // TODO: handle error return.
sd_flash_write((uint32_t *)_flash_page_addr, (uint32_t *)_flash_cache, FL_PAGE_SZ / sizeof(uint32_t));
wait_for_flash_operation();
} else {
uint8_t sd_en = 0;
(void) sd_softdevice_is_enabled(&sd_en);

if (sd_en) {
uint32_t err_code;
sd_flash_operation_status_t status;

sd_flash_operation_start();
err_code = sd_flash_page_erase(_flash_page_addr / FL_PAGE_SZ);
if (err_code != NRF_SUCCESS) {
mp_raise_OSError_msg_varg(translate("Flash erase failed to start, err 0x%04x"), err_code);
}
status = sd_flash_operation_wait_until_done();
if (status == SD_FLASH_OPERATION_ERROR) {
mp_raise_OSError_msg(translate("Flash erase failed"));
}

// Divide a full page into parts, because writing a full page causes an assertion failure.
// See https://devzone.nordicsemi.com/f/nordic-q-a/40088/sd_flash_write-cause-nrf_fault_id_sd_assert/
const size_t BLOCK_PARTS = 2;
size_t words_to_write = FL_PAGE_SZ / sizeof(uint32_t) / BLOCK_PARTS;
for (size_t i = 0; i < BLOCK_PARTS; i++) {
sd_flash_operation_start();
err_code = sd_flash_write(((uint32_t *)_flash_page_addr) + i * words_to_write,
(uint32_t *)_flash_cache + i * words_to_write,
words_to_write);
if (err_code != NRF_SUCCESS) {
mp_raise_OSError_msg_varg(translate("Flash write failed to start, err 0x%04x"), err_code);
}
status = sd_flash_operation_wait_until_done();
if (status == SD_FLASH_OPERATION_ERROR) {
mp_raise_OSError_msg(translate("Flash write failed"));
}
}
} else {
#endif
nrf_nvmc_page_erase(_flash_page_addr);
nrf_nvmc_write_words(_flash_page_addr, (uint32_t *)_flash_cache, FL_PAGE_SZ / sizeof(uint32_t));
nrf_nvmc_page_erase(_flash_page_addr);
nrf_nvmc_write_words(_flash_page_addr, (uint32_t *)_flash_cache, FL_PAGE_SZ / sizeof(uint32_t));
#ifdef BLUETOOTH_SD
}
}
#endif

_flash_page_addr = NO_CACHE;
}
_flash_page_addr = NO_CACHE;
}

mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num_blocks) {
// Must write out anything in cache before trying to read.
supervisor_flash_flush();
uint32_t src = lba2addr(block);
memcpy(dest, (uint8_t*) src, FILESYSTEM_BLOCK_SIZE*num_blocks);
return 0; // success
Expand All @@ -139,9 +157,11 @@ mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t lba, uint32
supervisor_flash_flush();

_flash_page_addr = page_addr;
// Copy the current contents of the entire page into the cache.
memcpy(_flash_cache, (void *)page_addr, FL_PAGE_SZ);
}

// Overwrite part or all of the page cache with the src data.
memcpy(_flash_cache + (addr & (FL_PAGE_SZ - 1)), src, count * FILESYSTEM_BLOCK_SIZE);

// adjust for next run
Expand Down