whole firmware run in ram
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-09-04 11:37 PM
Hello:
I use STM32CubeIDE 1.16.0 to develop an OTA feature in STM32H7A3ZIT6:
The firmware should be programed at flash address 0x08000000,and run in ram, it will receive the whole update image in temporary memory and then program into the flash at the same start address 0x08000000,is it possible in this way? Any detailed examples or documents are appreciated, thanks.
Bill
- Labels:
-
STM32CubeMX
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-09-05 1:30 AM
Hello @lbapplem
Yes, it is possible to implement an OTA update feature for the STM32H7A3ZIT6 microcontroller using STM32CubeIDE. The general idea is to have a bootloader that can receive the new firmware image, store it temporarily in RAM or another memory area, and then program it into the flash memory at the start address 0x08000000.
STM32CubeH7 Firmware Package: This package contains examples and libraries for STM32H7 series microcontrollers. You can find it on the STMicroelectronics website.
AN4852 Application Note: This document provides guidelines for developing a bootloader for STM32 microcontrollers. It can be found on the STMicroelectronics website.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-09-05 1:44 AM
Hi nouirakh:
Thanks for the quick response, but in my case there may not be a bootloader to do so, only the application will start at the default flash address 0x08000000 where is the start address of the flash, and the application should receive the new firmware image to RAM, then erase the flash from 0x08000000 and program the new image into this address,is it possible? I've used STM32H7A3ZITX_RAM.ld to make the application run in RAM(if it does so), but the application will crash when running to erase the flash from 0x08000000, did I miss something?
Bill
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-09-05 3:45 AM
hello @lbapplem
OK, so, it is possible to implement an OTA update feature without a separate bootloader, but it requires careful handling since the application will be running from RAM while it erases and reprograms the flash memory.By following these steps, you should be able to implement an OTA update feature:
-
Modify the Linker Script
Ensure that your linker script (STM32H7A3ZITX_RAM.ld) places the code and data in RAM. Here is an example of a linker script for running the application from RAM:
/* Entry Point */ ENTRY(Reset_Handler) /* Highest address of the user mode stack */ _estack = 0x20040000; /* end of RAM */ /* Generate a link error if heap and stack don't fit into RAM */ _Min_Heap_Size = 0x200; /* required amount of heap */ _Min_Stack_Size = 0x400; /* required amount of stack */ /* Specify the memory areas */ MEMORY { RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K } /* Define output sections */ SECTIONS { .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) /* Startup code */ . = ALIGN(4); } >RAM .text : { . = ALIGN(4); *(.text) /* .text sections (code) */ *(.text*) /* .text* sections (code) */ *(.rodata) /* .rodata sections (constants, strings, etc.) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ . = ALIGN(4); } >RAM .data : AT(__data_load_addr) { . = ALIGN(4); __data_start__ = .; *(.data) /* .data sections */ *(.data*) /* .data* sections */ . = ALIGN(4); __data_end__ = .; } >RAM .bss : { . = ALIGN(4); __bss_start__ = .; *(.bss) *(.bss*) . = ALIGN(4); __bss_end__ = .; } >RAM /* User_heap_stack section, used to check that there is enough RAM left */ ._user_heap_stack : { . = ALIGN(8); PROVIDE ( end = . ); PROVIDE ( _end = . ); . = . + _Min_Heap_Size; . = . + _Min_Stack_Size; . = ALIGN(8); } >RAM }​
View more2.Copy Application to RAM
In your startup code, copy the application from flash to RAM and then jump to the RAM execution address. Here is an example of how to do this in your
main.c
:#include "stm32h7xx_hal.h" #define APPLICATION_ADDRESS 0x08000000 #define RAM_EXECUTION_ADDRESS 0x20000000 void SystemClock_Config(void); void Error_Handler(void); void JumpToRAM(void); int main(void) { HAL_Init(); SystemClock_Config(); // Copy application from flash to RAM uint32_t *flash_ptr = (uint32_t *)APPLICATION_ADDRESS; uint32_t *ram_ptr = (uint32_t *)RAM_EXECUTION_ADDRESS; for (uint32_t i = 0; i < (128 * 1024) / 4; i++) { // Assuming 128KB application size ram_ptr[i] = flash_ptr[i]; } // Jump to RAM execution address JumpToRAM(); while (1) { } } void JumpToRAM(void) { typedef void (*pFunction)(void); uint32_t jumpAddress = *(__IO uint32_t *)(RAM_EXECUTION_ADDRESS + 4); pFunction jumpToApplication = (pFunction)jumpAddress; __set_MSP(*(__IO uint32_t *)RAM_EXECUTION_ADDRESS); jumpToApplication(); } void SystemClock_Config(void) { // Configure the system clock // ... } void Error_Handler(void) { // Implement error handling while (1) { } }​
View more3. Flash Erase and Program
Implement the flash erase and program routines in your application. Ensure that these routines are executed while the application is running from RAM.
void EraseFlash(uint32_t address) { FLASH_EraseInitTypeDef eraseInitStruct; uint32_t sectorError; eraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS; eraseInitStruct.Sector = FLASH_SECTOR_0; // Adjust as needed eraseInitStruct.NbSectors = 1; // Adjust as needed eraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3; if (HAL_FLASHEx_Erase(&eraseInitStruct, §orError) != HAL_OK) { Error_Handler(); } } void ProgramFlash(uint32_t address, uint8_t *data, uint32_t length) { HAL_FLASH_Unlock(); for (uint32_t i = 0; i < length; i += 4) { if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address + i, *(uint32_t *)(data + i)) != HAL_OK) { Error_Handler(); } } HAL_FLASH_Lock(); }​
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-09-05 5:58 AM
"Build for 0x20000000 base address, with whatever split for data, rebase the Reset_Handler entry point, copy the entire FLASH image to RAM, set SCB->VTOR to 0x20000000 per SystemInit() and fork."
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-09-05 9:59 PM
Hi, nouirakh:
Thanks for the detailed steps and I've followed like these:
1.burn the test_ram.hex at 0x08000000 in the evb NUCLEO-H7A3ZI-Q
2.debug in STM32CubeIDE 1.16.0
3.when call JumpToRam(), found it run to main() again
Attached file is my test project, can you help me out here? Thanks.
Bill
