on
2019-01-21
4:50 AM
- edited on
2024-06-17
6:57 AM
by
Laurids_PETERSE
In STM32H7, the base address of system memory is different from the entry point of the bootloader. Thus, in order to jump to the bootloader, address "0x1FF09800" should be used instead of "0x1FFF0000". Below, you find a sample code permitting the jump to the bootloader in STM32H7 devices:
void JumpToBootloader(void)
{
uint32_t i=0;
void (*SysMemBootJump)(void);
/* Set the address of the entry point to bootloader */
volatile uint32_t BootAddr = 0x1FF09800;
/* Disable all interrupts */
__disable_irq();
/* Disable Systick timer */
SysTick->CTRL = 0;
/* Set the clock to the default state */
HAL_RCC_DeInit();
/* Clear Interrupt Enable Register & Interrupt Pending Register */
for (i=0;i<5;i++)
{
NVIC->ICER[i]=0xFFFFFFFF;
NVIC->ICPR[i]=0xFFFFFFFF;
}
/* Re-enable all interrupts */
__enable_irq();
/* Set up the jump to booloader address + 4 */
SysMemBootJump = (void (*)(void)) (*((uint32_t *) ((BootAddr + 4))));
/* Set the main stack pointer to the bootloader stack */
__set_MSP(*(uint32_t *)BootAddr);
/* Call the function to jump to bootloader location */
SysMemBootJump();
/* Jump is done successfully */
while (1)
{
/* Code should never reach this loop */
}
}
I want learn led lighting program stvp and STVD plz help it's my mail suryamadhu58@outlook.com
I full confused
@Mmadh if you have a question please post it using the Q&A section in the global navigation bar.
I'm trying to implement this on stm32h743zit6, but no luck. The MCU just reboots instead of switching to a bootloader (as it does with the BOOT pin). What do I miss? Any specific option bytes or control registers perhaps?
Hello @Kirill Makukhin !
If you have a question please post it using the Q&A section in the global navigation bar at the top of this page.
Thank you!
This is useful, however I'd like to point out that if you are not jumping to the system bootloader, but e.g.: between a user bootloader and a user application that is located somewhere else than at 0x08000000, you will most likely need to update the interrupt vector with
```
SCB->VTOR = addr;
```
This is initialised to the default value of 0x08000000 by `SystemInit()` and so you have to make this change _after_ the jump (in case you are jumping to a place that calls `SystemInit()`, as it's likely the case). AFAICT, this cannot be done via the H7 HAL. There are a handful of places where this has been raised for other versions of the HAL (e.g.: https://github.com/STMicroelectronics/STM32CubeL0/pull/10, https://github.com/STMicroelectronics/STM32CubeF4/pull/64 ).
I want to draw attention to the versions. I couldn't get the system bootloader to work with UART2 as my PB15 is not connected to GND. If the STM32H747 system bootloader version is V9.0, the PB15 must be connected to GND.
Just to add a clarification, system memory bootloader address is mentioned on AN2606 and for STM32H7 it always differs from system memory base address. On STM32H72/3/4/5 bootloader address is 0x1FF09800 while for STM32H7A/B it is 0x1FF0A000.
Hi,
In the ICER and ICPR register reset loop, why are you resetting only 5 registers when sometimes there are used more? On STM32H723 we are using, there are used NVIC positions up to 162:
(source: RM), which means that those three interrupts are not disabled and it may cause issues (I just encountered those, that's how I know).
Wouldn't it be better to use something like
uint8_t cnt = (sizeof(NVIC->ICER) / sizeof(*NVIC->ICER));
for (i = 0; i < cnt; i++)
{
NVIC->ICER[i] = 0xFFFFFFFF;
NVIC->ICPR[i] = 0xFFFFFFFF;
}
just to be sure? This writes to all the registeres that are defined in the structure, I know that it is more than needed but it seems to be the better approach than use magic number "5".
Karel
Another thing, I may be mistaken, but in the first paragraph, it seems that System Memory base address is 0x1FFF0000, shouldn't it be 0x1FF00000? I think the same problem is in the application note AN2606, where there is mentioned that (for STM32H72xxx/73xxx): "128 Kbytes starting from address 0x1FFF0000, contain the bootloader firmware." I think that there, too, should be 0x1FF0 0000.
Furthermore, this might not be the right place to mention this, but in the reference manual:
the range given for System Memory seems very strange to me, as the supposed ending address is 1 byte lower than the beginning one...
Hi, I tried to work in the custom bootloader, so I created three application part, one managing the Bootloader and the application, 2nd one is the bootloader, 3rd one is the application, They are individually working perfect, but I tried to jump concept these are not working well, I gave the different memory location and also change the vector address, but is not working well, still I confused, what to do before jumping the application?
I used the stm32f103c8 controller, I developed the bare metal code using Keil software, can you explain before jumping the application Reset the peripherals concept please give the code format.
Thanks.
@heveskar , @MMARC.1 , @Ahmet Yasin CİVAN , @Khouloud GARSI, @haleecaero.1
Hi,
I'm working on STM32H7A3NIH6
Firmware Package: STM32Cube FW_H7 V1.11.2
I have a very interesting issue with bootloader jumping.
According to the file "an2606-stm32-microcontroller-system-memory-boot-mode-stmicroelectronics", the bootloader address is 0x1FF0A000.
The issue:
Sometime its works (succeed to jump into the bootloader, and succeed to program by STM32CubeProgrammer), and sometime is not.
After investigation, I found that when it is not works, it is because the jumping function stuck in HAL function named SCB_DisableDCache().
In SCB_DisableDCache(), there is a while loop that reduce a variable named "sets", and when it came to be zero, the loop is done, and the jumping is continue.
The variable "sets" value starting with some value, 127 for example, and sometime without any reason it changed to a non-reasonable number (605028303), and the loop is continued and continued.
SCB_DisableDCache() is a pure HAL function.
I'm using this function in the bootloader jumping function because I'm using SCB_EnableICache() & SCB_EnableDCache() in the main.
BTW, I noted, that if I'm jump before the function SCB_EnableDCache(), there is no issues.
Maybe there is something in the D cache?
I will glad if someone can help me with that.
tnx!
my jumping function:
void jumpToBootloader()
{
volatile uint32_t BOOTLOADER_ADDRESS = 0x1FF0A000;
// Prepare the micro controller for the jump.
// Reset all interrupts
__disable_irq();
for (uint16_t i = 0; i < sizeof(NVIC->ICER) / sizeof(NVIC->ICER[0]); ++i)
{
NVIC->ICER[i] = 0xFFFFFFFF;
NVIC->ICPR[i] = 0xFFFFFFFF;
}
//clean all caches.
//note!! the Disable performs also clean & invalidate.
SCB_DisableDCache();
SCB_DisableICache();
// disable SysTick timer
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
__enable_irq();
// peripherals if necessary
HAL_RCC_DeInit();
HAL_DeInit();
SCB->VTOR = BOOTLOADER_ADDRESS;
// Set main stack pointer (MSP) to the bootloader's MSP.
__set_MSP(*(uint32_t*)(BOOTLOADER_ADDRESS));
// Get the bootloader's reset vector address and jump to it.
void (*SysMemBootJump)(void);
SysMemBootJump = (void (*)(void))(*(uint32_t*)(BOOTLOADER_ADDRESS + 4));
SysMemBootJump();
//the program should not get here, it should be in bootloader mode.
}
My Main (pure HAL, only added jumpToBootloader() at line 18, for tests):
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MPU Configuration--------------------------------------------------------*/
MPU_Config();
/* Enable the CPU Cache */
/* Enable I-Cache---------------------------------------------------------*/
SCB_EnableICache();
/* Enable D-Cache---------------------------------------------------------*/
SCB_EnableDCache();
jumpToBootloader();
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* Configure the peripherals common clocks */
PeriphCommonClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_OCTOSPI1_Init();
MX_USART1_UART_Init();
MX_ADC2_Init();
MX_I2C4_Init();
MX_TIM8_Init();
MX_USART3_UART_Init();
MX_SPI4_Init();
MX_SPI5_Init();
MX_SPI6_Init();
MX_DAC1_Init();
MX_UART4_Init();
MX_I2C2_Init();
MX_SPI1_Init();
MX_ADC1_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Init scheduler */
osKernelInitialize();
/* Call init function for freertos objects (in cmsis_os2.c) */
MX_FREERTOS_Init();
/* Start scheduler */
osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}