This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

bootloader_app_start() doesn't run newly flashed app

Hi,

i'm doing my own bootloader and i want to use external flash to download image trough a spi. Now it almost works. But after an app image has been successfully transferred to nrf52 flash and the bootloader reaches bootloader_app_start(DFU_BANK_0_REGION_START), the app is hanged. It seems the bootloader_app_start() works fine, crash occurred in the app at ble_stack_init(), but ONLY once after burning. Pin reset makes newly flashed app to run normal way. So i suppose something wrong in bootloader's SD init\deinit or wrong pstorage_store() callback handling.

My code flow:

static void dfu_cb_handler(uint32_t packet, uint32_t result, uint8_t * p_data)
{
	pstorage_is_busy = (result != NRF_SUCCESS);
}


// copied from bootloader.c\wait_for_events(void) 77
// this one used for wait pstorage_store() completion
static void pstorage_wait(void)
{
	pstorage_is_busy = true;
	while (pstorage_is_busy)
	{
		// Wait in low power state for any events.
		uint32_t err_code = sd_app_evt_wait();
		APP_ERROR_CHECK(err_code);
		// Event received. Process it from the scheduler.
		app_sched_execute();
	}
}

// END OF BOOTLOADER MAIN FUNC
if (dfu_start || (!bootloader_app_is_valid(DFU_BANK_0_REGION_START)))
{
	err_code = dfu_init();
	APP_ERROR_CHECK(err_code);
	FlashSpiInit();
	dfu_register_callback(dfu_cb_handler);
	start_data_process(FW_RST_APP_ADDRESS); // load start packet from external flash
	 // load init packet from external flash, uses pstorage_wait();
	init_data_process();
	// load image packet from external flash, uses pstorage_wait();
	app_data_process(); 
	err_code = dfu_image_validate();
	APP_ERROR_CHECK(err_code);
	err_code = dfu_image_activate();
	APP_ERROR_CHECK(err_code);
	wait_for_events();
}

if (bootloader_app_is_valid(DFU_BANK_0_REGION_START) && !bootloader_dfu_sd_in_progress())
{
    bootloader_app_start(DFU_BANK_0_REGION_START);
}

NVIC_SystemReset();

i use wait_for_events(); directly from example library bootloader.c (remove the static key).

Any help appreciated.

  • @Konstantin: Have you made sure you have disabled the softdevice, and forwarded the interrupt vector table to the application as we do in the bootloader_app_start() function. Make sure the return error code is checked.

    You can have a look at our example of SPI bootloader here.

  • Hi, Hung Bui I use bootloader_app_start() directly (see the end of code in my post). This function will not return as it does the things you mentioned and jump to an app entry point. I have seen SPI bootloader example, but my project have different structure since it is SPI master. The problem still exists, so i'm trying to debug my application code from the bootloader project.

  • @Konstantin: I just want to make sure you haven't modified the bootloader_app_start() function. You can test to debug your application and see what happens when you step through the application code when it inits.

    Do you use any extra timer/peripheral in the bootloader that can trigger an interrupt in the period when the bootloader is closing and branching to the application that would not be handled ?

  • The problem is solved. The source of bug was spi init\deinit procedure. The NRF_SPIM1 module is used by either bootloade and app, so spi deinit is necessary for bootloader, but calling nrf_drv_spi_uninit() it seems was not enough. Subsequent call of spi_init() in app hangs CPU. Adding manual spi event reset solves the problem.

    	FlashSpiReadStop();
    	nrf_drv_spi_uninit(&AuxSpi);
    	NRF_SPIM1->EVENTS_END = 0;
    	NRF_SPIM1->EVENTS_ENDRX = 0;
    	NRF_SPIM1->EVENTS_ENDTX = 0;
    	NRF_SPIM1->EVENTS_STARTED = 0;
    	NRF_SPIM1->EVENTS_STOPPED = 0;
    

    May be the same behavior should be added in nrf_drv_spi.c

Related