提高移植性的建议
抽象存储位置:
- #if defined(__C51__) || defined(SDCC) // 8051
- #define FLASH_CONST code const
- #elif defined(__XC8__) || defined(__XC16__) || defined(__XC32__) // PIC
- #define FLASH_CONST const __flash // 根据具体XC编译器调整
- #elif defined(__AVR__) // AVR
- #include <avr/pgmspace.h>
- #define FLASH_CONST const PROGMEM
- #elif defined(__MSP430__) // MSP430-GCC, TI CCS (通常不需要特殊修饰符)
- #define FLASH_CONST const // 大多数情况下 const 就够了
- // 对于IAR可能需要单独处理
- #else // 标准C环境 (如x86, ARM Cortex未指定嵌入式)
- #define FLASH_CONST const
- #endif
- // 使用
- FLASH_CONST uint8_t MyArray[] = {1, 2, 3};
抽象访问方式:
- #if defined(__AVR__)
- #include <avr/pgmspace.h>
- #define READ_FLASH_BYTE(addr) pgm_read_byte(addr)
- #define READ_FLASH_WORD(addr) pgm_read_word(addr)
- #elif defined(__C51__) || defined(SDCC) || defined(__XC8__) || defined(__XC16__) || defined(__XC32__) || defined(__IAR_SYSTEMS_ICC__)
- // 8051, PIC, IAR MSP430:编译器通常能直接生成正确访问代码或提供透明访问
- // 如果编译器能正确处理 FLASH_CONST 定义的类型,直接访问即可
- #define READ_FLASH_BYTE(addr) (*(const uint8_t *)(addr))
- #define READ_FLASH_WORD(addr) (*(const uint16_t *)(addr))
- #else // MSP430-GCC, TI CCS, 标准环境
- // 统一编址或标准环境,直接访问
- #define READ_FLASH_BYTE(addr) (*(const uint8_t *)(addr))
- #define READ_FLASH_WORD(addr) (*(const uint16_t *)(addr))
- #endif
- // 使用
- uint8_t val = READ_FLASH_BYTE(&MyArray[index]);
字符串常量:
在AVR上坚持使用 F()。
在其他平台,可以定义一个空宏 #define F(str) (str) 或者更智能的宏来兼容。
或者直接使用 const char * 并依赖编译器的优化(在非AVR平台上可能没问题)。
优先使用标准 const: 在明确知道目标平台编译器将 const 放入Flash(如MSP430-GCC, CCS, 现代XC编译器高优化等级)且性能可接受时,优先只用 const 以简化代码。
文档和注释: 清晰注释常量预期的存储位置和访问方式。
编译器文档: 始终查阅目标平台和编译器的具体文档,了解 const 的确切行为和推荐的常量定义方式。
|