STM32H750启动和内存优化(分散加载修改)

前些日子有个朋友一直给我推荐STM32H750这款芯片,说它的性价比,说它多么多么好。于是乎,这两天试了试,嚯,真香!我们先看看基本配置
请添加图片描述
请添加图片描述

这里简单总结下,cortex-m7内核,128k片内flash ,1M RAM,淘宝价格十几块,瞬间感觉1052没那么香了(价格二十多)。关键这个价格几乎跟imxrt1011差不多了,而1011只有128K RAM,无片内flash,导致做不了很复杂的项目。除此之外h750还能拓展出32bit sdram这点相比1052的16bit性能也进一步加强。好了,本章不是介绍h750性能多强的,主要介绍,上手h750后,ram 和 rom如何高效利用起来。

内存分布

先看看系统的ram分布结构请添加图片描述
请添加图片描述

内存设备地址区间大小
ITCM0x0000_0000~0x0000_FFFF64K
DTCM0x2000_0000~0x2001_FFFF128K
AXI SRAM (D1)0x2400_0000~0x2407_FFFF512K
SRAM1 (D2)0x3000_0000~0x3001_FFFF128K
SRAM2 (D2)0x3002_0000~0x3003_FFFF128K
SRAM3 (D2)0x3004_0000~0x3004_7FFF32K
SRAM4 (D3)0x3800_0000~0x3800_FFFF64K

结合上述矩阵图,结合其速度位宽,我们可以给这些RAM做一个优先级划分 TCM > AXI SDRAM > SRAM 1 2 3 > SRAM 4,当然像以太网和 USB 的缓冲是要求用于SRAM3中的,这类特殊外设,需要特别注意。另外我们应该尽量让代码在TCM中运行,这时候我们就需要修改其分散加载文件(也叫链接脚本)。分散加载文件,主要目的就是把想要的数据或者代码运行到指定区域,进而让系统更高效的运行。

修改启动文件

请添加图片描述
这里笔者将启动文件startup_stm32h750xx.s分为两段,RES_HANDLER 包含 Reset_Handler SystemInit__main 函数相关,OTHER_HANDLER 包含其他中断函数。将这两个段,一个就地执行,一个拷贝到tcm,除此之外链接脚本中,VECTOR_RAM 用于存放中断向量,并在main开始阶段执行拷贝

//中断向量拷贝函数 ROM 拷贝到 RAM, 更新 SCB->VTOR
void xBSP_VectorInit(void)
{
	extern uint32_t Image$$VECTOR_ROM$$Base[];
	extern uint32_t Image$$VECTOR_RAM$$Base[];
	
    void *pS = (void *)Image$$VECTOR_ROM$$Base;
    void *pT = (void *)Image$$VECTOR_RAM$$Base;
	
	uint32_t pRamVectorAddr = (uint32_t)Image$$VECTOR_RAM$$Base;
	
    memcpy(pT,pS,0x298);
	__asm("CPSID I");
	SCB->VTOR = pRamVectorAddr;
	__asm("CPSIE i");
}

int main(void)
{
	xBSP_VectorInit();
	......
}

修改后的链接脚本

如下链接脚本,代码是下载到内部flash中的,如果下载到外部QSPI flash,那直接修改成0x9000_0000即可

LR_IROM1 0x08000000 0x00020000  
{    ; load region size_region
	VECTOR_ROM 0x08000000 0x00020000  
	{  ; load address = execution address
		*.o (RESET, +First)
		*(InRoot$$Sections)
		startup_stm32h750xx.o (RES_HANDLER)
		system_stm32h7xx.o (+RO)
	}

	VECTOR_RAM 0x00000000 0x00000298 
	{
	
	}

	RW_m_text 0x00000298 0x0000fd68 
	{  ; itcm 64k
		startup_stm32h750xx.o (OTHER_HANDLER)
		.ANY (+RO)
		.ANY (+XO)
	}

	RW_DTCM 0x20000000 0x00020000  
	{  ; dtcm 128k
		.ANY (+RW +ZI)
	}

	RW_SRAM 0x24000000 0x00080000  
	{	;512k axi sram
		
	}
}
修改后的map映射请添加图片描述

