2015-08-20 07:08 AM
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!
2015-08-20 07:32 AM
It seems you are missing some steps that are needed when you jump to the application program:
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.2015-08-21 04:52 AM
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;
}
}
2015-08-21 05:11 AM
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.2015-08-21 06:17 AM
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_;
}