comp.lang.ada
 help / color / mirror / Atom feed
From: daniel.dmk@googlemail.com
Subject: Forcing GNAT to use 32-bit load/store instructions on ARM?
Date: Mon, 30 Jun 2014 15:11:31 -0700 (PDT)
Date: 2014-06-30T15:11:31-07:00	[thread overview]
Message-ID: <0e0b9ac2-e793-4cc5-8d8d-d3441ca28a58@googlegroups.com> (raw)

Hello,

I've started using GNAT GPL for ARM (hosted on Windows) and I'm working on some code in SPARK 2014 to interface to memory-mapped registers to control registers on the STM32 F4 microcontroller, however I'm having trouble where GNAT is using byte loads/stores to the registers, instead of word load/stores (32-bit).

For a lot of registers on the STM32 it is necessary to always access the registers using 32-bit load/store instructions. Using half-word (16-bit) or byte (8-bit) accesses generates a CPU fault with these registers.

I'm representing the 32-bit register as a record as follows:

   type Bits_1 is mod 2**1 with Size => 1;

   type CR_Register is
      record
         RNGEN : Bits_1;
         IE    : Bits_1;
      end record;
   for CR_Register use
      record
         RNGEN at 0 range 2 .. 2; -- bits 0 .. 1 are reserved
         IE    at 0 range 3 .. 3;
         -- bits 4 .. 31 are reserved
      end record;
   for CR_Register'Size use 32;

I then define the register of type CR_Register at the peripheral's base address:

   CR : CR_Register
     with Size => 32,
       Volatile,
       Async_Readers, Async_Writers,
       Address => System'To_Address(Base_Address);

I'm using a record instead of a simple Unsigned_32 type so that:
1) I can hide access to the "reserved" parts of the register,
2) The code to modify the register is straightfoward.

For example, enabling the peripheral is done by setting the RNGEN bit to 1:

   CR.RNGEN := 1;

However, the GNAT compiler uses the ARM instruction ldrb to load the lower 8 bits of the register, modify the byte (or 16#40#), then use strb to write the lower 8-bits back to memory. This causes a fault since the register must be accessed using a 32-bit load/store instructions (the ldr and str instructions).

Does anyone know how I can force GNAT to generate the appropriate instructions?

Things I have tried:
1) Using the Atomic aspect on the record type and CR object had no effect on the code generated.
2) Using Pack.
3) Declaring the bits inside the register as: Bits_32 range 0 .. 1;

So far, I am able to get GNAT to use 32-bit load/stores only when I read the entire record into a temporary variable, as follows:

   declare
      Temp : CR_Register;
   begin
      Temp := CR;
      Temp.RNGEN := 1;
      CR := Temp;
   end;

However, this makes it more "clunky" to use in my opinion. I would prefer to be able to modify the bits directly, and have the compiler always use 32-bit load/store instructions.

Does anyone else have any ideas that I could try?

Thanks,
Dan


             reply	other threads:[~2014-06-30 22:11 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-06-30 22:11 daniel.dmk [this message]
2014-06-30 23:41 ` Forcing GNAT to use 32-bit load/store instructions on ARM? Jeffrey Carter
2014-07-01 12:06   ` Simon Clubley
2014-07-01 15:44     ` Niklas Holsti
2014-07-01 17:26       ` Simon Clubley
2014-07-01 17:18     ` Simon Wright
2014-07-01 19:43       ` Simon Wright
2014-07-01 17:28     ` Jeffrey Carter
2014-07-01  0:55 ` anon
2014-07-01  4:30 ` Niklas Holsti
2014-07-01  8:11 ` Dmitry A. Kazakov
2014-07-01 12:09   ` Simon Clubley
2014-07-01 12:20     ` Dmitry A. Kazakov
2014-07-01 17:00       ` Simon Clubley
2014-07-01 19:36         ` Dmitry A. Kazakov
2014-07-01 20:08           ` Simon Clubley
2014-07-02 22:24             ` Randy Brukardt
2014-07-06 20:40               ` MatthiasR
2014-07-07  0:25                 ` Simon Clubley
2014-07-07 22:38                 ` Randy Brukardt
2014-07-08  6:51                   ` Simon Wright
2014-07-10 11:47                     ` Simon Wright
2014-07-10 13:06                       ` Simon Clubley
2014-07-11 18:05                         ` Simon Wright
2014-07-11 20:22                           ` Simon Clubley
2014-07-08  8:50                   ` Brian Drummond
2014-07-08 12:12                   ` Simon Clubley
2014-07-08 13:26                     ` G.B.
2014-07-08 17:13                       ` Simon Clubley
2014-07-08 15:36                     ` Adam Beneschan
2014-07-08 15:40                       ` Adam Beneschan
2014-07-08 20:34                     ` Randy Brukardt
2014-07-09  7:31                       ` Dmitry A. Kazakov
2014-07-10  0:11                         ` Simon Clubley
2014-07-20 11:35                   ` MatthiasR
2014-07-20 15:49                     ` Simon Clubley
2014-07-26 11:05                       ` MatthiasR
2014-08-10 11:20                         ` MatthiasR
2014-07-01 12:03 ` Simon Clubley
2014-07-01 19:52   ` daniel.dmk
2014-07-01 20:40     ` Simon Clubley
2014-07-01 20:55       ` Simon Clubley
2014-07-01 21:01       ` Niklas Holsti
2014-07-01 21:20         ` Simon Clubley
2014-07-01 22:38           ` Niklas Holsti
2014-07-02 16:49             ` Simon Clubley
2014-07-01 21:55         ` daniel.dmk
2014-07-02  7:30     ` Simon Wright
2014-07-02 18:52       ` daniel.dmk
2014-07-04 23:51       ` Niklas Holsti
2014-07-05  0:18         ` Niklas Holsti
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox