背景
当前产品硬件:STM32F429IGT6( 内部ROM:1MB)+norflash(16MB)+sdram(32MB)+其他外围(RGB565\UART\SPI\IIC\等等)。操作系统为RTT,之前产品都是基于RTT开发的。
由于STM32F429价格太高,使用 i.MX RT1052 作为替代芯片。不仅仅是替换后续的产品,之前的产品硬件也要替换掉。
在ST上,0-128K作为bootloader区域,128K-1024K作为APP区域,FOTA大概过程:
- APP从服务器下载固件,保存到norflash,检验 MD5
- 重启设备
- bootloader 发现有新固件,解密,校验MD5,校验HASH等,检验通过则刷APP区域并跳入;检验不通过则删除固件,直接跳入APP
实施过程
1、跳转功能调试
先了解了1052的存储结构,了解了FDBC\DCD等,完成了跳转功能:
镜像结构:
通过修改编译链接文件,使bootloader和app镜像按照如上分部。目前已完成了从bootloader 跳转到app,app目前运行正常
\ | /
- RT - Thread Operating System
/ | \ 4.1.0 build May 27 2022 18:12:44
2006 - 2022 Copyright by RT-Thread team
Here is boot.[I/main]
Firmware Download Complete,Jump App.
\ | /
- RT - Thread Operating System
/ | \ 4.1.0 build May 29 2022 20:51:39
2006 - 2022 Copyright by RT-Thread team
msh >This's app
This's app
This's app
This's app
但是这是分两个工程分别用调试器下载进去的,仅仅验证了跳转功能。
2、操作norflash
方案1
开机就将系统加载到sdram中运行,这样操作用与XIP的norflash也不会影响到系统运行
修改了链接脚本(keil MDK ARMCC):
#define m_flash_config_start 0x60000000
#define m_flash_config_size 0x00001000
#define m_ivt_start 0x60001000
#define m_ivt_size 0x00001000
#define m_interrupts_start 0x60002000
#define m_interrupts_size 0x00000400
#define m_text_start 0x60002400
#define m_text_size 0x03FFDC00
;在SDRAM中存放代码的空间
;中断向量表
#define m_sdram_interrupts_start 0x80000000
#define m_sdram_interrupts_size 0x00000400
;SDRAM中的主体代码
#define m_sdram_text_start 0x80000400
#define m_sdram_text_size 0x003FFC00
#define m_data_start 0x80400000
#define m_data_size 0x01A00000
#define m_ncache_start 0x81E00000
#define m_ncache_size 0x00200000
#define m_data2_start 0x20000000
#define m_data2_size 0x00020000
#define m_data3_start 0x20200000
#define m_data3_size 0x00040000
/* Sizes */
#if (defined(__stack_size__))
#define Stack_Size __stack_size__
#else
#define Stack_Size 0x0400
#endif
#if (defined(__heap_size__))
#define Heap_Size __heap_size__
#else
#define Heap_Size 0x0400
#endif
LR_m_rom_config m_flash_config_start m_flash_config_size { ; load region size_region
RW_m_config_text m_flash_config_start m_flash_config_size { ; load address = execution address
* (.boot_hdr.conf, +FIRST)
}
}
LR_m_rom_ivt m_ivt_start m_ivt_size { ; load region size_region
RW_m_ivt_text m_ivt_start m_ivt_size { ; load address = execution address
* (.boot_hdr.ivt, +FIRST)
* (.boot_hdr.boot_data)
* (.boot_hdr.dcd_data)
}
}
LR_m_text m_interrupts_start m_text_start+m_text_size-m_interrupts_size { ; load region size_region
; 在FALSH中的中断向量表
VECTOR_ROM m_interrupts_start m_interrupts_size { ; load address = execution address
* (RESET,+FIRST)
}
; * (InRoot$$Sections)是__main中从加载域复制代码到执行域的程序scatter_copy,
; 启动时运行的startup_mimxrt1052t和system_mimxrt1052中的代码要存放在FLASH中
ER_m_text m_text_start m_text_size { ; load address = execution address
* (InRoot$$Sections)
startup_mimxrt1052.o(+RO)
system_mimxrt1052.o(+RO)
}
; EMPTY表示这段空间留空,防止其它应用占用或编译提示warning
VECTOR_RAM m_sdram_interrupts_start EMPTY m_sdram_interrupts_size { ;execution address
;这部分内容由board.c文件中的CopyAndUseRAMVectorTable函数从VECTOR_ROM中复制得到
;得到SDRAM版本的中断向量表
}
;存放主体程序的SDRAM空间,由__main函数从FLASH中加载
ER_m_ram_text m_sdram_text_start m_sdram_text_size { ;execution address
.ANY (+RO)
}
RW_m_data m_data_start m_data_size-Stack_Size-Heap_Size { ; RW data
.ANY (+RW +ZI)
*(m_usb_dma_init_data)
*(m_usb_dma_noninit_data)
}
ARM_LIB_HEAP +0 EMPTY Heap_Size { ; Heap region growing up
}
ARM_LIB_STACK m_data_start+m_data_size EMPTY -Stack_Size { ; Stack region growing down
}
RW_m_ncache m_ncache_start m_ncache_size { ; ncache RW data
* (NonCacheable.init)
* (NonCacheable)
}
}
借鉴了野火开发板的例程,开机后__main中从加载域复制代码到执行域的程序scatter_copy,