How to jump into app from bootloader ,52833?

I wrote a bootloader code. The flash space range of bootloader is 0x27000-0x3b000, and the flash space of app is 0x3b000-0x80000, but the app doesn't work. What's the problem?

My project consists of STM32 + 4G + nrf52833. When the 52833 firmware needs to be updated, the cloud service will send the 52833 firmware to STM32, and then STM32 will send the firmware to 52833 through the UART interface.

sdk:nRF5_SDK_17.0.2_d674dde

The flash distribution framework is as follows:

 bootloader:

typedef  void (*iapfun)(void);				
#define FLASH_APP1_ADDR		0x3B000			//app code start address
iapfun jump2app;
__asm void MSR_MSP(uint32_t addr) 
{
	MSR MSP, r0 							//set Main Stack value
	BX r14
}

//Jump to application segment
//appxaddr:app code start address
void iap_load_app(uint32_t appxaddr)
{
	jump2app=(iapfun)*(uint32_t*)(appxaddr+4);			//The second word in the user code area is the program start address (reset address)	

	#if 1
		MSR_MSP(*(uint32_t*)appxaddr);					//Initialize the app stack pointer ,(the first word in the user code area is
	#else												//used to store the stack top address)
		__set_MSP(appxaddr);
	#endif
	
	jump2app();									    	//jump to APP.
}		 


timer_out_st timer_period;
void handle_period_event(void)
{
	static uint32_t jump_to_app_timer = 0, pir_detect_ok_num = 0;
	static uint8_t dataW,dataR;
	if(!IsTimeOut(&timer_period)) return;
	TimeOutSet(&timer_period,10);
	
	mcu_led_set();

	if(++jump_to_app_timer > 300)
	{
		jump_to_app_timer=0;
	
		{	 
			printf("jump to app,0x3B000=%08x\n",*(uint32_t*)(FLASH_APP1_ADDR));
			nrf_delay_ms(100);

			// Turn off the peripherals used 
			uart_close(0);
			uart_close(1);
			sk_timer_set(0);
			iap_load_app(FLASH_APP1_ADDR);						
		}

		// This information will not be printed if it works properly
		printf("***err to jump app\n");
	}
}

app:

