2018-01-26 07:55 AM
Hi there,
we are currently developing the firmware for our custom board with an STM32F746 MCU in LQFP-100 package. Our current version is working well and now we want to be able to download updates via USB DFU. I read many posts and the related documents from ST, so there might be some ways to realize this. Unfortunately, in either way we get stuck on choosing the right addresses or verifying code with DfuSe. My favorite way is the following in which we jump to the internal bootloader:
&sharpdefine SYS_MEM_ADD 0x1FF00000
//Disables the RCC (reset setting)HAL_RCC_DeInit();SysTick->CTRL = 0;SysTick->LOAD = 0;SysTick->VAL = 0;
// disables every IRQ
__disable_irq();// remap system memory to 0x0000 0000
SYSCFG->MEMRMP = 0x01;JumpToApplication = (void (*)(void)) (*((uint32_t *)(SYS_MEM_ADD + 4)));
__set_MSP(*(__IO uint32_t*) SYS_MEM_ADD);JumpToApplication();
while(1);
The problem is that this way is just working in debug mode (toolchain SW4STM32 with Segger J-link). So my breakpoint is at JumpToApplication() and when I go one step further the device appears in DfuSe with the correct memory mapping (DFU update possible). In normal run mode the application is running and while switching to DFU/Bootloader mode the MCU just resets. I tried some different addresses but nothing would work. Maybe there is another way or something wrong in the IDE settings?
I appreciate every help. Thanks in advance!
Regards,
Kevin Lehzen
#stm32f7Solved! Go to Solution.
2018-01-26 06:51 PM
This brought up 'STM32 BOOTLOADER' on the STM32F746G-DISCO for me
//***************************************************************************
void BootDFU(void)
{
printf('Entering Boot Loader..
');
SCB_DisableDCache();
*((unsigned long *)0x2004FFF0) = 0xDEADBEEF; // 320KB STM32F7xx
__DSB();
NVIC_SystemReset();
}
//***************************************************************************
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =0x2004FFF0 ; Address for RAM signature
LDR R1, =0xDEADBEEF
LDR R2, [R0, #0]
STR R0, [R0, #0] ; Invalidate
CMP R2, R1
BEQ Reboot_Loader
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
Reboot_Loader PROC
EXPORT Reboot_Loader ; STM32F7xx
LDR R0, =0x1FF00000 ; ROM BASE
LDR SP, [R0, #0] ; SP @ +0
LDR R0, [R0, #4] ; PC @ +4
BX R0
ENDP ; sourcer32@gmail.com
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
2018-01-26 09:50 AM
A blanket disabling of IRQs is unhelpful, where would that get enabled again? Does this reflect the state at reset? Turn off your interrupt sources at the peripheral.
Don't call the loader from an interrupt context.
Would have to see if the system loader is testing for the dual bank boot.
2018-01-26 06:51 PM
This brought up 'STM32 BOOTLOADER' on the STM32F746G-DISCO for me
//***************************************************************************
void BootDFU(void)
{
printf('Entering Boot Loader..
');
SCB_DisableDCache();
*((unsigned long *)0x2004FFF0) = 0xDEADBEEF; // 320KB STM32F7xx
__DSB();
NVIC_SystemReset();
}
//***************************************************************************
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =0x2004FFF0 ; Address for RAM signature
LDR R1, =0xDEADBEEF
LDR R2, [R0, #0]
STR R0, [R0, #0] ; Invalidate
CMP R2, R1
BEQ Reboot_Loader
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
Reboot_Loader PROC
EXPORT Reboot_Loader ; STM32F7xx
LDR R0, =0x1FF00000 ; ROM BASE
LDR SP, [R0, #0] ; SP @ +0
LDR R0, [R0, #4] ; PC @ +4
BX R0
ENDP ; sourcer32@gmail.com
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
2018-01-29 12:30 PM
Thanks Clive,
I am sorry but I am a bit confused where to put the assembler code. Looks like its something for the startup...s?
Kind regards,
Kevin
2018-01-29 02:25 PM
Yes startup_stm32f7xx.s augmenting the reset vector permitting transfer into ROM at 'reset' conditions. Here using Keil syntax.
2018-02-01 01:02 AM
Thanks for your help, Clive. Now it works!
Cheers
2018-02-19 01:01 PM
Hi Clive
I too am struggling to get this boot loader thing going. I have read AN2606 and 3155 from STM and have seen your replies to many others like me in this forum. I am using an STM32L496 and will use USART1 as my boot load device. Could you explain a couple of things about the overall system to me:
1) I see that you are writing a flag into RAM and then testing this flag out of reset to determine if the CPU will branch to the main code or the boot loader. Why would you do this rather than just jump to the boot loader?
2) The STM docs tell me that the boot loader in the L496 will use the Systick timer for USART1. Figure 67 in AN2606 seems to indicate that the boot loader code will take care of setting this up. Do I need to disable the existing systick timer before jumping to the boot loader?
3) The same figure doesn't show that the USARTs are enabled by the boot loader. Do I need to set up USART1 before I jump there or did they just forget to include this in the figure?
4) In your system that writes 'DEADBEEF' to a RAM location, would there not be a risk of making the famous 'brick' if the boot load was interrupted? If the 'DEADBEEF' was written to an area of flash instead, and then only cleared by the PC updating program once it is sure the new code has been completely transferred, would that be any better? I think this should be possible with the L496 hardware.
Many thanks in advance for your advice (and patience)!
2018-02-19 02:53 PM
1) Because you're a lot closer to 'reset conditions' than you are in your main code with interrupts, PLLs etc.
2) The system loader runs from ROM with no user intervention normally, you're goal is to enter with the least amount of meddling. You enabling and having a bunch of interrupts firing isn't what the system loader expects.
3) see 2
4) If you foolishly delete the boot loader in FLASH so the board has nothing to execute you can certainly brick things. The goal would be to have a boot loader in front that you *don't* delete, and it checks and validates the application image placed later in FLASH before calling it. That way you always have something functioning, and a system that is recoverable. Not exactly sure how having a RAM tag that says run ROM vs FLASH will brick the system during a single reset cycle, or how that would be different, or less safe, to writing something more permanently in FLASH
If you want a recoverable board you'd expose the BOOT0 pins so you can get the device into the ROM's system loader.
2018-02-19 04:05 PM
Using Clive Oness guidance from above, I have it working now for the L496. To answer one of my questions above, the boot loader code does look after everything wrt to the USART and Systick set up. In the startup_stm32l496xx.s file, I inserted this just before the STM generated branch to main ( 'bl main') :
/* Look for boot loader signature. */
LDR R0, =0x20002000
// note different location for my system compared to example above
LDR R1, =0xDEADBEEF
LDR R2, [R0, &sharp0]
/* Invalidate */
STR R0, [R0, &sharp0]
CMP R2, R1
BEQ Reboot_Loader
LDR R0, =SystemInit
BLX R0
bl main
Reboot_Loader:
/* Boot Loader BASE */
LDR R0, =0x1FFF0000
// note different boot loader location for L496 compared to above
LDR SP, [R0, &sharp0]
// SP @ +0
LDR R0, [R0, &sharp4]
// PC @ +4
BX R0
// jump to bootloader
/* Call the application's entry point.*/
<-this generated by STM
bl main
<-this is generated by STM and could be removed now
LoopForever:
<-this is generated by STM
b LoopForever
<-this is generated by STM
And the function that starts it all:
void
bootload(
void
)
{
*((
unsigned
long
*)0x20002000) = 0xDEADBEEF;
NVIC_SystemReset();
while
(1);
// this should never happen!
}
For the L496, I will try placing the DEADBEEF signature into an area of flash that will be off limits to my update program. I will also not overwrite the code in the startupxxx.s file during an update. Once the new code has been completely written and verified, then I will clear the DEADBEEF flash location with the update program. I believe that this will keep the system in the boot load mode even if power or coms are interrupted during an update.
6 Mar 2018: Update for conversion to STM32L4R5: The stm32lr5 has a couple of changes compared to the stm32l496 that require an addition to the assembler startup file. The Syscfg register must be modified to map the bootloader to address 0x00000000:
/* Look for boot loader signature. */
LDR R0, =0x20040000
LDR R1, =0xDEADBEEF
LDR R2, [R0, &sharp0]
/* Invalidate */
STR R0, [R0, &sharp0]
CMP R2, R1
BEQ Reboot_Loader
LDR R0, =SystemInit
BLX R0
bl main
Reboot_Loader:
/* Remap bootloader code to address 0x00000000 */
LDR R0, =0x40021060
// address of the clock enable register for access to syscfg
LDR R1, =0x00000001
// only need to set bit one to 1. All others will be 0 out of reset
STR R1, [R0, &sharp0]
LDR R0, =0x40010000
// location of SYSCFG_MEMRMP
LDR R1, =0x00000001
STR R1, [R0, &sharp0]
/* Boot Loader BASE */
LDR R0, =0x00000000
LDR SP, [R0, &sharp0]
// SP @ +0
LDR R0, [R0, &sharp4]
// PC @ +4
BX R0
// jump to bootloader
/* Call the application's entry point.*/
bl main
LoopForever:
b LoopForever
2018-02-19 05:18 PM
Makes sense and much appreciated! Thanks for your help J
Paul