CAN/CSA-ISO/IEC TR 18037-09 (R2014): C Extensions for Embedded Processor Support — Scope and Implementation Guide

An Overview of the Fixed-Point Arithmetic and Address Space Extensions Standard for Embedded C Programming

The CAN/CSA-ISO/IEC TR 18037-09 (R2014) is the Canadian adoption of the international Information technology — Programming languages — C — Extensions to support embedded processors technical report. Published originally in 2009 and reaffirmed in 2014 by the Canadian Standards Association (CSA), this document provides essential guidance for extending the standard C language to meet the specific demands of embedded systems development. It defines new data types for fixed-point arithmetic, introduces named address spaces for accessing different memory regions, and outlines minimal I/O operations — all aimed at improving code portability and efficiency across a wide range of microcontrollers and embedded processors.

Scope and Purpose

The scope of TR 18037 is to extend the C programming language (as defined by ISO/IEC 9899:1999, C99) with features that directly support embedded processor hardware. The extensions address common challenges in programming resource-constrained devices:

  • Fixed-point arithmetic — Provides fractional and accumulative data types that allow efficient real-time control without floating-point units.
  • Named address spaces — Enable precise placement of variables in specific memory areas (e.g., program flash, external RAM, I/O space).
  • Basic I/O operations — Offer unified access to memory-mapped I/O and peripheral registers.
  • Implementation-defined behaviour — Documents necessary compiler and platform choices to maintain portability.

The document is a Technical Report (TR), meaning it provides guidance rather than mandatory requirements. However, it has been widely adopted by compiler vendors as a de facto standard for embedded C extensions.

Technical Requirements

TR 18037 introduces a set of optional extensions that a conforming implementation may support. The core technical additions from the report are categorized below.

Fixed-Point Data Types

The standard defines two families of fixed-point types: fractional (_Fract) and accumulative (_Accum). These types represent signed or unsigned fixed-point numbers with a specified integer and fractional bit count. Key characteristics include:

Tip: Fixed-point types avoid the overhead of floating-point units while still providing fractional precision, making them ideal for digital signal processing (DSP) and control loops in low-power microcontrollers.

The following table summarises the basic fixed-point types as defined by the report (typical 32-bit implementation shown):

Type Signedness Format (bits) Approximate Range Resolution
_Fract Unsigned / Signed 1.15 / 1.0.15 [-1.0, 1.0) ~3.05e-5
_Accum Unsigned / Signed 8.8 / 8.8 (or 16.16) [-256.0, 255.996) or larger ~3.9e-3 (8.8) / ~1.5e-5 (16.16)
_Sat modifier Applies to any fixed-point type Clamps to max/min

Modifiers such as _Sat (saturation), unsigned, and explicit bit-width suffixes (_Fract32, _Accum32) allow tuning of range and precision. The standard also mandates a set of conversion rules, rounding modes (to nearest, toward zero, etc.), and overflow handling (wrap or saturate).

Named Address Spaces

Named address spaces extend the C syntax so that developers can place objects in specific hardware memory regions. This is critical for Harvard-architecture devices (e.g., many microcontrollers) where program memory and data memory are separate. Common spaces include:

  • __flash — Read-only data stored in program space.
  • __xdata — External data memory.
  • __idata, __pdata — Internal or paged data memory.
  • __io — Memory-mapped I/O registers (with possible side effects).
Warning: Named address spaces are highly platform-dependent. A program written for AVR __flash may not compile for ARM Cortex-M without modification. The TR provides guidance on defining custom spaces, but actual syntax varies among compilers.

Basic I/O Operations

The report defines a small set of intrinsics for reading and writing to memory-mapped I/O ports and registers. These operations guarantee access atomicity (where applicable) and inhibit optimisations that might reorder or eliminate I/O accesses. Typical operations include:

  • __readb(address) — Read a byte from an I/O address.
  • __writeb(value, address) — Write a byte to an I/O address.
  • Similar forms for half-word and word sizes (__readw, __writew, etc.).

