comp.lang.ada
 help / color / mirror / Atom feed
From: Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP>
Subject: Re: Forcing GNAT to use 32-bit load/store instructions on ARM?
Date: Tue, 1 Jul 2014 12:03:30 +0000 (UTC)
Date: 2014-07-01T12:03:30+00:00	[thread overview]
Message-ID: <lou82i$7u2$1@dont-email.me> (raw)
In-Reply-To: 0e0b9ac2-e793-4cc5-8d8d-d3441ca28a58@googlegroups.com

On 2014-06-30, daniel.dmk@googlemail.com <daniel.dmk@googlemail.com> wrote:
> 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).
>

This is both a GNAT front end problem and a GCC ARM code generator problem.

A couple of years ago, I tried to use bitfields in C code instead of
bitmasks (which I don't like) in the same way you are using them here
in Ada and I ran into the same ldrb/strb problem.

At the time I could not find a reliable solution to this and I went back
to using bitmasks in my C code.

However, we had a discussion in a related area on comp.lang.ada recently
and, in Ada, the conclusion was that the Atomic pragma should indeed
either give you the guarantee you seek or GNAT should reject the code
during compilation.

If this isn't happening then I regard that as a major GNAT bug if Pragma
Atomic is indeed being ignored.

> 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;
>

In the general case, you need to initialise those reserved bits to known
values; to not do this is too dangerous. I always do this in C and if I
was doing embedded code in Ada I would do the same thing in Ada as well.

> 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.

That absolutely should have worked or GNAT should have raised a error
during compilation.

> 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;
>

FYI, if you need to set more than one bitfield at the same time (as part
of an atomic register update) this is the only way you can do this in Ada
unless you resort to using C style bitmasks.

> 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?
>

Pragma Atomic _should_ have given you the guarantee you needed.
Are you double checked how it's being used in the code ?

Simon.

-- 
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980s technology to a 21st century world

  parent reply	other threads:[~2014-07-01 12:03 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-06-30 22:11 Forcing GNAT to use 32-bit load/store instructions on ARM? daniel.dmk
2014-06-30 23:41 ` 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 [this message]
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