Reserved fields in svd2ada mapping

Perhaps a somewhat philosophical question but I am wondering if mapping reserved fields in svd2ada is meaningful/useful for the clients of these packages.

Taking the RNG_CR register in the random number generator on a stm32f4 board, as a random example (apologies for the terrible pun) the svd2ada mapping is the following (taken directly from ADL):

type CR_Register is record
    --  unspecified
    Reserved_0_1  : HAL.UInt2 := 16#0#;
    --  Random number generator enable
    RNGEN         : Boolean := False;
    --  Interrupt enable
    IE            : Boolean := False;
    --  unspecified
    Reserved_4_31 : HAL.UInt28 := 16#0#;
 end record
   with Volatile_Full_Access, Size => 32,
        Bit_Order => System.Low_Order_First;

 for CR_Register use record
    Reserved_0_1  at 0 range 0 .. 1;
    RNGEN         at 0 range 2 .. 2;
    IE            at 0 range 3 .. 3;
    Reserved_4_31 at 0 range 4 .. 31;
   end record;

However, as stipulated by the RM, these fields should not be meddled with and should be kept at reset value:

On one hand it can be argued that svd2ada simply maps what is parses on the file as this is what its job is and then it’s up to the clients (typically HAL implementers) to enforce any constraints/restrictions and that also these fields act as documentation aid. On the other hand, it could also be argued that these fields should not be modified at all and it would be safer to not expose them at all in the first place? That could also simplify the record interface that clients see (which could make the autocomplete list on the IDE’s a bit more readable) e.g.:

type CR_Register is record      
    --  Random number generator enable
    RNGEN         : Boolean := False;
    --  Interrupt enable
    IE            : Boolean := False;
 end record
   with Volatile_Full_Access, Size => 32,
        Bit_Order => System.Low_Order_First;

 for CR_Register use record
    RNGEN         at 0 range 2 .. 2;
    IE            at 0 range 3 .. 3;
 end record;

And the correct sizes are naturally enforced by the Size aspect.

(I assume svd2ada has somehow the ability to tell which fields are reserved and which not or is that not how it works?)

Any thoughts?

If you’re using SPARK, unchecked conversions require all bits to be assigned to a field. I believe this is why svd2ada generates the reserved fields.

[Sources of unchecked conversion shall not have unused bits. Limits on the Size of scalar types are meant to allow the compiler to zero out extra bits not used in the representation of the scalar value, when writing a value of the type (as GNAT ensures).]

SPARK Reference Manual - 13.9 Unchecked Type Conversions

With Volatile_Full_Access any access to this register will read/write the whole 32-bits, whether these fields are defined or not. On ARM microcontrollers, this is usually a limitation of the APB bus the peripherals are connected to- these buses don’t support unaligned bitwise access.

Personally, I think the CPU should throw a fault interrupt when those instructions are used in a peripheral memory area, but that’s not how ARM decided to do it. There is no way to indicate to GCC that a memory area does not support bitwise access. This could be detected with static analysis after code generation, though I’m not aware of any existing tools that do so.

Newer versions of the SVD standard can specify access constraints at the field level, but there’s no way to communicate those constraints in Ada. I have not seen any vendor SVD files in the wild that actually define these constraints.

Ah, I see about the SPARK requirement..! Ok, so assume shall not have unused bits translates to all bits must be explicitly specified.

Yeah, there would be full 32-bit accesses due to this aspect, was mainly coming from an “information hiding” perspective and whether exposing less is more etc..etc. Totally agree on the throwing a fault exception on byte or halfword accesses on the APB bus. What happens instead is that on these accesses the cpu will silently clone the byte or halfword across the full 32 bits causing some really painful to debug behaviour!

Interesting to know about the newest SVD standard, thanks for sharing.