From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM autolearn=unavailable autolearn_force=no version=3.4.4 X-Received: by 10.66.102.9 with SMTP id fk9mr21883719pab.2.1404166291297; Mon, 30 Jun 2014 15:11:31 -0700 (PDT) X-Received: by 10.140.80.5 with SMTP id b5mr68079qgd.20.1404166291216; Mon, 30 Jun 2014 15:11:31 -0700 (PDT) Path: backlog3.nntp.dca3.giganews.com!border1.nntp.dca.giganews.com!nntp.giganews.com!goblin1!goblin.stu.neva.ru!hn18no386262igb.0!news-out.google.com!a8ni1qaq.1!nntp.google.com!w8no4292237qac.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail Newsgroups: comp.lang.ada Date: Mon, 30 Jun 2014 15:11:31 -0700 (PDT) Complaints-To: groups-abuse@google.com Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=90.219.105.227; posting-account=qa2LvwoAAADwbTxJVBI5rHWSlh3aClXp NNTP-Posting-Host: 90.219.105.227 User-Agent: G2/1.0 MIME-Version: 1.0 Message-ID: <0e0b9ac2-e793-4cc5-8d8d-d3441ca28a58@googlegroups.com> Subject: Forcing GNAT to use 32-bit load/store instructions on ARM? From: daniel.dmk@googlemail.com Injection-Date: Mon, 30 Jun 2014 22:11:31 +0000 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Xref: number.nntp.dca.giganews.com comp.lang.ada:187295 Date: 2014-06-30T15:11:31-07:00 List-Id: 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/sto= res (32-bit). For a lot of registers on the STM32 it is necessary to always access the re= gisters using 32-bit load/store instructions. Using half-word (16-bit) or b= yte (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 =3D> 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 add= ress: CR : CR_Register with Size =3D> 32, Volatile, Async_Readers, Async_Writers, Address =3D> 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 :=3D 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 mu= st be accessed using a 32-bit load/store instructions (the ldr and str inst= ructions). Does anyone know how I can force GNAT to generate the appropriate instructi= ons? Things I have tried: 1) Using the Atomic aspect on the record type and CR object had no effect o= n 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 th= e entire record into a temporary variable, as follows: declare Temp : CR_Register; begin Temp :=3D CR; Temp.RNGEN :=3D 1; CR :=3D Temp; end; However, this makes it more "clunky" to use in my opinion. I would prefer t= o 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