4

Trying to roll my own code for STM32F4 UART. A peculiarity of this chip is that if you use byte addressing as the GNAT compiler does when setting a single bit, the corresponding bit in the other byte of the half word is set. The data sheet says use half word addressing. Is there a way to tell the compiler to do this? I tried for CR1_register'Size use 16;

but this had no effect. Writing the whole 16 bit word works, but you lose the ability to set named bits.

2 Answers2

5

The GNAT way to do this, as used in the AdaCore Ada Drivers Library, is to use the GNAT-only aspect Volatile_Full_Access, about which the GNAT Reference Manual says

This is similar in effect to pragma Volatile, except that 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.

The intention is that this be suitable for use with memory-mapped I/O devices on some machines. Note that there are two important respects in which this is different from pragma Atomic. First a reference to a Volatile_Full_Access object is not a sequential action in the RM 9.10 sense and, therefore, does not create a synchronization point. Second, in the case of pragma Atomic, there is no guarantee that all the bits will be accessed if the reference is not to the whole object; the compiler is allowed (and generally will) access only part of the object in this case.

Their code is

   --  Control register 1
   type CR1_Register is record
      --  Send break
      SBK            : Boolean := False;
      ...
   end record
     with Volatile_Full_Access, Size => 32,
          Bit_Order => System.Low_Order_First;

   for CR1_Register use record
      SBK            at 0 range 0 .. 0;
      ...
   end record;
Simon Wright
  • 25,108
  • 2
  • 35
  • 62
1

Portable way is to do this explicitly: read whole record, modify, then write it back. As long as it is declared Volatile a compiler will not optimize reads and writes out.

    -- excerpt from my working code --
    declare
        R : Control_Register_1 := Module.CR1;
    begin
        R.UE := True;
        Module.CR1 := R;
    end;

This is very verbose, but it does its work.

Vovanium
  • 3,798
  • 17
  • 23