The idea is to be able to reboot to DFU without using boot1 pin (as long as the reboot is triggered thru the sketch using the magic packet).
Currently the libmaple F4 doesn’t implement that, just does a hard reset:
https://github.com/rogerclarkmelbourne/ … vcp.c#L290
Not sure if the Generic core does it, haven’t looked at it, but if it doesn’t we should be able to do it the same way.
I am thinking on a modified version of this code:
https://community.st.com/thread/36971-h … -stm32f417
I think I posted about it as well.
Perhaps we can move the posts scattered throughout the forum to one central post
So here is the link to STM’s community forum
https://community.st.com/thread/40238-s … m-software
The final code posted on that site is
typedef void (*pFunction)(void);
pFunction JumpToApplication;
uint32_t JumpAddress;
HAL_RCC_DeInit();
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
/**
* Step: Disable all interrupts
*/
__disable_irq();
/* ARM Cortex-M Programming Guide to Memory Barrier Instructions.*/
__DSB();
__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
/* Remap is bot visible at once. Execute some unrelated command! */
__DSB();
__ISB();
JumpToApplication = (void (*)(void)) (*((uint32_t *)(0x1FFF0000 + 4)));
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) 0x1FFF0000);
JumpToApplication();
#include <Arduino.h>
void RCC_DeInit()
{
/* Set HSION bit */
RCC->CR |= (RCC_CR_HSION | RCC_CR_HSITRIM_4);
/* Reset CFGR register */
RCC->CFGR = 0;
/* Reset HSEON, CSSON, PLLON, PLLI2S */
RCC->CR &= ~(RCC_CR_HSEON | RCC_CR_CSSON | RCC_CR_PLLON| RCC_CR_PLLI2SON);
/* Reset PLLCFGR register */
RCC->PLLCFGR = 0;
RCC->PLLCFGR = (RCC_PLLCFGR_PLLM_4 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_7 | RCC_PLLCFGR_PLLQ_2);
/* Reset PLLI2SCFGR register */
RCC->PLLI2SCFGR = 0;
RCC->PLLI2SCFGR = (RCC_PLLI2SCFGR_PLLI2SN_6 | RCC_PLLI2SCFGR_PLLI2SN_7 | RCC_PLLI2SCFGR_PLLI2SR_1);
/* Reset HSEBYP bit */
RCC->CR &= ~(RCC_CR_HSEBYP);
/* Disable all interrupts */
RCC->CIR = 0;
}
void JumpToBootloader(void) __attribute__((optimize("-O0")));
void JumpToBootloader(void)
{
void (*SysMemBootJump)(void);
/**
* Step: Set system memory address.
*
* For STM32F407, system memory is on 0x1FFF 0000
* For other families, check AN2606 document table 110 with descriptions of memory addresses
*/
volatile register uint32_t addr = 0x1FFF0000;
/**
* Step: Disable RCC, set it to default (after reset) settings
* Internal clock, no PLL, etc.
*/
RCC_DeInit();
/**
* Step: Disable systick timer and reset it to default values
*/
SYSTICK->CTRL = 0;
SYSTICK->LOAD = 0;
SYSTICK->VAL = 0;
/**
* Step: Disable all interrupts
*/
noInterrupts();
//delay(10000);
/**
* Step: Remap system memory to address 0x0000 0000 in address space
* For each family registers may be different.
* Check reference manual for each family.
*
* For STM32F4xx, MEMRMP register in SYSCFG is used (bits[1:0])
* For STM32F0xx, CFGR1 register in SYSCFG is used (bits[1:0])
* For others, check family reference manual
*/
SYSCFG->MEMRMP = 0x01;
/**
* Step: Set jump memory location for system memory
* Use address with 4 bytes offset which specifies jump location where program starts
*/
SysMemBootJump = (void (*)(void)) (*((uint32_t *)(addr + 4)));
/**
* Step: Set main stack pointer.
* This step must be done last otherwise local variables in this function
* don't have proper value since stack pointer is located on different position
*
* Set direct address location which specifies stack pointer in SRAM location
*/
asm volatile ("mov r3, %0\nldr r3, [r3, #0]\nMSR msp, r3\n" : : "r" (addr) : "r3", "sp");
/**
* Step: Actually call our function to jump to set location
* This will start system memory execution
*/
SysMemBootJump();
/**
* Step: Connect USB<->UART converter to dedicated USART pins and test
* and test with bootloader works with STM32 Flash Loader Demonstrator software
*/
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
delay(3000);
Serial.println("This is a test how to jump to the system bootloader without setting BOOT0 pin to 1.\n");
Serial.println("Type any key to jump to ROM bootloader...\n");
// wait for user input
//while (!Serial.available()) ;
// read all serial input data
//while (Serial.available()) Serial.read();
//Serial.println("The system will now jump to ROM bootloader...");
//delay(100); // let time for serial to output message
// jump to bootloader
JumpToBootloader();
}
void loop() {
// put your main code here, to run repeatedly:
}
BTW. I know you were debugging the code… Does it work ?
Perhaps someone using a HAL core on the F4 can try it to prove it works
Thinking about using the F4 internal DFU bootloader, I can see this could be problematic, because there is no timeout on the DFU and also the sketch would need to work perfectly so that it was able to jump to the bootloader
In may cases we all have problems were the code crashes etc, in which case the only option would be to move the jump links and press reset
We can’t even make the sketch always jump to the bootloader when it starts, because there isn’t a timeout on the built in bootloader.
I think we need to write a F4 version of the bootloader, probably using LibOpenCM3.
I did see some code on a Chinese website where someone had ported the Maple bootloader to the F4, but it was one of those sites where you have to pay a small fee to download the code and there was no way I was giving some unknown website my credit card details !
I had been thinking too in the problem of the sketch crashing or something and needing to reboot the board with the boot1 jumper set.
The repo says the F1 build is compatible with my F1 repo, which is interesting
https://github.com/devanlai/dapboot
It is probably worth trying that and if its any good, then see if it can be ported to the F4
dapboot is only compatible in the sense that it uses the same application offset as the STM32duino bootloader and uses the same RTC backup register values to force the bootloader to enumerate (in case you were wondering where those magic values came from…). It’s not really compatible with the normal STM32duino bootloading process.
It has the same behavior as the STM32F4 DFU bootloader, where it only enumerates if requested by the application or if the right pins are asserted at bootup. Personally, I prefer this behavior since there’s no fiddly PC-specific startup delay to contend with.
Recovering to the bootloader via jumper after flashing bad code is not an ideal workflow, but it’s not so bad – it’s not like you have to break out a hardware debugger or serial dongle or solder any new pins/wires to your board. I think using the USB DFU ROM bootloader will simplify support, since the board ships ready to accept sketches (assuming the vendors are not shipping F4 boards with random demo firmware).
Thanks. I thought I recognised the author’s name ![]()
I thought I could modify your code to behave in a similar way to the Maple bootloader
BTW. The LibMaple core currently does not set the Backup registers so the PC has to be ready quickly as the bootloader only stays in DFU for about 1 second.
When I was debugging some other code the other day, I did investigate setting the magic numbers in the Backup reg but I didn’t get it to work at the time, and I didnt have time to debug it.
The only change to your code would be to always enter DFU, but then exit after 1 second and jump to the Application sketch if the sketch is present (using the same validation code from the Maple bootloader)
For setting the backup registers in the magic-reset-sequence from libmaple, the code that I used was:
// Write a magic flag into the RTC register 10 to ensure we reboot
// into persistent bootloader mode
bkp_init();
bkp_enable_writes();
bkp_write(10, 0x424C);
bkp_disable_writes();
Its interesting that LibOpenCM3 creates a larger binary than the Maple bootloader.
The backup registers code is not essential, so that would make some space.
Thanks
Roger
It’s already done and he used it with a 446 and the Generic core (which follows the same method as libmaple to reboot).
I’m sure it doesn’t need much to make it run in other MCUs. We also need to change the usb enumeration method to ours (pulling the usb pin down), but those changes should be small.
I think perhaps the major changes are in making it work with several F4 with differen flash sizes, but that may have been taken in account already by STM.
Do you see any problem in using the STM code? is part of the CubeMX.
I hope Chriss wouldn’t mind using his bits and pieces since they are small changes, but we can check with him.
It takes about 16KB, which I guess is alright on an F4, and may be possible to optimize it further.
I don’t see any problem with using the Cube. AFIK its license is not too restrictive.
Do you have a link to Chris’s bootloader ?
FYI
I built @devan’s bootloader this morning, but had to do it on my linux VM as on windows it needs msys, which I don’t currently have installed
PS.
Strangely I can build libopencm3 in the BMP repo on Windows without needing msys, and it uses libopemcm3, but Blacksphere must have changed the build process on libopencm3 to make it work on Windows.. But unfortunately the BMP version does not work with @davan’s code, as there appear to be differences in the API versions
https://github.com/chrissbarr/PicoPrint-Bootloader
its based on the 446, but I think the cube code is almost the same for all F4 since the use and the flash work the same way.
You can see the code he added on main to manage the usb discovery pin, 3 seconds time out, etc.
https://github.com/arduino-org/arduino-core-stm32f4
To enter in dfu, no need user action, set seialusb config to 1200:
https://github.com/arduino-org/arduino- … _if.c#L261
Then, set a dedicated magic code at a dedicated @:
https://github.com/arduino-org/arduino- … _if.c#L436
Finally, during init:
https://github.com/arduino-org/arduino- … ds.cpp#L70
Call entersysrom:
https://github.com/arduino-org/arduino- … sROM.S#L11
Thanks
I will look at those repo’s
That is the same method that I mentioned in the first post.
[fpiSTM – Sat Aug 26, 2017 6:41 am] –
FYI, Dfu for F4 was implemented for the Otto:
https://github.com/arduino-org/arduino-core-stm32f4To enter in dfu, no need user action, set seialusb config to 1200:
https://github.com/arduino-org/arduino- … _if.c#L261
Then, set a dedicated magic code at a dedicated @:
https://github.com/arduino-org/arduino- … _if.c#L436
Finally, during init:
https://github.com/arduino-org/arduino- … ds.cpp#L70
Call entersysrom:
https://github.com/arduino-org/arduino- … sROM.S#L11
@fpiSTM
Has any bootloader or POC been tried? This uses the read only ROM bootloader of F3/F4 core right?
Yes, no dedicated bootloader
Best & merry Xmas, E.
OK, thanks, i tested the same mecanism for STM32F303, only replacing SRAM flag by RTC backup register since the F303CC doesnt have backup SRAM (so it was not working as is), the STM32F303 now resets on CDC 1200bps touch and can detect the DFU mode after reset.However, i still have a problem for jumping to bootlader (sysROM.s), it falls into usageFault when reaching line 19
https://github.com/arduino-org/arduino- … sROM.S#L19
Is SYSCFG_CFGR1 (+0x00) specific to STM32F4? i havent found any info on how to jump to the internal DFU bootlaoder on STM32F303 in datasheet and DM00046982. If anyone has a clue.
[edogaldo – Sat Dec 23, 2017 7:51 am] –
Hi all, I was wondering if it could be enough to set the system bootloader address in the reset handler to do the trick.Best & merry Xmas, E.
Sorry I edited Edogaldo post by mistake before, this part was mine:
There is a bit more than that, you need to set the NVIC VTOR register so the NVIC can find the vector table.
This video shows it and shows sample code, very minimal. You just set a couple of registers and jump to it:
https://www.youtube.com/watch?v=cvKC-4tCRgw
[logd32 – Sun Dec 24, 2017 3:34 pm] –
Is SYSCFG_CFGR1 (+0x00) specific to STM32F4? i havent found any info on how to jump to the internal DFU bootlaoder on STM32F303 in datasheet and DM00046982. If anyone has a clue.
Generally the F3 peripherals are more similar to the F1 than the F4. It has a cortexM4 core, but with F1 peripherals (mostly), vs the F2 which has F4 peripherals with a cortex M3 like the F1.
So the SYSCFG_CFGR1 register may be very different between the F3 and F4, check the datasheet.

