Naming conventions and optional features for accessing peripherals.
More...
|
#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...
|
|
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 {
} 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:
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_STATUSR;
__I uint32_t RESERVED1[40];
__IOM uint32_t C_NSAPR[4];
__I uint32_t RESERVED2[3];
__I uint32_t RESERVED3[960];
- 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.
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.
#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.
#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:
#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: