CMSIS-Core (Cortex-A): Peripheral Access

| CMSIS-Core (Cortex-A) Version 1.0.0 CMSIS-Core support for Cortex-A processor-based devices

- Main Page
- Usage and Description
- Reference

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Macros
Peripheral Access

Naming conventions and optional features for accessing peripherals. More...

## Macros
#define | _VAL2FLD(field, value)
| Mask and shift a bit field value for assigning the result to a peripheral register. More...
#define | _FLD2VAL(field, value)
| Extract from a peripheral register value the a bit field value. More...

## Description

The section below describes the naming conventions, requirements, and optional features for accessing device specific peripherals. Most of the rules also apply to the core peripherals. The Device Header File <device.h> contains typically these definition and also includes the core specific header files.

The definitions for Peripheral Access can be generated using the CMSIS-SVD System View Description for Peripherals. Refer to SVDConv.exe for more information.

Each peripheral provides a data type definition with a name that is composed of:

- an optional prefix <device abbreviation>_
- <peripheral name>
- postfix _Type or _TypeDef to identify a type definition.

Examples:

- UART_TypeDef for the peripheral UART.
- IMX_UART_TypeDef for the device family IMX and the peripheral UART.

The data type definition uses standard C data types defined by the ANSI C header file <stdint.h>.

- IO Type Qualifiers are used to specify the access to peripheral variables.

  IO Type Qualifier | Type | Description
  --- | --- | ---
  __IM | Struct member | Defines 'read only' permissions
  __OM | Struct member | Defines 'write only' permissions
  __IOM | Struct member | Defines 'read / write' permissions
  __I | Scalar variable | Defines 'read only' permissions
  __O | Scalar variable | Defines 'write only' permissions
  __IO | Scalar variable | Defines 'read / write' permissions

  The typedef <device abbreviation>_UART_TypeDef shown below defines the generic register layout for all UART channels in a device.

typedef struct {
__O uint32_t UART_CR; // Offset: 0x0000 ( /W) Control Register
__IO uint32_t UART_MR; // Offset: 0x0004 (R/W) Mode Register
__O uint32_t UART_IER; // Offset: 0x0008 ( /W) Interrupt Enable Register
__O uint32_t UART_IDR; // Offset: 0x000C ( /W) Interrupt Disable Register
__I uint32_t UART_IMR; // Offset: 0x0010 (R/ ) Interrupt Mask Register
__I uint32_t UART_SR; // Offset: 0x0014 (R/ ) Status Register
__I uint32_t UART_RHR; // Offset: 0x0018 (R/ ) Receive Holding Register
__O uint32_t UART_THR; // Offset: 0x001C ( /W) Transmit Holding Register
__IO uint32_t UART_BRGR; // Offset: 0x0020 (R/W) Baud Rate Generator Register
__IO uint32_t UART_CMPR; // Offset: 0x0024 (R/W) Comparison Register
__IO uint32_t UART_RTOR; // Offset: 0x0028 (R/W) Receiver Time-out Register
__I uint32_t RESERVED[46]; // Offset: 0x002C (R/ ) Reserved
__IO uint32_t UART_WPMR; // Offset: 0x00E4 (R/W) Write Protection Mode Register
} IMX_UART_TypeDef;

To access the registers of the UART defined above, pointers to this register structure are defined. If more instances of a peripheral exist, the variables have a postfix (digit or letter) that identifies the peripheral.

Example: In this example, IMX_UART2 and IMX_UART3 are two pointers to UARTs defined with above register structure.

#define IMX_UART2 ((IMX_UART_TypeDef *) IMX_UART2_BASE)
#define IMX_UART3 ((IMX_UART_TypeDef *) IMX_UART3_BASE)

Note
  - The prefix IMX is optional.

The registers in the various UARTs can now be referred in the user code as shown below:

val = IMX_UART2->SR // is the Status Register of UART2.

# Minimal Requirements

To access the peripheral registers and related function in a device, the files device.h and core_ca.h define as a minimum:

