Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
CAN CSA ISO/IEC TR 18037-09 (2014) 是加拿大标准协会(CSA)采纳并确认的 ISO/IEC TR 18037:2008 正式版本,其完整名称为《信息技术 — 编程语言 — C — 支持嵌入式处理器的扩展》。本标准于2009年首次发布,并于2014年经CSA确认沿用,是嵌入式软件开发者不可或缺的技术参考资料。
该标准的核心目标是为 C 语言提供一套可选的扩展机制,使其能够更自然、高效地表达嵌入式系统中常见的底层操作,主要涵盖以下三大领域:
_Fract、_Accum 等数据类型以及饱和、舍入等语义,为无浮点单元的微控制器提供高精度数值运算能力。_Space 实现对片上存储器、外部总线的直接控制。_IO、_SPACE 等关键字,规范寄存器的声明与访问,支持对中断、外设接口的直接操作。本技术报告适用于所有需要在资源受限、实时性要求高的嵌入式环境中使用 C 语言的开发者,尤其是需要直接操作硬件寄存器、使用定点算法(如数字信号处理、控制算法)的场景。需要强调的是,这些扩展并非强制性要求,而是为编译器实现提供的可选规范,旨在促进不同嵌入式编译器之间的功能一致性。
标准定义了一组定点数据类型,包括有符号/无符号的 _Fract(纯小数)和 _Accum(整数+小数),以及可选的 _Sat 饱和限定符。每个类型有固定的位宽(如 16 位、32 位),其小数位数由实现定义,但标准提供了推荐的布局规则。下表总结了常用定点类型的典型特性(基于 32 位示例):
| 类型 | 位数 | 整数部分(位) | 小数部分(位) | 值范围 |
|---|---|---|---|---|
_Fract | 16 | 0 | 15 | [-1, 1-2-15] |
_Accum | 32 | 16 | 15 | [-215, 215-2-15] |
unsigned _Fract | 16 | 0 | 16 | [0, 1-2-16] |
unsigned _Accum | 32 | 16 | 16 | [0, 216-2-16] |
定点运算支持用 _Sat 表示饱和(溢出时取最大/最小值),并定义了四舍五入(_Round)或向零截断等模式。这些机制使编译器能够在不引入浮点指令的情况下生成高效的定点代码,同时保证行为的一致性。
嵌入式系统常采用哈佛架构或多级存储器层次,标准通过 _Space 类型限定符让程序员显式指定变量所属的存储区域,例如:
_Space(_FLASH) const int coeff[256];
对于外设寄存器,标准引入 _IO 关键字,指示编译器该变量可能被硬件或中断修改,禁止某些优化。典型的声明方式如下:
_IO volatile unsigned int * const UART_STATUS = (_IO unsigned int *)0x40004000;
结合命名地址空间,可进一步限定寄存器位于特殊功能寄存器空间(如 _SFR),从而实现跨编译器的可移植性。
首先确认编译器支持 _Fract、_Accum 等关键字。如果支持,可在性能关键代码(如控制环路、滤波器)中使用定点类型替代浮点,设置合适的舍入模式。建议为每个模块定义专有的定点类型(例如 typedef _Fract fract16_t;),便于统一调整字长。同时注意标准中的运算规则:混合不同定点类型时,自动转换遵循“保留精度”原则,但最好显式强制转换以避免二义性。
对于哈佛架构 MCU(如 8051、AVR、某些 PIC),将常量数据指定在程序存储空间(如 _Space(_CODE))可大幅节省 RAM。在编写外设驱动时,利用 _IO 和 _SPACE 的组合清晰区分普通变量与硬件寄存器,并借助 volatile 防止编译器优化掉必要的多字节读/写操作。注意:不要对 _IO 对象使用“读-修改-写”以外的原子操作,除非硬件保证;必要时应使用 RTOS 提供的同步机制。
CAN CSA ISO/IEC TR 18037-09 (2014) 是 ISO/IEC 9899(C语言标准)的补充技术报告,旨在探索未来 C 标准可吸纳的嵌入式特性。它的部分内容(尤其是定点算术的概念)影响了后来 C2x 标准的制定讨论。此外,它与以下标准或规范密切相关:
_Pragma、属性语法有相似目标,体现了嵌入式领域语言功能的共性需求。总之,本报告为嵌入式 C 语言提供了一套实用的“方言”,它填补了标准 C 在硬件亲密性上的空白,同时也为未来语言演进积累了宝贵经验。
_Accum 类型的运算会保留中间结果的小数部分,而纯整数计算需要程序员自行维护比例因子。_BitInt 用于精确宽度整数),但未直接引入定点类型。因此,TR 18037 仍作为专门的嵌入式扩展存在,需要编译器单独支持。_Fract 关键字,可以使用标准 C 的宏和函数库手动模拟定点运算,但会损失性能与可读性。另一种方法是选择已实现 TR 18037 的嵌入式编译器(如 Tasking、IAR、Keil 等),或者查阅编译器厂商是否提供了等效的非标准扩展。_Space 可以指导编译器生成更高效的指令(如 avr-gcc 中的 __flash),但滥用可能导致代码膨胀或链接错误。通常建议仅对大型常量表和特殊寄存器使用,并在链接脚本中定义相应的地址空间段。调试时需注意逻辑地址与物理地址的映射关系。