Arduino Framework library

Hello everybody

I’m working on a project on STM32 in Ada language that calls a C library developped on C/C++ with PlatformIO and Arduino Framework.

It works when I don’t use the functions of Arduino framework : I tested with a simple add() function : build and link were ok with the object code .pio\build\nucleo_f446re\src\export.c.o that contains the function (build and link on GNAT Studio Ada environment and the test was ok on a nucleo F446RE)
But when I use functions of Arduino framework (digitalWrite and delay) I’ve got “undefined reference” linking errors.
I’ve linked with .pio\build\nucleo_f446re\libFrameworkArduino.a
This library is recognized by the linker (error messages references it) but it seems not enough to link

Thanks for your help

The object code and libraries on PIO :

And the linking error messages :

gprbuild --target=arm-eabi -d -PC:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_ada\test_librairie_c_code_ada.gpr -XADL_BUILD_CHECKS=Disabled -XADL_BUILD=Debug -XADAFLAGS= -largs -Wl,-Map=map.txt
Link
   [link]         test_librairie_c_code_ada.adb
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: C:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_c\.pio\build\nucleo_f446re\libFrameworkArduino.a(wiring_digital.c.o): in function `pinMode':
wiring_digital.c:(.text.pinMode+0x36): undefined reference to `pin_in_pinmap'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_digital.c:(.text.pinMode+0x3e): undefined reference to `dac_stop'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_digital.c:(.text.pinMode+0x88): undefined reference to `pin_in_pinmap'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_digital.c:(.text.pinMode+0x92): undefined reference to `pwm_stop'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_digital.c:(.text.pinMode+0xc8): undefined reference to `digitalPin'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_digital.c:(.text.pinMode+0xd0): undefined reference to `PinMap_DAC'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_digital.c:(.text.pinMode+0xd4): undefined reference to `analogInputPin'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_digital.c:(.text.pinMode+0xd8): undefined reference to `PinMap_TIM'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_digital.c:(.text.pinMode+0xa0): undefined reference to `pin_function'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_digital.c:(.text.pinMode+0xc0): undefined reference to `_Error_Handler'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: C:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_c\.pio\build\nucleo_f446re\libFrameworkArduino.a(wiring_digital.c.o): in function `digitalWrite':
wiring_digital.c:(.text.digitalWrite+0x64): undefined reference to `digitalPin'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_digital.c:(.text.digitalWrite+0x68): undefined reference to `GPIOPort'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_digital.c:(.text.digitalWrite+0x6c): undefined reference to `pin_map_ll'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_digital.c:(.text.digitalWrite+0x70): undefined reference to `analogInputPin'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: C:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_c\.pio\build\nucleo_f446re\libFrameworkArduino.a(wiring_digital.c.o): in function `digitalRead':
wiring_digital.c:(.text.digitalRead+0x64): undefined reference to `digitalPin'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_digital.c:(.text.digitalRead+0x68): undefined reference to `GPIOPort'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_digital.c:(.text.digitalRead+0x6c): undefined reference to `pin_map_ll'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_digital.c:(.text.digitalRead+0x70): undefined reference to `analogInputPin'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: C:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_c\.pio\build\nucleo_f446re\libFrameworkArduino.a(wiring_digital.c.o): in function `digitalToggle':
wiring_digital.c:(.text.digitalToggle+0x6c): undefined reference to `digitalPin'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_digital.c:(.text.digitalToggle+0x70): undefined reference to `GPIOPort'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_digital.c:(.text.digitalToggle+0x74): undefined reference to `pin_map_ll'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_digital.c:(.text.digitalToggle+0x78): undefined reference to `analogInputPin'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: C:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_c\.pio\build\nucleo_f446re\libFrameworkArduino.a(wiring_time.c.o): in function `millis':
wiring_time.c:(.text.millis+0x0): undefined reference to `getCurrentMillis'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: C:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_c\.pio\build\nucleo_f446re\libFrameworkArduino.a(wiring_time.c.o): in function `micros':
wiring_time.c:(.text.micros+0x0): undefined reference to `getCurrentMicros'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: C:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_c\.pio\build\nucleo_f446re\libFrameworkArduino.a(wiring_time.c.o): in function `delay':
wiring_time.c:(.text.delay+0x6): undefined reference to `getCurrentMillis'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_time.c:(.text.delay+0x10): undefined reference to `getCurrentMillis'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: C:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_c\.pio\build\nucleo_f446re\libFrameworkArduino.a(wiring_analog.c.o): in function `analogReadResolution':
wiring_analog.c:(.text.analogReadResolution+0x32): undefined reference to `_Error_Handler'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: C:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_c\.pio\build\nucleo_f446re\libFrameworkArduino.a(wiring_analog.c.o): in function `analogWriteResolution':
wiring_analog.c:(.text.analogWriteResolution+0x1c): undefined reference to `_Error_Handler'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: C:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_c\.pio\build\nucleo_f446re\libFrameworkArduino.a(wiring_analog.c.o): in function `analogRead':
wiring_analog.c:(.text.analogRead+0xe): undefined reference to `adc_read_value'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: C:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_c\.pio\build\nucleo_f446re\libFrameworkArduino.a(wiring_analog.c.o): in function `analogWrite':
wiring_analog.c:(.text.analogWrite+0x24): undefined reference to `pin_in_pinmap'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_analog.c:(.text.analogWrite+0x90): undefined reference to `pin_in_pinmap'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_analog.c:(.text.analogWrite+0x104): undefined reference to `digitalPin'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_analog.c:(.text.analogWrite+0x108): undefined reference to `PinMap_DAC'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_analog.c:(.text.analogWrite+0x114): undefined reference to `analogInputPin'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_analog.c:(.text.analogWrite+0x118): undefined reference to `PinMap_TIM'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_analog.c:(.text.analogWrite+0x66): undefined reference to `dac_write_value'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: wiring_analog.c:(.text.analogWrite+0xd4): undefined reference to `pwm_start'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: C:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_c\.pio\build\nucleo_f446re\libFrameworkArduino.a(pins_arduino.c.o): in function `pinNametoDigitalPin':
pins_arduino.c:(.text.pinNametoDigitalPin+0x2c): undefined reference to `digitalPin'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: C:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_c\.pio\build\nucleo_f446re\libFrameworkArduino.a(pins_arduino.c.o): in function `analogInputToPinName':
pins_arduino.c:(.text.analogInputToPinName+0xec): undefined reference to `analogInputPin'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: pins_arduino.c:(.text.analogInputToPinName+0xf0): undefined reference to `digitalPin'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: C:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_c\.pio\build\nucleo_f446re\libFrameworkArduino.a(pins_arduino.c.o): in function `digitalpinIsAnalogInput':
pins_arduino.c:(.text.digitalpinIsAnalogInput+0x24): undefined reference to `analogInputPin'
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/../lib/gcc/arm-eabi/12.2.0/../../../../arm-eabi/bin/ld.exe: C:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_c\.pio\build\nucleo_f446re\libFrameworkArduino.a(pins_arduino.c.o): in function `digitalPinToAnalogInput':
pins_arduino.c:(.text.digitalPinToAnalogInput+0x34): undefined reference to `analogInputPin'
collect2.exe: error: ld returned 1 exit status
gprbuild: link of test_librairie_c_code_ada.adb failed
gprbuild: failed command was: c:\users\mbdj\.config\alire\cache\dependencies\gnat_arm_elf_12.2.1_351564ba\bin\arm-eabi-gcc.exe test_librairie_c_code_ada.o b__test_librairie_c_code_ada.o C:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_ada\obj\development\package_test_librairie_c_code_ada.o C:\Users\mbdj\Dev\AdaLib\Ada_Drivers_Library-master\boards\nucleo_f446re\obj\full_lib_Debug\libada_drivers_library.a C:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_c\.pio\b
uild\nucleo_f446re\src\export.c.o C:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_c\.pio\build\nucleo_f446re\libFrameworkArduino.a -Wl,-Map=map.txt -LC:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_ada\obj\development\ -LC:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_ada\obj\development\ -LC:\Users\mbdj\Dev\AdaLib\Ada_Drivers_Library-master\boards\nucleo_f446re\obj\full_lib_Debug\ -LC:\users\mbdj\.config\alire\cache\dependencies\gnat_arm_e
lf_12.2.1_351564ba\arm-eabi\lib\gnat\embedded-stm32f4\adalib\ -static-libgcc C:\users\mbdj\.config\alire\cache\dependencies\gnat_arm_elf_12.2.1_351564ba\arm-eabi\lib\gnat\embedded-stm32f4\adalib\libgnarl.a C:\users\mbdj\.config\alire\cache\dependencies\gnat_arm_elf_12.2.1_351564ba\arm-eabi\lib\gnat\embedded-stm32f4\adalib\libgnat.a -Wl,-LC:\users\mbdj\.config\alire\cache\dependencies\gnat_arm_elf_12.2.1_351564ba\arm-eabi\lib\gnat\embedded-stm32f4\/adalib -nostartfiles -nolibc -Wl,--start-group,-l
gnarl,-lgnat,-lc,-lgcc,--end-group -LC:\users\mbdj\.config\alire\cache\dependencies\gnat_arm_elf_12.2.1_351564ba\arm-eabi\lib\gnat\embedded-stm32f4\/ld_user -LC:\users\mbdj\.config\alire\cache\dependencies\gnat_arm_elf_12.2.1_351564ba\arm-eabi\lib\gnat\embedded-stm32f4\/ld -mlittle-endian -mfloat-abi=hard -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mthumb -T common-ROM.ld -o C:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_ada\bin\\test_librairie_c_code_ada
[2023-08-12 11:42:47] process exited with status 4, 100% (183/183), elapsed time: 01.13s

I’m pretty sure that you need to declare the Arduino functions as the Ada equivalent to C++'s extern "C" ... because they come from a file named wiring_digital.c and will be using the C calling convention and registers etc.

I’ve never coded in Ada, so I might be talking nonsense, but I assume it does have the ability to call C modules and libraries?

Cheers,
Norm.

Thanks @normandunbar

But I’ve yet declared the functions that I use (equivalent to extern “C”).
In Ada it looks like :

 procedure Blink (N : Interfaces.Unsigned_32);
   pragma Import (C, Blink, "blink");

   procedure Delai (Ms : Interfaces.Unsigned_32);
   pragma Import (C, Delai, "delai");

   function Add (A : Interfaces.Unsigned_32 ;
                 B : Interfaces.Unsigned_32) return Interfaces.Unsigned_32;
   pragma Import (C, Add, "add");

The code with the use of Add() alone is linking without error and runs correctly but if I use in addition the functions Delai and Blink then the linking fails with the previous errors.

These functions call Arduino framework functions digitalWrite and delay :

#include <Arduino.h>

void blink(uint32_t n)
{
    for (int i = 0; i < n; i++)
    {
        digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
        delay(100);                      // wait for a second
        digitalWrite(LED_BUILTIN, LOW);  // turn the LED off by making the voltage LOW
        delay(100);
    }
}

void delai(uint32_t ms)
{
    delay(ms);
}

uint32_t add(uint32_t a, uint32_t b)
{
    return a + b;
}

digitalWrite and delay are part of Arduino framework.

@maxgerhardt has made a good tutorial on use of Arduino libraries here : How to generate and use pre-compiled objects
And I understood that I have to link with libFrameworkArduino.a library (in addition of export.c.o that contains my functions add, blink and delay) that is the run time Arduino

This library is well identified by the linker because one see that the linker references it in the error messages :

[link] test_librairie_c_code_ada.adb
c:/users/mbdj/.config/alire/cache/dependencies/gnat_arm_elf_12.2.1_351564ba/bin/…/lib/gcc/arm-eabi/12.2.0/…/…/…/…/arm-eabi/bin/ld.exe: C:\Users\mbdj\Dev\Ada\STM32\test_librairie_c\test_librairie_c_code_c.pio\build\nucleo_f446re\libFrameworkArduino.a(wiring_digital.c.o): in function `pinMode': wiring_digital.c:(.text.pinMode+0x36): undefined reference to `pin_in_pinmap’

And the error concerns functions that I don’t use directly (eg pinMode and pin_in_pinmap) but that the library libFrameworkArduino.a seems to use and that seems to be missing for the linker …

So I guess another Arduino libraries are missing for linking. But I don’t know which ones they are.

I wonder! Sometimes when linking it is necessary to add a library more than once to the command line. This is, apparently, because the linker won’t find a function in the library if it has already read past it while scanning the library. I also wonder if this has been long time fixed as I haven’t had a problem myself in years!

The solution used to be to add the affected library again, something like:

gcc ... -l FrameworkArduino -l other -l morestuff -l FrameworkArduino
        ^^^^^^^^^^^^^^^^^^^                       ^^^^^^^^^^^^^^^^^^^  

Just a thought.

Cheers,
Norm.

Norman
I’ve tried that but it seems not working

Thanks for your help

I’m afraid that you have exhausted my ideas of how to help. Sorry. :cry:

Cheers,
Norm.