SCB->VTOR =  0x3B000;				// remap interrupt vector table address

  • Hi,

    Normally the SoftDevice assumes that the application is located immediately after the SoftDevice. It is possible to locate the application elsewhere though, but in that case you need to Configure the SoftDevice to forward interrupts properly (just jumping to the application like it seems you do is not enough). Please see this post for details. Note that interrupts must go via SoftDevice, so using VTOR will not work.

  • In the app code, after disabling the functions related to ble, jump from bootload to app, and it can work.

    But with the related functions enabled, it won't work anymore.

    What's the problem?

    app main code:

    /**@brief Application main function.
     */
    int main(void)
    {
    	ret_code_t ret;
        bool erase_bonds;
    	
    	gpio_output_voltage_setup_3v3();
    	
    	SCB->VTOR =  0x3B000;				// remap interrupt vector table address
    	
    	NRF_UICR->NFCPINS = 0; 				//config NFC to GPIO mode
    	uart_app_init(1000000);
     	UART_Init();
        log_init();
    
    	ret = nrf_drv_clock_init();
    	APP_ERROR_CHECK(ret);
    	nrf_drv_clock_lfclk_request(NULL);
    
    
    	timers_init();
    
    #if 0 									// If this part of the code is enabled, it will not run
    	power_management_init();
    	ble_stack_init();
    	
    	gap_params_init();
    	gatt_init();
    	services_init();
    	advertising_init();
    	conn_params_init();
    	// Start execution.
    	printf("\r\nUART started.\r\n");
    	NRF_LOG_INFO("Debug logging for UART over RTT started.");
    	advertising_start();
    #endif
    
    	sk_timer_init();
    	sk_timer_set(1);
    
    	printf("---app --\n");
    
        for (;;)
        {	
    		handle_period_event();
        }
    }
    
    

  • can23 said:

    In the app code, after disabling the functions related to ble, jump from bootload to app, and it can work.

    But with the related functions enabled, it won't work anymore.

    What's the problem?

    In this part you enable the SoftDevice, and if you have not changed the way you start your application like I suggested (like not using VTOR) this will fail. You need to do as suggested in the post I linked to in my previous post when you use a SoftDevice.

  • hi,

    thanks for your reply!

    This problem has puzzled me for several days. I read your post. My code is as follows. How to use SD_ MBR_ COMMAND_ IRQ_ FORWARD_ ADDRESS_ Set (nrf_dfu_mbr_irq_forward_address_set()) to set interrupt forwarding?

    sdk is nRF5_SDK_17.0.2

    chip:52833

    bootloader code:

    typedef  void (*iapfun)(void);				
    #define FLASH_APP1_ADDR		0x3B000			//app code start address
    iapfun jump2app;
    __asm void MSR_MSP(uint32_t addr) 
    {
    	MSR MSP, r0 							//set Main Stack value
    	BX r14
    }
    
    //Jump to application segment
    //appxaddr:app code start address
    void iap_load_app(uint32_t appxaddr)
    {
    	jump2app=(iapfun)*(uint32_t*)(appxaddr+4);			//The second word in the user code area is the program start address (reset address)	
    
    	#if 0
    		MSR_MSP(*(uint32_t*)appxaddr);					//Initialize the app stack pointer ,(the first word in the user code area is
    	#else												//used to store the stack top address)
    		__set_MSP(appxaddr);
    	#endif
    	
    	jump2app();									    	//jump to APP.
    }		 
    
    
    /**@brief Function that sets the stack pointer and starts executing a particular address.
     *
     * @param[in]  new_msp  The new value to set in the main stack pointer.
     * @param[in]  addr     The address to execute.
     */
    void jump_to_addr(uint32_t new_msp, uint32_t addr)
    {
        __set_MSP(new_msp);
        ((void (*)(void))addr)();
    }
    
    
    // After 3 seconds, jump to app
    void handle_period_event(void)
    {
    	static uint32_t jump_to_app_timer = 0;
    
    
    	if(++jump_to_app_timer > 300)
    	{
    		jump_to_app_timer=0;
    	
    		{	 
    			printf("jump to app,0x3B000=%08x\n",*(uint32_t*)(FLASH_APP1_ADDR));
    			nrf_delay_ms(100);
    
    			// Turn off the peripherals used 
    			uart_close(0);
    			uart_close(1);
    			sk_timer_set(0);
    
    			#if 1
    				// Disable and clear interrupts
    				const uint32_t current_isr_num = (__get_IPSR() & IPSR_ISR_Msk);
    				const uint32_t new_msp		   = *((uint32_t *)(FLASH_APP1_ADDR));					// The app's Stack Pointer is found as the first word of the vector table.
    				const uint32_t reset_handler   = *((uint32_t *)(FLASH_APP1_ADDR + sizeof(uint32_t))); // The app's Reset Handler is found as the second word of the vector table.
    
    
    				__set_CONTROL(0x00000000);   // Set CONTROL to its reset value 0.
    			    __set_PRIMASK(0x00000000);   // Set PRIMASK to its reset value 0.
    			    __set_BASEPRI(0x00000000);   // Set BASEPRI to its reset value 0.
    			    __set_FAULTMASK(0x00000000); // Set FAULTMASK to its reset value 0.
    
    	
    			    NVIC->ICER[0]=0xFFFFFFFF;
    			    NVIC->ICPR[0]=0xFFFFFFFF;
    			    NVIC->ICER[1]=0xFFFFFFFF;
    			    NVIC->ICPR[1]=0xFFFFFFFF;
    
    ////				 ASSERT(current_isr_num == 0); // If this is triggered, the CPU is currently in an interrupt.
    
    			    // The CPU is in Thread mode (main context).
    			    jump_to_addr(new_msp, reset_handler); // Jump directly to the App's Reset Handler.
    			#else
    				iap_load_app(FLASH_APP1_ADDR);	
    			#endif
    		}
    
    		// This information will not be printed if it works properly
    		printf("***err to jump app\n");
    	}
    }
    
    
    
    
    
    
    **@brief Application main function.
     */
    int main(void)
    {
    	ret_code_t ret;
        bool erase_bonds;
    	
    	NRF_UICR->NFCPINS = 0; 				//config NFC to GPIO mode
    
    	gpio_output_voltage_setup_3v3();
    
    	uart_app_init(1000000);
     	UART_Init();
    	
        log_init();
    
    	ret = nrf_drv_clock_init();
    	APP_ERROR_CHECK(ret);
    	nrf_drv_clock_lfclk_request(NULL);
    
    	printf("---bootloader--\n");
    	printf("---SCB->VTOR=%08x--\n",SCB->VTOR);
    
        for (;;)
        {
            nrf_delay_ms(10);
    
    		handle_period_event();
        }
    }

    app code:

    
    
    
    // Print a string of information indicating that the app works
    void handle_period_event(void)
    {
    	static uint32_t printf_period = 0, printf_num = 0;
    
    	printf_period++;
    	if(printf_period > 100)
    	{
    		printf_period = 0;
    
    		printf_num++;
    		printf("[%s][%d] app num =%d\n",__func__,__LINE__,printf_num);
    	}
    
    }
    
    /**@brief Application main function.
     */
    int main(void)
    {
    	ret_code_t ret;
        bool erase_bonds;
    	
    	gpio_output_voltage_setup_3v3();
    	
    	SCB->VTOR =  0x3B000;				// remap interrupt vector table address
    	
    	NRF_UICR->NFCPINS = 0; 				//config NFC to GPIO mode
    	uart_app_init(1000000);
     	UART_Init();
        log_init();
    
    	ret = nrf_drv_clock_init();
    	APP_ERROR_CHECK(ret);
    	nrf_drv_clock_lfclk_request(NULL);
    
    #if 1 									// If this part of the code is enabled, it will not run
    	power_management_init();
    	ble_stack_init();
    	
    	gap_params_init();
    	gatt_init();
    	services_init();
    	advertising_init();
    	conn_params_init();
    	// Start execution.
    	printf("\r\nUART started.\r\n");
    	NRF_LOG_INFO("Debug logging for UART over RTT started.");
    	advertising_start();
    #endif
    
    	printf("---app --\n");
    
        for (;;)
        {	
            nrf_delay_ms(10);
    		handle_period_event();
        }
    }
    
    

    thanks!

  • The way you jump to your application looks fine, but before you do this you must configure interrupt forwarding in the SoftDevice. What you need to do here is essentially what is done by nrf_bootloader_app_start() in <SDK14.2>\components\libraries\bootloader\nrf_bootloader_app_start.c, so I suggest you download SDK 14.2 and look at that (just for reference, as this specific part is done differently in a way that does not fit your needs in SDK >= 15.0.0). Essentially you need to do exactly the same.

Related