These operations are optional; compilers that support TR 18037 may use alternative built-in functions or volatile-qualified pointers to achieve the same effect.

Implementation Highlights

TR 18037 serves as a blueprint for compiler extension design. Many embedded toolchains, including GCC (through fixed-point built-ins and named address space attributes) and commercial compilers from IAR, ARM, and Renesas, have implemented parts of the report.

Success: By adopting the TR 18037 extensions, development teams can write portable embedded C code across different platforms, reducing the need for assembly language or hardware-dependent macros.

Key implementation considerations:

  • Fixed-point arithmetic — Compilers generate inline code or call library routines for fixed-point operations. Efficient implementations use integer instructions with explicit scaling.
  • Named address spaces — Typically handled via separate ISA instructions (e.g., LPM on AVR, LDR on ARM with appropriate segment qualifiers).
  • Optimisation — The report warns against optimisations that break strict aliasing or reorder pointer-based I/O accesses.
  • Test suites — Although not part of the TR, conformance can be verified using proprietary test suites or the open-source “TR 18037 conformance test” from some compiler vendors.

Compliance Notes

Because TR 18037 is a Technical Report and not a full International Standard, “compliance” is interpreted as conformance to the report’s specifications. Compilers that claim support for the extensions should follow the semantics described in the document. Points to verify when evaluating compliance include:

  1. Fixed-point keyword presence — Do _Fract, _Accum, and _Sat compile as expected?
  2. Address space qualifiers — Are the predefined spaces recognised and do they affect code generation correctly?
  3. I/O intrinsic functions — Does the implementation provide the recommended accessors (or an equivalent mechanism)?
  4. Conversion and overflow behaviour — Verify that rounding and saturation work according to the report’s tables.
Danger: Mixing fixed-point types without explicit rounding or saturation can lead to subtle precision loss. Always check the compiler’s fixed-point ABI and ensure consistent use of saturation across the codebase.

For CSA adoption, compliance with CAN/CSA-ISO/IEC TR 18037-09 (R2014) means that the product or tool claims to adhere to the requirements of ISO/IEC TR 18037:2009 (E) as corrected by its technical corrigenda. Users should consult the latest version of the ISO/IEC report for errata and amendments.

Q: Are the TR 18037 extensions part of the C11 or C23 standard?
A: No. The extensions described in TR 18037 remain separate from ISO/IEC 9899 (the C standard). However, some ideas have influenced embedded-specific additions to later C standards, such as the _Atomic qualifier and generic selections. Most compiler vendors implement the TR independently.
Q: Which compilers currently support TR 18037?
A: GCC provides fixed-point support (enabled with -ffixed-point) and named address space extensions via attributes. IAR Embedded Workbench, ARM Compiler 5/6, and Renesas CC-RX also offer partial support. Not all features are uniformly implemented; check the specific compiler manual.
Q: How do fixed-point types differ from integer scaling?
A: Fixed-point types in TR 18037 are first-class data types with overloading of arithmetic operators, automatic conversion, and dedicated overflow modes (wrap or saturate). Integer scaling requires manual shift operations and explicit overflow detection, making the code less readable and more error-prone.
Q: Can I use TR 18037 extensions in a hosted (non-embedded) environment?
A: Technically yes, but the extensions are designed for embedded contexts. Most hosted compilers do not implement them because they lack the low-level memory models. For cross-platform code, fall back to integer scaling or libraries.

Last reviewed: 2026. This article is based on CAN/CSA-ISO/IEC TR 18037-09 (R2014) and ISO/IEC TR 18037:2009. Always refer to the official CSA document for authoritative requirements.

📥 Standard Documents Download

🔒
Please wait 10 seconds, the download links will appear after the ad loads

Leave a Reply

Your email address will not be published. Required fields are marked *