STM32 的 Flash 通常用于存储用户程序(代码和常量数据)。例如,一个 STM32F103 系列的微控制器可能有 128KB 的 Flash,其中前 64KB 被应用程序占用,剩下的 64KB 可以用作模拟 E2PROM:
0x08000000 - 0x0800FFFF:应用程序代码(64KB)
0x08010000 - 0x0801FFFF:模拟E2PROM(64KB)
Flash 页大小与对齐
Flash 操作通常以页(Page)为单位进行擦除。不同 STM32 型号的 Flash 页大小可能不同:
- STM32F1 系列:通常 1KB / 页
- STM32F4 系列:通常 16KB / 页
- STM32L0 系列:通常 128 字节 / 页
为了保证模拟 E2PROM 区域从完整的页边界开始,起始地址需要是页大小的整数倍。例如:
- 对于 1KB 页大小的设备,起始地址应是 0x1000(4096 字节)的倍数
- 对于 16KB 页大小的设备,起始地址应是 0x4000(16384 字节)的倍数
0x08010000
是 1KB、2KB、4KB、8KB、16KB 等常见页大小的整数倍,因此具有良好的通用性。
在 STM32 的 Flash 编程中,"写入操作通常要求地址和数据大小对齐" 是一个重要的约束条件,这涉及到底层硬件的工作机制。下面详细解释这个概念及其实际影响。
一、什么是地址对齐?
地址对齐指的是内存访问地址必须是数据类型大小的整数倍。例如:
- 8 位数据(1 字节):可以从任意地址开始(无需对齐)
- 16 位数据(2 字节,半字):地址必须是 2 的倍数(如
0x08000000
、0x08000002
) - 32 位数据(4 字节,字):地址必须是 4 的倍数(如
0x08000000
、0x08000004
)
如果地址不满足对齐要求,会导致:
- 硬件异常:某些架构直接禁止非对齐访问
- 性能下降:处理器需要多次访问内存来拼凑数据
- 数据错误:写入的数据可能被截断或错位
二、STM32 Flash 写入的对齐要求
STM32 的 Flash 编程接口对写入操作有严格的对齐要求:
1. 数据类型与对齐关系
操作函数 | 数据大小 | 地址对齐要求 |
---|---|---|
FLASH_ProgramByte() |
8 位 | 任意地址 |
FLASH_ProgramHalfWord() |
16 位 | 地址必须是 2 的倍数 |
FLASH_ProgramWord() |
32 位 | 地址必须是 4 的倍数 |
FLASH_ProgramDoubleWord() |
64 位 | 地址必须是 8 的倍数(仅部分型号支持) |
2. 为什么有对齐要求?
- 硬件设计限制:Flash 控制器内部按字(32 位)组织数据,非对齐访问需要额外处理
- 写入效率:对齐的写入操作可以一次性完成,非对齐则需要多次操作
- 数据完整性:确保数据按正确边界写入
三、实际影响与示例
1. 错误示例
以下代码会导致错误,因为地址0x08010001
不是 4 的倍数:
// 错误!地址0x08010001不是4的倍数
FLASH_ProgramWord(0x08010001, 0x12345678);
2. 正确示例
确保地址对齐:
// 正确!地址0x08010000是4的倍数
FLASH_ProgramWord(0x08010000, 0x12345678);
// 正确!地址0x08010002是2的倍数
FLASH_ProgramHalfWord(0x08010002, 0x5678);
3. 动态计算对齐地址
在实际应用中,可通过位运算确保地址对齐:
// 将address向上对齐到4的倍数
uint32_t aligned_address = (address + 3) & ~0x03;
// 示例:
// address = 0x08010001 → aligned_address = 0x08010004
// address = 0x08010004 → aligned_address = 0x08010004
四、模拟 E2PROM 中的对齐处理
在模拟 E2PROM 时,由于 Flash 写入前需要擦除整页,通常会设计数据结构来确保对齐:
// 定义按4字节对齐的结构体
typedef __packed struct {
uint32_t id; // 变量ID
uint32_t value; // 变量值
} EEPROM_Variable;
// 写入操作示例
void EEPROM_WriteVariable(uint32_t address, uint32_t id, uint32_t value) {
EEPROM_Variable var = {id, value};
FLASH_ProgramWord(address, *(uint32_t*)&var); // 确保address是4的倍数
}
五、总结
对齐规则:
- 写入数据时,地址必须是数据大小的整数倍
- 例如 32 位写入要求地址为
XXXXXX00
(二进制)
检查方法:
// 判断地址是否对齐 if ((address % 4) == 0) { // 32位对齐 // 地址有效 } else { // 地址无效,需要调整 }
最佳实践:
- 从页边界开始分配 E2PROM 空间
- 使用结构体和数组组织数据,确保自然对齐
- 在写入前检查地址有效性
- 避免跨页写入,防止数据碎片化
理解并遵守对齐规则是 Flash 编程的基础,违反这些规则可能导致难以调试的问题(如数据丢失、硬件错误)。