Dear community,
I am trying to program a nRF58240 board that I have. I saw that there is support for it in Alire and I am using the crate to work with it GitHub - damaki/nrf52-runtimes: Ada/SPARK run-times for nRF52 SoCs (props to @damaki)
TL;DR: I am getting an unexpected warning/exception by the compiler and I do not understand why and I do not know how to debug it.
I want to try out a simple led blinking example for my board. For that I created the following code example:
with Interfaces.NRF52.GPIO;
use Interfaces.NRF52.GPIO;
procedure Test is
LED_Pin : constant := 15;
procedure Set_LED_Output
with Inline
is
begin
-- P0_Periph.PIN_CNF(15) := (DIR => Output, others => <>);
-- P0_Periph.DIR := (As_Array => True,
-- Arr => (LED_Pin => Output, others => <>));
P0_Periph.DIR := (As_Array => True,
Arr => (others => Output));
P1_Periph.DIR := (As_Array => True,
Arr => (others => Output));
end Set_LED_Output;
procedure Wait
with Inline
is
Ticks : constant := 1_000_000;
Counter : Integer := 0;
begin
while Counter /= Ticks loop
Counter := Counter + 1;
end loop;
end Wait;
type Mode is (Off, On);
procedure Set_LED (Dir : Mode)
with Inline
is
begin
-- P0_Periph.OUT_k := (As_Array => True,
-- Arr => (LED_Pin => (if Dir = Off then Low else High), others => <>));
P0_Periph.OUT_k := (As_Array => True,
Arr => (others => (if Dir = Off then Low else High)));
P1_Periph.OUT_k := (As_Array => True,
Arr => (others => (if Dir = Off then Low else High)));
end Set_LED;
Interval : constant Standard.Duration := 0.5;
begin
Set_LED_Output;
loop
Set_LED(Off);
-- delay Interval;
Wait;
Set_LED(On);
-- delay Interval;
Wait;
end loop;
end Test;
I get the following warnings/errors if any of the above code is the following (which is what I want):
P0_Periph.DIR := (As_Array => True,
Arr => (LED_Pin => Output));
Note: Building test=0.1.0-dev/test.gpr...
Compile
[Ada] test.adb
test.adb:14:37: warning: too few elements for type "Interfaces.Nrf52.Gpio.DIR_PIN_Field_Array" [enabled by default]
test.adb:14:37: warning: expected 32 elements; found 1 element [enabled by default]
test.adb:14:37: warning: Constraint_Error will be raised at run time [enabled by default]
test.adb:42:04: warning: constant "Interval" is not referenced [-gnatwu]
Bind
[gprbind] test.bexch
[Ada] test.ali
Link
[link] test.adb
Why do I have to indicate others => <>?? I do not understand. Okay, I mean, the Array is packaged and maybe the compiler cannot modify a single bit? Here is the data structure from the runtime (nrf52-runtimes/nrf52_src/nrf52840/svd/i-nrf52-gpio.ads at aced423df66f7f484deb544e4495cad9e4c13784 · damaki/nrf52-runtimes · GitHub):
-- Pin 0
type DIR_PIN0_Field is
(-- Pin set as input
Input,
-- Pin set as output
Output)
with Size => 1;
for DIR_PIN0_Field use
(Input => 0,
Output => 1);
-- DIR_PIN array
type DIR_PIN_Field_Array is array (0 .. 31) of DIR_PIN0_Field
with Component_Size => 1, Size => 32;
-- Direction of GPIO pins
type DIR_Register
(As_Array : Boolean := False)
is record
case As_Array is
when False =>
-- PIN as a value
Val : Interfaces.NRF52.UInt32;
when True =>
-- PIN as an array
Arr : DIR_PIN_Field_Array;
end case;
end record
with Unchecked_Union, Size => 32, Volatile_Full_Access,
Bit_Order => System.Low_Order_First;
for DIR_Register use record
Val at 0 range 0 .. 31;
Arr at 0 range 0 .. 31;
end record;
Also, what does others => <> do exactly? Because as far as I know, it does the “default constructor/value for the elements”, which is not what I want. I want the rest of the pins to be left untouched.
The alire.toml for the project is the following:
name = "test"
description = "test"
version = "0.1.0-dev"
authors = ["tes"]
maintainers = ["tes <test@test.tes>"]
maintainers-logins = ["tes"]
licenses = "MIT OR Apache-2.0 WITH LLVM-exception"
website = ""
tags = []
executables = ["test"]
[[depends-on]]
# light_tasking_nrf52840 = "*"
embedded_nrf52840 = "*"
[configuration.values]
# light_tasking_nrf52840.LFCLK_Src = "RC"
# light_tasking_nrf52840.Time_Base = "RTC0"
embedded_nrf52840.LFCLK_Src = "RC"
embedded_nrf52840.Time_Base = "RTC0"
[gpr-set-externals]
LIGHT_TASKING_NRF52840_BUILD = "Production"
EMBEDDED_NRF52840_BUILD = "Production"
[build-switches]
"*".style_checks = "No"
"*".runtime_checks = "none"
[[actions]]
type = "post-build"
command = ["arm-eabi-size", "-A", "bin/test"]
[[actions]]
type = "post-build"
command = ["arm-eabi-objcopy", "-O","ihex", "bin/test", "bin/test.hex"]
[[actions]]
type = "post-build"
command = ["uf2conv.py", "bin/test.hex", "-f", "0xADA52840", "-o", "bin/flash.uf2"]
As you can see, I tried to use the light_tasking example (initially in debug mode, then in production). I also initally tried to compile with all assertions enabled (default in Debug), but I switched back to turning the checks off as that seems to be killing my program.
I decompiled (Iaito/Radare2 for the win!) the program and I found out that the _last_chance_handler was being called (marked as likely, even when I get no warning), so there is probably a bug somewhere. I usually fix these things in no time with gdb, however… I do not know how to properly debug the board as I think it has no OpenOCD support and no J-TAG either… Also, the board is loaded with the Adafruit_nRF52_Bootloader bootloader and I think that may be playing a role with the program… Even though I modify all GPIO to be output and to “blink”, some leds that are usually controlled by the bootloader are not responding to blinking…
Any tips here? Any tips on how to work with GDB and ARM boards (I only used OpenOCD and GDB with RISC-V).
Best regards,
Fer