cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F429 custom boot loader (run RTX OS) can not jump to application program

gds
Associate II
Posted on August 20, 2015 at 16:08

Ihave a same problem , I have read many post about this problem (most of them is Clive's post, thank Clive so much), but I still canfix this bug, it can not jump to application program ( or applicationprogram can not run). Someone please give me some advices so solvedthis bug.

Mydevice: STM32F429 DISCOVERY Board

Myquestion: write a custom boot loader to upgrade application program.Run RTX OS to use USB connection (as a device).

MyIDE: Keil ARM v5

Ihave done: get image of application program (.bin) and write toflash.

Isplit Flash to 3 part:

-0x08000000 – 0x08040000 : contain boot loader ( 256KB, used 80KB)

-0x08040000 – 0x081C0000 : contain application program( used 11KBfor blink led application)

-0x081C0000 – 0x081E0000 : contain configuration and data sharebetween boot loader and application program.

Inboot loader:

-Start at : 0x08000000 – size 0x40000

-#define VECT_TAB_OFFSET 0x00

;*************************************************************

;*** Scatter-Loading Description File generated by uVision ***

;*************************************************************

LR_IROM10x08000000 0x00040000 { ; load region size_region

ER_IROM1 0x080000000x00040000 { ; load address = execution address

*.o (RESET, +First)

*(InRoot$$Sections)

.ANY (+RO)

}

RW_IRAM1 0x200000000x00030000 { ; RW data

.ANY (+RW +ZI)

}

}

Inapplication program

-Start at : 0x08040000 – size 0x1C0000

-#define VECT_TAB_OFFSET 0x40000

;*************************************************************

;*** Scatter-Loading Description File generated by uVision ***

;*************************************************************

LR_IROM10x08040000 0x001C0000 { ; load region size_region

ER_IROM1 0x080400000x001C0000 { ; load address = execution address

*.o (RESET, +First)

*(InRoot$$Sections)

.ANY (+RO)

}

RW_IRAM1 0x200000000x00030000 { ; RW data

.ANY (+RW +ZI)

}

}

Myjump code: in the first of main boot loader, it check a value storein 0x081E0000 of flash, if value = 0 will jump to application elsecontinue to run boot loader program (Init System and ...).

if( boot_select == 0x00) // check boot flag

{ //APPLICATION_ADDRESS = 0x08040000LED_Initialize();

LED_On(0);

if((((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0xFF000000 ) ==0x20000000) || \

(((*(__IOuint32_t*)APPLICATION_ADDRESS) & 0xFF000000 ) == 0x10000000))

{

JumpAddress = *(__IOuint32_t*) (APPLICATION_ADDRESS + 4 );

Jump_To_Application =(pFunction) JumpAddress;

__set_MSP(*(__IO uint32_t*)APPLICATION_ADDRESS);

Jump_To_Application();

}

}

Ihave test this jump command, if I replace APPLICATION_ADDRESS =0x08000000 ( boot loader address) it can 

jump(as reset) but if APPLICATION_ADDRESS = 0x08040000, nothing happen .I have run debug in Keil, I saw it 

gotHard Fault.

Thanksso much for your help!

4 REPLIES 4
knielsen
Associate II
Posted on August 20, 2015 at 16:32

It seems you are missing some steps that are needed when you jump to the application program:

  1. You should reset any peripherals that your bootloader has used, including disabling any interrupts that might have been enabled. Otherwise your application program may find a device in an unexpected state, or take an interrupt that it is not prepared to handle.
  2. You need to relocate the global vector table to the one of the application, so that all interrupt vectors etc. are correct.
  3. I think it is in principle incorrect to use __set_MSP() in C code to change the stack pointer - the C compiler might generate code that tries to access the wrong stack. The better way is to use inline assembler for changing stack + jumping to target. Though in practice your code might work fine, depending on compiler used.
You can see an example of a working bootloader I wrote

https://github.com/knielsen/stm32f4_wireless_bootloader/blob/master/wireless_bootloader.c

. The function that transfers to the application program is jump_to_target(), and illustrates the points above. Google should find other examples as well.

EDIT: fix the link.

gds
Associate II
Posted on August 21, 2015 at 13:52

Thanks nielsen.kristian! 

My jump code work fine, the problem is the application program can not run because my boot loader write wrong data to flash. Thanks for your advice!

May I ask you some question? STM32F4 receive application program image from PC ( STM32F4 is a USB Device) and write it to Flash byte by byte , address will increase 1 byte every byte code is written to flash. Is it OK?

Here is my code:

 

unsigned char user_write_flash(__IO uint32_t Addr, uint8_t Data)

{

  HAL_FLASH_Unlock();

  if (Addr < FLASH_USER_END_ADDR)

  {

Rewrite:

    if (HAL_FLASH_Program(TYPEPROGRAM_BYTE, Addr, Data) == HAL_OK)

    {

data8 = *(__IO uint32_t*)Addr;

if (data8 != Data)

{

LED_On(LED4);

LED_On(LED3);

goto Rewrite;

}     

    }

    else

    { 

LED_On(1);

return FAILED;

    }

  }

  HAL_FLASH_Lock(); 

  return SUCCESS_;

}

for (i = 0; i < data_lenght; i++ )

{

Flash_Process

= FLASHING;

if (user_write_flash(Current_Addr, INFO.USB_message[i]) == FAILED)

{

USB_Send_package_Err(0x0C);

}

else

{

Current_Addr = Current_Addr + 1;

}

}

knielsen
Associate II
Posted on August 21, 2015 at 14:11

I do not see any code to erase pages before writing? This is necessary (at least if you need to write at least one '0' bit on top on a '1' bit, which is generally the case). Be sure to understand the exact page layout of your MCU, it can be complex. Erase can only be done page-by-page.

I am not familiar with the HAL functions, but I assume there is a function to erase a page.

In my bootloader, I am writing a complete page at a time, this way my code can check if an erase is needed (eg. avoid an erase if writing identical data). But I think a simpler byte-by-byte write could work fine, as well.

gds
Associate II
Posted on August 21, 2015 at 15:17 I erase all flash from0x08040000 to0x081C0000 before begin get data and write to flash. Did you get any Faults when write 1 Word code to flash? and what should we do to repair it? I will try to write 1 word at time, because it get many faults when write byte by byte.


unsigned char user_erase_flash(uint32_t Start_Addr, uint32_t End_Addr)

{

/* Unlock the Flash to enable the flash control register access *************/

HAL_FLASH_Unlock();


/* Erase the user Flash area

(area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) ***********/


/* Get the 1st sector to erase */

FirstSector = GetSector(Start_Addr);

/* Get the number of sector to erase from 1st sector*/

NbOfSectors = GetSector(End_Addr) - FirstSector + 1;


/* Fill EraseInit structure*/

EraseInitStruct.TypeErase = TYPEERASE_SECTORS;

EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3;

EraseInitStruct.Sector = FirstSector;

EraseInitStruct.NbSectors = NbOfSectors;

__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGSERR );

if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK)

{

return FAILED;

}

return SUCCESS_;

}