Closed m-kru closed 1 week ago
@gusthoff ping
Hello @m-kru,
To modify multiple components in a single assignment, you can use delta aggregates, see here:
https://learn.adacore.com/courses/advanced-ada/parts/data_types/aggregates.html#delta-aggregates
For example:
pragma Ada_2022;
with Registers; use Registers;
procedure Main is
R : PMC_SCER_Register;
begin
-- Initializing the registers
R := (USBCLK0 => 1,
USBCLK1 => 1,
USBCLK2 => 1,
others => <>);
-- Modifying only USBCLK0 and USBCLK2 registers
R := (R with delta USBCLK0 => 0, USBCLK2 => 0);
end Main;
Note that delta aggregates are an Ada 2022 feature.
Also, to ensure that you write all bits of the record at once, you can add GNAT's Volatile_Full_Access
aspect to the record declaration:
[...] any reference to the object is guaranteed to be done only with instructions that read or write all the bits of the object. Furthermore, if the object is of a composite type, then any reference to a subcomponent of the object is guaranteed to read and/or write all the bits of the object.
https://gcc.gnu.org/onlinedocs/gnat_rm/Pragma-Volatile_005fFull_005fAccess.html
Alternatively, you can use the Full_Access_Only
aspect introduced in Ada 2022:
All reads of or writes to any nonatomic subcomponent of a full access object are performed by reading and/or writing all of the nearest enclosing full access object.
Annotated Ada Reference Manual, C.6: http://www.ada-auth.org/standards/22aarm/html/AA-C-6.html
You can find a code example using the Volatile_Full_Access
aspect in the Ada Drivers Library. For example: stm32_svd-gpio.ads.
I am currently studying the "Ada For The Embedded C Developer Book". I feel like the book misses the information on how to write multiple elements of a single record in single operation while preserving the value of other record elements. It would probably be the best to describe this aspect in the "Interfacing with Devices" section.
The whole book presents how to solve programming problems encountered in the embedded world. However, it misses an example of how to write multiple register fields in a single operation while preserving the value of remaining fields. This is a very common scenario easily solved in C by applying bitwise and, or and shift operations.
The "Register overlays" section provides an example of a power management register. However, this example is too simple, it contains only one valid record element
USBCLK
.Now, imagine the register is a little bit more complex:
How do I write elements
USBCLK0
andUSBCLK2
(in a single opration), while preserving the value ofUSBCLK1
element?