补充:下载外部flash需要对应的下载算法,下载算法基于硬件设计(选择的IO)和flash品牌不同而有差异,所以在使用外部flash时候,需要制作其下载算法,下载算法如何制作,可以看看如下链接:

STM32H750片外Flash启动(W25Q64JVSIQ) - STM32H7 - 硬汉嵌入式论坛 - Powered by Discuz! (armbbs.cn)

STM32H750 是意法半导体(STMicroelectronics)推出的一款高性能 ARM Cortex-M7 内核的微控制器,属于 STM32H7 系列。该芯片支持多种外设高级功能,适用于工业控制、智能家电、物联网设备等应用场景。其中,其 Flash 存储器是系统代码存储执行的关键部分。 ### Flash 容量与结构 STM32H750 提供高达 2MB 的嵌入式 Flash 存储器,用于存储程序代码常量数据。Flash 存储器支持多 Bank 架构,分为两个独立的 Bank:Bank1 Bank2。每个 Bank 可以单独进行擦除编程操作,同时支持读写同时(Read-While-Write, RWW)特性,允许在一个 Bank 上执行代码的同时对另一个 Bank 进行写操作[^1]。 ### Flash 配置 在使用 STM32H750 的 2MB Flash 时,通常需要通过启动文件(如 `.sct` 文件)配置内存映射。Keil MDK 使用分散加载文件(scatter file)来定义各个段(如代码段、只读数据段、初始化数据段等)在 Flash RAM 中的位置。例如: ```text LR_IROM1 0x08000000 0x200000 { ; Load region for Code and RO data (2MB) ER_IROM1 0x08000000 0x200000 { ; Execution region for Code and RO data *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } RW_IRAM1 0x20000000 0x60000 { ; RW data (SRAM D1) .ANY (+RW +ZI) } } ``` 此配置将整个 2MB Flash(从地址 `0x08000000` 开始)分配给代码只读数据,并将 SRAM 区域用于可读写数据[^2]。 ### Flash 使用注意事项 1. **擦写次数限制**:Flash 存储器有擦写寿命限制(通常为 100,000 次),因此频繁写入应避免直接使用 Flash,建议使用外部 EEPROM 或 FRAM。 2. **页大小与擦除单位**:STM32H750 的 Flash 通常以 128KB 或 256KB 为一个扇区,擦除操作必须按整个扇区进行。 3. **双 Bank 模式**:在双 Bank 模式下,可以实现 XIP(Execute In Place)模式,即直接在 Flash 中执行代码的同时更新另一部分 Flash 的内容。 4. **安全机制**:Flash 支持读保护(RDP)、写保护(WRP)等功能,防止未经授权的访问修改。 ### Flash 编程与调试 在开发过程中,推荐使用 Keil µVision 或 STM32CubeIDE 进行 Flash 编程。若需提高开发效率,也可以使用 VSCode 编写代码,再通过 Keil 编译下载。VSCode 提供更强大的代码补全导航功能,尤其适合大型项目[^2]。 ### 示例代码:Flash 擦除与写入 以下是一个简单的 Flash 操作示例,基于 HAL 库进行擦除写入操作: ```c #include "stm32h7xx_hal.h" #define FLASH_USER_START_ADDR ADDR_FLASH_SECTOR_8 /* Base address of Bank 1, Sector 8 */ #define DATA_32 0x12345678 void Flash_Write_Test(void) { uint32_t Address = FLASH_USER_START_ADDR; uint32_t PageError = 0; FLASH_EraseInitTypeDef eraseInitStruct; HAL_FLASH_Unlock(); eraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS; eraseInitStruct.Sector = FLASH_SECTOR_8; eraseInitStruct.NbSectors = 1; eraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3; if (HAL_FLASHEx_Erase(&eraseInitStruct, &PageError) != HAL_OK) { // 错误处理 } if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, DATA_32) != HAL_OK) { // 写入失败处理 } HAL_FLASH_Lock(); } ``` 上述代码展示了如何解锁 Flash、擦除指定扇区并写入一个 32 位数据的过程。擦除写入操作前必须调用 `HAL_FLASH_Unlock()`,完成后应调用 `HAL_FLASH_Lock()` 以防止意外修改
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值