cancel
Showing results for 
Search instead for 
Did you mean: 

when jumping from bootloader to application the mcu stucks sometimes

HZaib.1
Associate III

MCU: STM32F411CEU6

 

So, I am having a weird issue. I created a bootloader for my application to accommodate OTA updates. Bootloader makes decision when it has new firmware inside external flash(the application code tells it), then bootloader loads that otherwise it simply jumps to existing firmware in internal flash. Now issue arise when it jumps to firmware for example I have simply given the command to my application code to reset the mcu, now the mcu goes to bootloader first and then bootloader makes the jump to the firmware in this the jump is successful sometimes and most of the time it fails and the mcu get stuck, and sometimes it keeps working perfectly 

 

now when I send the new firmware to application code it saves it into external flash and then resets it, the bootloader reads special header and so it knows that it needs to download new firmware to the mcu, so instead of jumping to internal flash firmware it erases it and loads the new firmware from external flash and then jumps to it, the success rate for this which I tested is almost 100per and the mcu never get stucks and always successfully goes to new firmware. 

The issue only arises if application resets the mcu and most of the time the bootloader fails to jump. 

Here is my bootloader code

 

 void flash_jump_to_app(uint32_t address)
 {
   /* Function pointer to the address of the user application. */
   fnc_ptr jump_to_app;
   jump_to_app = (fnc_ptr)(*(volatile uint32_t*) (address+4u));
   HAL_DeInit();
   HAL_RCC_DeInit();
   /* Change the main stack pointer. */
   __set_MSP(*(volatile uint32_t*)address);
   jump_to_app();
 }

void app_main()
 {

	 imghdr_t *ipFlaPar;
	 ipFlaPar = (imghdr_t*) Img_Hdr_Start_Address_Internal_Flash;

	 /*first we read if external flash has valid image */
	 SPIF_ReadAddress(&handle_ext_flash,Img_Start_Address_External_Flash,(uint8_t *)&imgFixedhdr,sizeof(imghdr_t));


	 if(imgFixedhdr.imgVld == Img_Header_valid_bytes )
      {
		 /*now we read the external header in external flash to judge if this image needs to be copied into flash*/
         SPIF_ReadSector(&handle_ext_flash, Img_Header_Start_Sector, (uint8_t *)&imgExternalhdr, sizeof(imghdr_t), 0);
         if(imgExternalhdr.imgVld == Img_Header_valid_bytes)
          {
        	 if(imgExternalhdr.imgCpStat == 1) //needs copy
        	   {

        		 if(copy_img_external_to_internal(&handle_ext_flash,imgExternalhdr.imgExternalStartAdr
        				 ,imgExternalhdr.imgHdrStartAdr,imgExternalhdr.imgtotalsize,1024) == 1)
        		 {
        			  imgExternalhdr.imgCpStat = 0; //tell bootloader valid image and copy it
        			  //imgExternalhdr.restartCount = imgExternalhdr.restartCount + 1;
        			  SPIF_EraseSector(&handle_ext_flash, Img_Header_Start_Sector);
        			  SPIF_WriteSector(&handle_ext_flash, Img_Header_Start_Sector, (uint8_t *)&imgExternalhdr, sizeof(imghdr_t), 0);
        			  flash_jump_to_app(imgExternalhdr.prgEntry);
        		 }
        	   }
          }

      }


	 /*This tells us there is already an image in internal flash */
	 if(ipFlaPar->imgVld == Img_Header_valid_bytes )
	 {
	     flash_jump_to_app(ipFlaPar->prgEntry);
	 }




	 while(1);

 }


 

 

6 REPLIES 6
Uwe Bonnes
Principal III

I.m.h.o. the best way is to have a switch at the very beginning of the startup code to jump to the bootloader after a reset. Trigger a reset, when bootloader entry is wanted and check for warm boot in that code.

sorry I did not understand what do you mean by this, can you eloborate

 

and btw with my further testing when I removed 

HAL_RCC_DEINIT()

HAL_DeInit()

these two from my flash_jumo_to_app function, now it seems to be working correctly. I am giving it multiple resets and it always lands on application, but I am still testing it, so cant say if it is fixed or not

LCE
Principal

Interesting that removing the De-Inits makes it work...

Because I just wanted to answer that it helped my application to de-init all of the used peripherals in the bootloader before jumping (on a H7xx).

HZaib.1
Associate III

I think so the reason for that is, I am already deiniting everything in start of application. So my guess is something cause issue if you deinit twice, but I will surely test this behavior and come back with my findings.

LCE
Principal

It somehow seems "cleaner" to me, when the part that's using stuff then de-inits it before jumping.

So bootloader de-inits everything it used, application de-inits everything it used (in case it can jump to the bootloader). 

That way you can keep them independent of each other.

Pavel A.
Evangelist III

@Uwe Bonnes proposes the cleanest solution  It does not init anything and does not need to deinit anything.