![]() |
RA Flexible Software Package Documentation
Release v5.9.0
|
|
In some cases users may wish to utilize chip functionality that is not supported yet by FSP. While we encourage contacting us when new feature requests arise it takes time before any updates are made. In the meantime, it is recommended to use the register definition files accessed via renesas.h
to add custom functionality as needed. Official ARM CMSIS documentation refers to this format of related register definition files as device header files. Within Renesas, these files are often referred to as an IO define or more commonly iodefine.
Iodefine files contain definitions for all the I/O registers on a device. For RA FSP, one iodefine header is provided per device group (RA6M3, RA2A1 etc.) that contains all the register definitions provided in the hardware manual for that group. These headers are accessed via renesas.h
, which selects the appropriate file based on the MCU configured in the project.
renesas.h
contained a superset of all register definitions for RA MCUs. This became unsustainable as new device families were added and was confusing for users, so headers for each device were created and renesas.h
was updated to serve as a selector.In RA FSP, iodefine files are stored in ra/fsp/src/bsp/cmsis/Device/RENESAS/Include
. This includes both renesas.h
as well as the device group specific iodefine headers.
Each peripheral register set is provided as a struct. In general, the template to follow is:
Registers are most commonly accessed whole. For example, say we want to read the counter on GPT channel 3:
As shown in the template, the iodefines can also be used to access bitfields. For example, to start GPT channel 3:
It is worth noting that each bitfield access will cause a full read-modify-write which cannot be combined by the compiler because the register definitions are by necessity volatile
. This can be very size and speed inefficient, particularly when the peripheral is on a very slow clock. It is recommended to write whole registers wherever possible. This is made easier by macros that are provided alongside the register definitions.
Every bitfield has two associated macros: _Msk
(bitfield mask) and _Pos
(bit position). These macros can be used to manipulate whole registers instead of using bitfield access when multiple bitfields are modified simultaneously. For example, setting both GPT3 output pins to 100% duty cycle:
Some registers are part of an array. These are typically listed in the manual using indexes like "n" or "m", but may occasionally be listed with individual numbers or letters. Accessing register arrays is just like accessing a regular array. For example, the GPT duty cycle registers are GTCCRA through GTCCRF. In the iodefine, they are accessed via the GTCCR array:
Sometimes there are groups of registers that are repeated multiple times. These groups are called a cluster. Clusters are accessed similarly to arrays, except the actual registers are elements of the array values instead. For example, mailboxes in the CAN peripheral have several registers each:
FSP drivers often calculate a register offset in the Open function. This is typically done by multiplying the channel by the offset between channels 0 and 1. For example, here is the calculation for GPT:
When drivers need to support multiple channels of a peripheral it can be helpful to save the offset in a persistent variable or structure so that it only needs to be calculated once.