mirror of
https://github.com/oltaco/Adafruit_nRF52_Bootloader_OTAFIX.git
synced 2026-10-15 15:31:01 +00:00
Wait until FLASH operation queue has enough available room, instead of silently dropping operations
This commit is contained in:
@@ -186,10 +186,34 @@ static void bootloader_settings_save(bootloader_settings_t * p_settings)
|
||||
{
|
||||
if ( is_ota() )
|
||||
{
|
||||
uint32_t err_code = pstorage_clear(&m_bootsettings_handle, sizeof(bootloader_settings_t));
|
||||
uint32_t err_code;
|
||||
while(1) {
|
||||
err_code = pstorage_clear(&m_bootsettings_handle, sizeof(bootloader_settings_t));
|
||||
if (err_code != NRF_ERROR_NO_MEM)
|
||||
break;
|
||||
// This means the write/erase queue of commands was completely full - Should not
|
||||
// happen, but better safe than sorry, wait until space becomes available -
|
||||
// the pstorage event handler is only run from the main loop, and we are also
|
||||
// running from a BLE event on the main loop: This means if we wait here, the FLASH
|
||||
// completion events will never be handled (will be queued by app_scheduler, but
|
||||
// not handled, and that means this wait will never end... So, process SOC events
|
||||
// from the SD (but NOT BLE events!) - This will free entries on the pstorage queue
|
||||
// as soon as operations are complete, allowing this op to be queued
|
||||
while (NRF_ERROR_NOT_FOUND != proc_soc()) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
err_code = pstorage_store(&m_bootsettings_handle, (uint8_t *) p_settings, sizeof(bootloader_settings_t), 0);
|
||||
while(1) {
|
||||
err_code = pstorage_store(&m_bootsettings_handle, (uint8_t *) p_settings, sizeof(bootloader_settings_t), 0);
|
||||
if (err_code != NRF_ERROR_NO_MEM)
|
||||
break;
|
||||
// No space, wait until an entry in the queue is freed
|
||||
while (NRF_ERROR_NOT_FOUND != proc_soc()) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -92,6 +92,8 @@ uint32_t bootloader_dfu_sd_update_finalize(void);
|
||||
|
||||
void bootloader_mbr_addrs_populate(void);
|
||||
|
||||
extern uint32_t proc_soc(void);
|
||||
|
||||
#endif // BOOTLOADER_H__
|
||||
|
||||
/**@} */
|
||||
|
||||
@@ -82,7 +82,6 @@ static void pstorage_callback_handler(pstorage_handle_t * p_handle,
|
||||
APP_ERROR_CHECK(result);
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling the DFU timeout.
|
||||
*
|
||||
* @param[in] p_context The timeout context.
|
||||
@@ -136,19 +135,28 @@ static void dfu_prepare_func_app_erase(uint32_t image_size)
|
||||
// Doing a SoftDevice update thus current application must be cleared to ensure enough space
|
||||
// for new SoftDevice.
|
||||
m_dfu_state = DFU_STATE_PREPARING;
|
||||
|
||||
if ( is_ota() )
|
||||
{
|
||||
uint32_t err_code = pstorage_clear(&m_storage_handle_app, m_image_size);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
flash_nrf5x_erase(DFU_BANK_0_REGION_START, m_image_size);
|
||||
|
||||
if ( is_ota() )
|
||||
{
|
||||
uint32_t err_code;
|
||||
while(1) {
|
||||
err_code = pstorage_clear(&m_storage_handle_app, m_image_size);
|
||||
if (err_code != NRF_ERROR_NO_MEM)
|
||||
break;
|
||||
// No space, wait until an entry in the queue is freed
|
||||
while (NRF_ERROR_NOT_FOUND != proc_soc()) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
flash_nrf5x_erase(DFU_BANK_0_REGION_START, m_image_size);
|
||||
|
||||
// invoke complete callback
|
||||
pstorage_callback_handler(&m_storage_handle_app, PSTORAGE_CLEAR_OP_CODE, NRF_SUCCESS, NULL, 0);
|
||||
}
|
||||
// invoke complete callback
|
||||
pstorage_callback_handler(&m_storage_handle_app, PSTORAGE_CLEAR_OP_CODE, NRF_SUCCESS, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -163,19 +171,28 @@ static void dfu_prepare_func_swap_erase(uint32_t image_size)
|
||||
mp_storage_handle_active = &m_storage_handle_swap;
|
||||
|
||||
m_dfu_state = DFU_STATE_PREPARING;
|
||||
|
||||
if ( is_ota() )
|
||||
{
|
||||
uint32_t err_code = pstorage_clear(&m_storage_handle_swap, image_size);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
flash_nrf5x_erase(DFU_BANK_1_REGION_START, image_size);
|
||||
|
||||
if ( is_ota() )
|
||||
{
|
||||
uint32_t err_code;
|
||||
while(1) {
|
||||
err_code = pstorage_clear(&m_storage_handle_swap, image_size);
|
||||
if (err_code != NRF_ERROR_NO_MEM)
|
||||
break;
|
||||
// No space, wait until an entry in the queue is freed
|
||||
while (NRF_ERROR_NOT_FOUND != proc_soc()) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
flash_nrf5x_erase(DFU_BANK_1_REGION_START, image_size);
|
||||
|
||||
// invoke complete callback
|
||||
pstorage_callback_handler(&m_storage_handle_swap, PSTORAGE_CLEAR_OP_CODE, NRF_SUCCESS, NULL, 0);
|
||||
}
|
||||
// invoke complete callback
|
||||
pstorage_callback_handler(&m_storage_handle_swap, PSTORAGE_CLEAR_OP_CODE, NRF_SUCCESS, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -263,26 +280,45 @@ static uint32_t dfu_activate_app(void)
|
||||
uint32_t err_code = NRF_SUCCESS;
|
||||
|
||||
// Erase BANK 0.
|
||||
if ( is_ota() )
|
||||
{
|
||||
err_code = pstorage_clear(&m_storage_handle_app, m_start_packet.app_image_size);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
err_code = pstorage_store(&m_storage_handle_app,
|
||||
(uint8_t *)m_storage_handle_swap.block_id,
|
||||
m_start_packet.app_image_size,
|
||||
0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( is_ota() )
|
||||
{
|
||||
while(1) {
|
||||
err_code = pstorage_clear(&m_storage_handle_app, m_start_packet.app_image_size);
|
||||
if (err_code != NRF_ERROR_NO_MEM)
|
||||
break;
|
||||
// No space, wait until an entry in the queue is freed
|
||||
while (NRF_ERROR_NOT_FOUND != proc_soc()) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
while(1) {
|
||||
err_code = pstorage_store(&m_storage_handle_app,
|
||||
(uint8_t *)m_storage_handle_swap.block_id,
|
||||
m_start_packet.app_image_size,
|
||||
0);
|
||||
|
||||
if (err_code != NRF_ERROR_NO_MEM)
|
||||
break;
|
||||
// No space, wait until an entry in the queue is freed
|
||||
while (NRF_ERROR_NOT_FOUND != proc_soc()) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
flash_nrf5x_erase(DFU_BANK_0_REGION_START, m_start_packet.app_image_size);
|
||||
pstorage_callback_handler(&m_storage_handle_app, PSTORAGE_CLEAR_OP_CODE, NRF_SUCCESS, NULL, 0);
|
||||
|
||||
|
||||
flash_nrf5x_write(DFU_BANK_0_REGION_START, (uint8_t *)DFU_BANK_1_REGION_START, m_start_packet.app_image_size, false);
|
||||
flash_nrf5x_flush(false);
|
||||
flash_nrf5x_flush(false);
|
||||
pstorage_callback_handler(&m_storage_handle_app, PSTORAGE_STORE_OP_CODE, NRF_SUCCESS, (uint8_t *) DFU_BANK_1_REGION_START, m_start_packet.app_image_size);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (err_code == NRF_SUCCESS)
|
||||
{
|
||||
dfu_update_status_t update_status = { 0 };
|
||||
@@ -430,13 +466,13 @@ uint32_t dfu_start_pkt_handle(dfu_update_packet_t * p_packet)
|
||||
}
|
||||
|
||||
if ( DFU_STATE_IDLE != m_dfu_state )
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
|
||||
// Valid peer activity detected. Hence restart the DFU timer.
|
||||
err_code = dfu_timer_restart();
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
m_functions.prepare(m_image_size);
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
|
||||
// Valid peer activity detected. Hence restart the DFU timer.
|
||||
err_code = dfu_timer_restart();
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
m_functions.prepare(m_image_size);
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
@@ -486,17 +522,25 @@ uint32_t dfu_data_pkt_handle(dfu_update_packet_t * p_packet)
|
||||
|
||||
if ( is_ota() )
|
||||
{
|
||||
err_code = pstorage_store(mp_storage_handle_active, (uint8_t *)p_data, data_length, m_data_received);
|
||||
VERIFY_SUCCESS(err_code);
|
||||
while(1) {
|
||||
err_code = pstorage_store(mp_storage_handle_active, (uint8_t *)p_data, data_length, m_data_received);
|
||||
if (err_code != NRF_ERROR_NO_MEM)
|
||||
break;
|
||||
// No space, wait until an entry in the queue is freed
|
||||
while (NRF_ERROR_NOT_FOUND != proc_soc()) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
VERIFY_SUCCESS(err_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
flash_nrf5x_write(
|
||||
(mp_storage_handle_active == &m_storage_handle_app
|
||||
? DFU_BANK_0_REGION_START
|
||||
: DFU_BANK_1_REGION_START)
|
||||
+ m_data_received, p_data, data_length, false);
|
||||
pstorage_callback_handler(mp_storage_handle_active, PSTORAGE_STORE_OP_CODE, NRF_SUCCESS, (uint8_t *) p_data, data_length);
|
||||
flash_nrf5x_write(
|
||||
(mp_storage_handle_active == &m_storage_handle_app
|
||||
? DFU_BANK_0_REGION_START
|
||||
: DFU_BANK_1_REGION_START)
|
||||
+ m_data_received, p_data, data_length, false);
|
||||
pstorage_callback_handler(mp_storage_handle_active, PSTORAGE_STORE_OP_CODE, NRF_SUCCESS, (uint8_t *) p_data, data_length);
|
||||
}
|
||||
|
||||
m_data_received += data_length;
|
||||
@@ -508,8 +552,8 @@ uint32_t dfu_data_pkt_handle(dfu_update_packet_t * p_packet)
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !is_ota() ) flash_nrf5x_flush(false);
|
||||
|
||||
if ( !is_ota() ) flash_nrf5x_flush(false);
|
||||
|
||||
// The entire image has been received. Return NRF_SUCCESS.
|
||||
err_code = NRF_SUCCESS;
|
||||
}
|
||||
@@ -561,7 +605,7 @@ uint32_t dfu_init_pkt_handle(dfu_update_packet_t * p_packet)
|
||||
case DFU_STATE_RDY:
|
||||
m_dfu_state = DFU_STATE_RX_INIT_PKT;
|
||||
// When receiving init packet in state ready just update and fall through this case.
|
||||
/* FALLTHRU */
|
||||
/* FALLTHRU */
|
||||
|
||||
case DFU_STATE_RX_INIT_PKT:
|
||||
// DFU initialization has been done and a start packet has been received.
|
||||
@@ -811,7 +855,7 @@ uint32_t dfu_bl_image_swap(void)
|
||||
uint32_t dfu_bl_image_validate(void)
|
||||
{
|
||||
bootloader_settings_t bootloader_settings;\
|
||||
|
||||
|
||||
sd_mbr_command_t sd_mbr_cmd_1;
|
||||
sd_mbr_command_t sd_mbr_cmd_2;
|
||||
|
||||
@@ -829,6 +873,10 @@ uint32_t dfu_bl_image_validate(void)
|
||||
sd_mbr_cmd_1.params.compare.ptr2 = (uint32_t *)(bl_image_start_1);
|
||||
sd_mbr_cmd_1.params.compare.len = bootloader_settings.bl_image_size / sizeof(uint32_t);
|
||||
|
||||
uint32_t err_code = sd_mbr_command(&sd_mbr_cmd_1);
|
||||
if (err_code == NRF_SUCCESS)
|
||||
return NRF_SUCCESS;
|
||||
|
||||
uint32_t bl_image_start_2 = (bootloader_settings.sd_image_size == 0) ?
|
||||
DFU_BANK_1_REGION_START :
|
||||
bootloader_settings.sd_image_start +
|
||||
@@ -839,7 +887,7 @@ uint32_t dfu_bl_image_validate(void)
|
||||
sd_mbr_cmd_2.params.compare.ptr2 = (uint32_t *)(bl_image_start_2);
|
||||
sd_mbr_cmd_2.params.compare.len = bootloader_settings.bl_image_size / sizeof(uint32_t);
|
||||
|
||||
return sd_mbr_command(&sd_mbr_cmd_1) && sd_mbr_command(&sd_mbr_cmd_2);
|
||||
return sd_mbr_command(&sd_mbr_cmd_2);
|
||||
}
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
@@ -863,7 +911,7 @@ uint32_t dfu_sd_image_validate(void)
|
||||
uint32_t block_size = (bootloader_settings.sd_image_start - sd_start) / 2;
|
||||
uint32_t image_end = bootloader_settings.sd_image_start +
|
||||
bootloader_settings.sd_image_size;
|
||||
|
||||
|
||||
/* ##### FIX START ##### */
|
||||
block_size &= ~(uint32_t)(CODE_PAGE_SIZE - 1);
|
||||
/* ##### FIX END ##### */
|
||||
|
||||
@@ -140,7 +140,16 @@ static void dfu_prepare_func_app_erase(uint32_t image_size)
|
||||
|
||||
if ( is_ota() )
|
||||
{
|
||||
uint32_t err_code = pstorage_clear(&m_storage_handle_app, m_image_size);
|
||||
uint32_t err_code;
|
||||
while(1) {
|
||||
err_code = pstorage_clear(&m_storage_handle_app, m_image_size);
|
||||
if (err_code != NRF_ERROR_NO_MEM)
|
||||
break;
|
||||
// No space, wait until an entry in the queue is freed
|
||||
while (NRF_ERROR_NOT_FOUND != proc_soc()) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
else
|
||||
@@ -414,7 +423,15 @@ uint32_t dfu_data_pkt_handle(dfu_update_packet_t * p_packet)
|
||||
|
||||
if ( is_ota() )
|
||||
{
|
||||
err_code = pstorage_store(mp_storage_handle_active, (uint8_t *)p_data, data_length, m_data_received);
|
||||
while(1) {
|
||||
err_code = pstorage_store(mp_storage_handle_active, (uint8_t *)p_data, data_length, m_data_received);
|
||||
if (err_code != NRF_ERROR_NO_MEM)
|
||||
break;
|
||||
// No space, wait until an entry in the queue is freed
|
||||
while (NRF_ERROR_NOT_FOUND != proc_soc()) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
VERIFY_SUCCESS(err_code);
|
||||
}
|
||||
else
|
||||
@@ -742,6 +759,17 @@ uint32_t dfu_bl_image_validate(void)
|
||||
|
||||
if (bootloader_settings.bl_image_size != 0)
|
||||
{
|
||||
/*
|
||||
* The problem with updating the bootloader from a dual to single bank bootloader is that the new
|
||||
* bootloader expects the firmware image to be at the start of BANK 0, while it's actually loaded
|
||||
* to BANK1 by the old bootloader. After the update the new single bank bootloader verifies that
|
||||
* the image was correctly written to flash by comparing itself with the firmware image that it
|
||||
* expects to be located in BANK0. Since the actual firmware image is in BANK 1 this check will
|
||||
* fail and the new bootloader updates itself with whatever data located in BANK0 using the MBR.
|
||||
|
||||
* The fix is to modify the dfu_bl_image_validate() function in dfu_single_bank.c run verification
|
||||
* on both addresses (BANK0 and BANK1)
|
||||
*/
|
||||
uint32_t bl_image_start_1 = (bootloader_settings.sd_image_size == 0) ?
|
||||
DFU_BANK_0_REGION_START :
|
||||
bootloader_settings.sd_image_start +
|
||||
@@ -752,6 +780,10 @@ uint32_t dfu_bl_image_validate(void)
|
||||
sd_mbr_cmd_1.params.compare.ptr2 = (uint32_t *)(bl_image_start_1);
|
||||
sd_mbr_cmd_1.params.compare.len = bootloader_settings.bl_image_size / sizeof(uint32_t);
|
||||
|
||||
uint32_t err_code = sd_mbr_command(&sd_mbr_cmd_1);
|
||||
if (err_code == NRF_SUCCESS)
|
||||
return NRF_SUCCESS;
|
||||
|
||||
uint32_t bl_image_start_2 = (bootloader_settings.sd_image_size == 0) ?
|
||||
DFU_BANK_1_REGION_START :
|
||||
bootloader_settings.sd_image_start +
|
||||
@@ -762,7 +794,7 @@ uint32_t dfu_bl_image_validate(void)
|
||||
sd_mbr_cmd_2.params.compare.ptr2 = (uint32_t *)(bl_image_start_2);
|
||||
sd_mbr_cmd_2.params.compare.len = bootloader_settings.bl_image_size / sizeof(uint32_t);
|
||||
|
||||
return sd_mbr_command(&sd_mbr_cmd_1) && sd_mbr_command(&sd_mbr_cmd_2);
|
||||
return sd_mbr_command(&sd_mbr_cmd_2);
|
||||
}
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ static __INLINE uint32_t pstorage_flash_page_end()
|
||||
#define PSTORAGE_SWAP_ADDR PSTORAGE_DATA_END_ADDR
|
||||
|
||||
#define PSTORAGE_MAX_BLOCK_SIZE PSTORAGE_FLASH_PAGE_SIZE /**< Maximum size of block that can be registered with the module. Should be configured based on system requirements. And should be greater than or equal to the minimum size. */
|
||||
#define PSTORAGE_CMD_QUEUE_SIZE 10 /**< Maximum number of flash access commands that can be maintained by the module for all applications. Configurable. */
|
||||
#define PSTORAGE_CMD_QUEUE_SIZE 18 /**< Maximum number of flash access commands that can be maintained by the module for all applications. Configurable. */
|
||||
|
||||
/**@breif Define this flag in case Raw access to persistent memory is to be enabled. Raw mode
|
||||
* unlike the data mode is for uses other than storing data from various mode. This mode is
|
||||
|
||||
Reference in New Issue
Block a user