- The Register Layout Typedef for each peripheral that defines all register names. RESERVED is used to introduce space into the structure for adjusting the addresses of the peripheral registers.
  Example:
  typedef struct
  {
  __IOM uint32_t C_CTLR; // Offset: 0x0000 (R/W) CPU Interface Control Register
  __IOM uint32_t C_PMR; // Offset: 0x0004 (R/W) Interrupt Priority Mask Register
  __IOM uint32_t C_BPR; // Offset: 0x0008 (R/W) Binary Point Register
  __IM uint32_t C_IAR; // Offset: 0x000C (R/ ) Interrupt Acknowledge Register
  __OM uint32_t C_EOIR; // Offset: 0x0010 ( /W) End Of Interrupt Register
  __IM uint32_t C_RPR; // Offset: 0x0014 (R/ ) Running Priority Register
  __IM uint32_t C_HPPIR; // Offset: 0x0018 (R/ ) Highest Priority Pending Interrupt Register
  __IOM uint32_t C_ABPR; // Offset: 0x001C (R/W) Aliased Binary Point Register
  __IM uint32_t C_AIAR; // Offset: 0x0020 (R/ ) Aliased Interrupt Acknowledge Register
  __OM uint32_t C_AEOIR; // Offset: 0x0024 ( /W) Aliased End Of Interrupt Register
  __IM uint32_t C_AHPPIR; // Offset: 0x0028 (R/ ) Aliased Highest Priority Pending Interrupt Register
  __IOM uint32_t C_STATUSR; // Offset: 0x002C (R/W) Error Reporting Status Register, optional
  __I uint32_t RESERVED1[40]; // Offset: 0x0030 (R/ ) Reserved
  __IOM uint32_t C_APR[4]; // Offset: 0x00D0 (R/W) Active Priority Register
  __IOM uint32_t C_NSAPR[4]; // Offset: 0x00E0 (R/W) Non-secure Active Priority Register
  __I uint32_t RESERVED2[3]; // Offset: 0x00F6 (R/ ) Reserved
  __IM uint32_t C_IIDR; // Offset: 0x00FC (R/ ) CPU Interface Identification Register
  __I uint32_t RESERVED3[960]; // Offset: 0x0100 (R/ ) Reserved
  __OM uint32_t C_DIR; // Offset: 0x1000 ( /W) Deactivate Interrupt Register
  } GICInterface_Type;
- Base Address for each peripheral (in case of multiple peripherals that use the same register layout typedef multiple base addresses are defined).
  Example:
  #define GIC_INTERFACE_BASE (0xe8202000UL) // GIC Interface Base Address
- Access Definitions for each peripheral. In case of multiple peripherals that are using the same register layout typedef, multiple access definitions exist.
  Example:
  #define GICInterface ((GICInterface_Type *) GIC_INTERFACE_BASE) // GIC Interface Access Definition

These definitions allow accessing peripheral registers with simple assignments.

- Example:
  GICInterface->C_CTLR |= 1; // Enable Interface

# Optional Features

Optionally, the file device.h may define:

- Register Bit Fields and #define constants that simplify access to peripheral registers. These constants may define bit-positions or other specific patterns that are required for programming peripheral registers. The identifiers should start with <device abbreviation>_ and <peripheral name>_. It is recommended to use CAPITAL letters for #define constants.
- More complex functions (i.e. status query before a sending register is accessed). Again, these functions start with <device abbreviation>_ and <peripheral name>_.

# Register Bit Fields

For Core Register, macros define the position and the mask value for a bit field.

Example:

Bit field definitions for register ACTLR in CP15.

// CP15 Register ACTLR
#define ACTLR_DDI_Pos 28U
#define ACTLR_DDI_Msk (1UL << ACTLR_DDI_Pos)
#define ACTLR_DDVM_Pos 15U
#define ACTLR_DDVM_Msk (1UL << ACTLR_DDVM_Pos)
#define ACTLR_L1PCTL_Pos 13U
#define ACTLR_L1PCTL_Msk (3UL << ACTLR_L1PCTL_Pos)
#define ACTLR_L1RADIS_Pos 12U
#define ACTLR_L1RADIS_Msk (1UL << ACTLR_L1RADIS_Pos)
#define ACTLR_L2RADIS_Pos 11U
#define ACTLR_L2RADIS_Msk (1UL << ACTLR_L2RADIS_Pos)
#define ACTLR_DODMBS_Pos 10U
#define ACTLR_DODMBS_Msk (1UL << ACTLR_DODMBS_Pos)
#define ACTLR_SMP_Pos 6U
#define ACTLR_SMP_Msk (1UL << ACTLR_SMP_Pos)

The macros _VAL2FLD(field, value) and _FLD2VAL(field, value) enable access to bit fields.

## Macro Definition Documentation

#define _FLD2VAL | ( |  | field,
|  |  | value
| ) |  |

Parameters

  field | name of bit field.
  value | value of the register. This parameter is interpreted as an uint32_t type.

The macro _FLD2VAL uses the #define's _Pos and _Msk of the related bit field to extract the value of a bit field from a register.

Example:

i = _FLD2VAL(ACTLR_SMP, ACTLR);

#define _VAL2FLD | ( |  | field,
|  |  | value
| ) |  |

Parameters

  field | name of bit field.
  value | value for the bit field. This parameter is interpreted as an uint32_t type.

The macro _VAL2FLD uses the #define's _Pos and _Msk of the related bit field to shift bit-field values for assigning to a register.

Example:

ACTLR = _VAL2FLD(ACTLR_SMP, 0x1)