Hi,
I'm facing the following issue when trying to use the DFU bootloader. Below you can find the code of the bootloader, which I flash after I erase everything, flash S110 soft device and then the bootloader.
I start nrf toolbox in iOS and I choose my firmware, I see my device advertising as DfuTarg, I select, upload, and then I get a vague error "DFU - operation failed".
I then enabled RTT to see what's going on and I observed that I enter bootloader_dfu_start(), but then, when I try to upload the firmware the function ASSERTS (you can see app_error_handler getting triggered) and reboots.
I've tried different firmwares (custom and the ones provided as examples) and I always see the same behaviour.
Question is, how do I investigate further? Any clues will be highly appreciated.
Thanks
Details Softdevice: S110 DFU botloader: Single bank BLE
Source code
#if BUTTONS_NUMBER < 1
#error "Not enough buttons on board"
#endif
#if LEDS_NUMBER < 1
#error "Not enough LEDs on board"
#endif
#define IS_SRVC_CHANGED_CHARACT_PRESENT 1 /**< Include the service_changed characteristic. For DFU this should normally be the case. */
#define BOOTLOADER_BUTTON BSP_BUTTON_3 /**< Button used to enter SW update mode. */
#define UPDATE_IN_PROGRESS_LED BSP_LED_2 /**< Led used to indicate that DFU is active. */
#define APP_TIMER_PRESCALER 0 /**< Value of the RTC1 PRESCALER register. */
#define APP_TIMER_OP_QUEUE_SIZE 4 /**< Size of timer operation queues. */
#define SCHED_MAX_EVENT_DATA_SIZE MAX(APP_TIMER_SCHED_EVT_SIZE, 0) /**< Maximum size of scheduler events. */
#define SCHED_QUEUE_SIZE 20 /**< Maximum number of events in the scheduler queue. */
void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
{
app_error_handler(0xDEADBEEF, line_num, p_file_name);
}
/**@brief Function for initialization of LEDs.
*/
static void leds_init(void)
{
nrf_gpio_range_cfg_output(LED_START, LED_STOP);
nrf_gpio_pins_set(LEDS_MASK);
}
/**@brief Function for initializing the timer handler module (app_timer).
*/
static void timers_init(void)
{
// Initialize timer module, making it use the scheduler.
APP_TIMER_APPSH_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, true);
}
static void buttons_init(void)
{
nrf_gpio_cfg_sense_input(BOOTLOADER_BUTTON,
BUTTON_PULL,
NRF_GPIO_PIN_SENSE_LOW);
}
static void sys_evt_dispatch(uint32_t event)
{
pstorage_sys_event_handler(event);
}
static void ble_stack_init(bool init_softdevice)
{
uint32_t err_code;
sd_mbr_command_t com = {SD_MBR_COMMAND_INIT_SD, };
if (init_softdevice)
{
err_code = sd_mbr_command(&com);
APP_ERROR_CHECK(err_code);
}
SEGGER_RTT_WriteString(0, "ble_stack_init: A\n");
err_code = sd_softdevice_vector_table_base_set(BOOTLOADER_REGION_START);
APP_ERROR_CHECK(err_code);
SEGGER_RTT_WriteString(0, "ble_stack_init: B\n");
//SOFTDEVICE_HANDLER_APPSH_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, true);
SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_RC_250_PPM_4000MS_CALIBRATION, false);
SEGGER_RTT_WriteString(0, "ble_stack_init: C\n");
// Enable BLE stack
ble_enable_params_t ble_enable_params;
memset(&ble_enable_params, 0, sizeof(ble_enable_params));
// Below code line is needed for s130. For s110 is inrrelevant - but executable
// can run with both s130 and s110.
ble_enable_params.gatts_enable_params.attr_tab_size = BLE_GATTS_ATTR_TAB_SIZE_DEFAULT;
ble_enable_params.gatts_enable_params.service_changed = IS_SRVC_CHANGED_CHARACT_PRESENT;
err_code = sd_ble_enable(&ble_enable_params);
APP_ERROR_CHECK(err_code);
err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch);
APP_ERROR_CHECK(err_code);
}
static void scheduler_init(void)
{
APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
}
void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name) {
SEGGER_RTT_WriteString(0, "ERROR....\n");
}
int main(void)
{
uint32_t err_code;
bool dfu_start = false;
bool app_reset = (NRF_POWER->GPREGRET == BOOTLOADER_DFU_START);
if (app_reset)
{
NRF_POWER->GPREGRET = 0;
}
leds_init();
// This check ensures that the defined fields in the bootloader corresponds with actual
// setting in the nRF51 chip.
APP_ERROR_CHECK_BOOL(*((uint32_t *)NRF_UICR_BOOT_START_ADDRESS) == BOOTLOADER_REGION_START);
APP_ERROR_CHECK_BOOL(NRF_FICR->CODEPAGESIZE == CODE_PAGE_SIZE);
// Initialize.
timers_init();
buttons_init();
(void)bootloader_init();
if (bootloader_dfu_sd_in_progress())
{
nrf_gpio_pin_clear(UPDATE_IN_PROGRESS_LED);
err_code = bootloader_dfu_sd_update_continue();
APP_ERROR_CHECK(err_code);
ble_stack_init(!app_reset);
scheduler_init();
err_code = bootloader_dfu_sd_update_finalize();
APP_ERROR_CHECK(err_code);
nrf_gpio_pin_set(UPDATE_IN_PROGRESS_LED);
}
else
{
// If stack is present then continue initialization of bootloader.
ble_stack_init(!app_reset);
scheduler_init();
}
if (bootloader_app_is_valid(DFU_BANK_0_REGION_START))
{
SEGGER_RTT_WriteString(0, "Application found....\n");
} else {
SEGGER_RTT_WriteString(0, "Application not found....\n");
}
dfu_start = app_reset;
dfu_start |= ((nrf_gpio_pin_read(BOOTLOADER_BUTTON) == 0) ? true: false);
SEGGER_RTT_WriteString(0, "Yow ...\n");
if (dfu_start || (!bootloader_app_is_valid(DFU_BANK_0_REGION_START)))
{
SEGGER_RTT_WriteString(0, "DFU A ...\n");
// Initiate an update of the firmware.
SEGGER_RTT_WriteString(0, "DFU B ...\n");
err_code = bootloader_dfu_start();
SEGGER_RTT_WriteString(0, "DFU C ...\n");
if (err_code != NRF_SUCCESS) SEGGER_RTT_WriteString(0, "DFU error ...\n");
APP_ERROR_CHECK(err_code);
SEGGER_RTT_WriteString(0, "DFU D ...\n");
}
if (bootloader_app_is_valid(DFU_BANK_0_REGION_START) && !bootloader_dfu_sd_in_progress())
{
// Select a bank region to use as application region.
// @note: Only applications running from DFU_BANK_0_REGION_START is supported.
bootloader_app_start(DFU_BANK_0_REGION_START);
}
NVIC_SystemReset();
}
Output
ble_stack_init: A
ble_stack_init: B
ble_stack_init: C
Application not found....
Yow ...
DFU A ...
DFU B ...
ERROR....
ERROR....
ERROR....
ERROR....
ERROR....
ERROR....
ERROR....
ERROR....
ERROR....
ERROR....
ERROR....
ERROR....
ERROR....
ERROR....
ERROR....
ERROR....
ble_stack_init: A
ble_stack_init: B
ble_stack_init: C
Application not found....
Yow ...
DFU A ...
DFU B ...