DFU bootloader in F4

Post here first, or if you can't find a relevant section!
victor_pv
Posts: 1863
Joined: Mon Apr 27, 2015 12:12 pm

DFU bootloader in F4

Post by victor_pv » Mon Aug 21, 2017 5:18 pm

Since the STM32F4xx MCUs have a DFU bootloader included in ROM, I'm thinking on adding code so when the board is rebooted to upload a sketch it goes to system rom, to show as DFU device, rather than just doing a hard reset.
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

User avatar
RogerClark
Posts: 7681
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: Rebooting to DFU bootloader in F4 and others.

Post by RogerClark » Mon Aug 21, 2017 9:26 pm

Steve is already investigating this.

I think I posted about it as well.

Perhaps we can move the posts scattered throughout the forum to one central post

User avatar
RogerClark
Posts: 7681
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: Rebooting to DFU bootloader in F4 and others.

Post by RogerClark » Tue Aug 22, 2017 6:14 am

I can't seem to move my post about it.. (in fact I think I've accidently deleted it when trying to move it)

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

Code: Select all

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();

stevestrong
Posts: 2057
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany
Contact:

Re: Rebooting to DFU bootloader in F4 and others.

Post by stevestrong » Tue Aug 22, 2017 6:41 am

Here is the code I was testing:

Code: Select all

#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:
}
Intended to run under libmaple core, I think the RCC registers are defined only on my local pc (did not commit yet), but feel free to change as needed.

I will be off till end of the week.

User avatar
RogerClark
Posts: 7681
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: Rebooting to DFU bootloader in F4 and others.

Post by RogerClark » Tue Aug 22, 2017 7:31 am

Thanks

BTW. I know you were debugging the code... Does it work ?

stevestrong
Posts: 2057
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany
Contact:

Re: Rebooting to DFU bootloader in F4 and others.

Post by stevestrong » Tue Aug 22, 2017 9:30 am

No, I'm still fighting with Eclipse debugging for F4 (as presented in another topic).

User avatar
RogerClark
Posts: 7681
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: Rebooting to DFU bootloader in F4 and others.

Post by RogerClark » Tue Aug 22, 2017 10:02 am

OK
Perhaps someone using a HAL core on the F4 can try it to prove it works

User avatar
RogerClark
Posts: 7681
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: Rebooting to DFU bootloader in F4 and others.

Post by RogerClark » Wed Aug 23, 2017 10:19 pm

Victor

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 !

victor_pv
Posts: 1863
Joined: Mon Apr 27, 2015 12:12 pm

Re: Rebooting to DFU bootloader in F4 and others.

Post by victor_pv » Thu Aug 24, 2017 1:45 am

I believe STM may have a boot loader application note with a sample bootloader code for DFU. We could probably take that, and modify to our liking.
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.

User avatar
RogerClark
Posts: 7681
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: Rebooting to DFU bootloader in F4 and others.

Post by RogerClark » Thu Aug 24, 2017 2:55 am

I cant find any STM code for a bootloader, but I have found a bootloader written using LibOpenCM3 for the F1
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

Post Reply