在单片机中,片内Flash的地址表示方法通常与芯片架构和内存映射方式有关。以下是常见的表示方法及注意事项:
1. 片内Flash地址的基本概念
单片机的Flash存储器用于存储程序代码(Code)、常量数据(const)或用户数据(如EEPROM模拟)。其地址表示方式一般遵循以下规则:
(1) 绝对地址(物理地址)
由芯片厂商定义,在数据手册(Datasheet)或参考手册(Reference Manual)中给出。
例如:
STM32F103 的Flash起始地址为 0x08000000。
ATmega328P 的Flash起始地址为 0x0000(16位地址,但实际物理地址可能更复杂,因为AVR采用哈佛架构)。
(2) 相对地址(偏移地址)
某些情况下,开发者可能使用相对于Flash起始地址的偏移量:
#define FLASH_BASE 0x08000000 // STM32的Flash起始地址
uint32_t* data_address = (uint32_t*)(FLASH_BASE + 0x1000); // 偏移4KB
2. 不同架构的Flash地址表示
(1) ARM Cortex-M(如STM32)
Flash通常映射到 0x08000000(默认启动地址)。
示例:
// 访问Flash的某个地址(如读取前4字节)
uint32_t* flash_addr = (uint32_t*)0x08000000;
uint32_t value = *flash_addr; // 读取数据
(2) AVR(如ATmega系列)
Flash地址是 16位 的(但实际物理地址可能更大,因为Flash可能超过64KB)。
需要使用 pgm_read_byte() 或 pgm_read_word() 访问:
#include
const uint8_t data[] PROGMEM = {0x01, 0x02, 0x03}; // 数据存储在Flash
uint8_t value = pgm_read_byte(&data[0]); // 读取第一个字节
(3) 8051
Flash(CODE空间)通常用 16位地址 访问。
使用 code 关键字定义常量:
uint8_t code my_data[] = {0x01, 0x02, 0x03}; // 数据存储在Flash
uint8_t value = my_data[0]; // 读取数据
3. 如何获取Flash地址?
(1) 查看芯片数据手册
例如:
STM32F103:Flash起始于 0x08000000,每个扇区大小可能为 1KB/2KB。
ATmega328P:Flash起始于 0x0000,但实际物理地址可能涉及分页。
(2) 使用厂商提供的宏
STM32 HAL库提供 FLASH_BASE:
#define FLASH_BASE 0x08000000
(3) 通过链接脚本(Linker Script)定义
在 *.ld 文件中定义Flash的起始和大小:
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
}
4. 常见操作
(1) 读取Flash数据
// STM32示例
uint32_t read_flash(uint32_t address) {
return *(__IO uint32_t*)address;
}
(2) 写入Flash(需解锁+擦除+编程)
// STM32 HAL库示例
HAL_FLASH_Unlock();
FLASH_Erase_Sector(FLASH_SECTOR_1, VOLTAGE_RANGE_3);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x08010000, 0x12345678);
HAL_FLASH_Lock();
(3) 检查Flash是否为空(通常擦除后为0xFF)
bool is_flash_empty(uint32_t address, uint32_t size) {
uint8_t* ptr = (uint8_t*)address;
for (uint32_t i = 0; i < size; i++) {
if (ptr[i] != 0xFF) return false;
}
return true;
}
5. 注意事项
对齐访问:
ARM Cortex-M 通常要求 32位/64位对齐访问,否则可能触发 HardFault。
写保护:
写入Flash前需解锁,并确保目标地址已擦除(通常全为 0xFF)。
哈佛架构(如AVR):
Flash和RAM地址空间独立,不能直接用指针访问,需使用 pgm_read_* 函数。
优化编译:
常量数据可能被编译器优化到Flash,使用 const + PROGMEM(AVR)或 __attribute__((section(".rodata")))(ARM)确保存储位置。
总结
架构Flash起始地址访问方式STM320x08000000直接指针访问AVR0x0000(逻辑)pgm_read_byte/word80510x0000code 关键字
正确理解Flash地址表示方法对固件开发、Bootloader、OTA升级等至关重要,务必参考芯片手册!