Compilation fails for trivial C program with Adafruit Metro M0

Hi all

For my Adafruit Metro M0 board, I want to build a trivial program in C with PlatformIO:

➜ cat src/main.c
int main(void) {
  return 0;
}

I generated the project like this:

➜ pio --version
PlatformIO Core, version 5.1.1
➜ pio project init --board adafruit_metro_m0
...
Project has been successfully updated!

My platformio.ini looks good (I guess):

[env:adafruit_metro_m0]
platform = atmelsam
board = adafruit_metro_m0
framework = arduino

But when I try and build this, the compiler says:

error: 'Port' was not declared in this scope

Here is the relevant part from the output:

➜ pio run -v
Processing adafruit_metro_m0 (platform: atmelsam; board: adafruit_metro_m0; framework: arduino)
---------------------------------------------------------------------------------------------------------------------------------------------
CONFIGURATION: https://docs.platformio.org/page/boards/atmelsam/adafruit_metro_m0.html
PLATFORM: Atmel SAM (6.3.1) > Adafruit Metro M0 Expresss
HARDWARE: SAMD21G18A 48MHz, 32KB RAM, 256KB Flash
DEBUG: Current (atmel-ice) External (atmel-ice, blackmagic, jlink)
PACKAGES: 
- framework-arduino-samd-adafruit 1.7.2 
- framework-cmsis 2.50400.181126 (5.4.0) 
- framework-cmsis-atmel 1.2.2 
- toolchain-gccarmnoneeabi 1.90301.200702 (9.3.1)
...
arm-none-eabi-g++ -o .pio/build/adafruit_metro_m0/FrameworkArduino/Uart.cpp.o -c -fno-rtti -fno-exceptions -std=gnu++11 -fno-threadsafe-statics -Os -ffunction-sections -fdata-sections -Wall -mcpu=cortex-m0plus -mthumb -nostdlib --param max-inline-insns-single=500 -Wno-expansion-to-defined -DPLATFORMIO=50101 -DARDUINO_SAMD_ZERO -DADAFRUIT_METRO_M0_EXPRESS -DARM_MATH_CM0PLUS -D__SAMD21G18A__ -DARDUINO=10805 -DF_CPU=48000000L -DUSBCON -DUSB_VID=0x239A -DUSB_PID=0x8013 "-DUSB_PRODUCT=\"Metro M0 Expres\"" -DUSB_MANUFACTURER=\"Adafruit\" -DARDUINO_ARCH_SAMD -DUSB_CONFIG_POWER=100 -I/Users/me/.platformio/packages/framework-cmsis/CMSIS/Core/Include -I/Users/me/.platformio/packages/framework-cmsis-atmel/CMSIS/Device/ATMEL -I/Users/me/.platformio/packages/framework-arduino-samd-adafruit/cores/arduino -I/Users/me/.platformio/packages/framework-arduino-samd-adafruit/libraries/Adafruit_TinyUSB_Arduino/src/arduino -I/Users/me/.platformio/packages/framework-cmsis/CMSIS/DSP/Include -I/Users/me/.platformio/packages/framework-arduino-samd-adafruit/variants/metro_m0 /Users/me/.platformio/packages/framework-arduino-samd-adafruit/cores/arduino/Uart.cpp
In file included from /Users/me/.platformio/packages/framework-cmsis-atmel/CMSIS/Device/ATMEL/samd21/include/samd21.h:69,
                from /Users/me/.platformio/packages/framework-cmsis-atmel/CMSIS/Device/ATMEL/samd.h:105,
                from /Users/me/.platformio/packages/framework-cmsis-atmel/CMSIS/Device/ATMEL/sam.h:565,
                from /Users/me/.platformio/packages/framework-arduino-samd-adafruit/cores/arduino/Arduino.h:48,
                from /Users/me/.platformio/packages/framework-arduino-samd-adafruit/cores/arduino/Tone.h:23,
                from /Users/me/.platformio/packages/framework-arduino-samd-adafruit/cores/arduino/Tone.cpp:20:
/Users/me/.platformio/packages/framework-arduino-samd-adafruit/cores/arduino/Tone.cpp: In function 'void tone(uint32_t, uint32_t, uint32_t)':
/Users/me/.platformio/packages/framework-cmsis-atmel/CMSIS/Device/ATMEL/samd21/include/samd21g18a.h:480:29: error: 'Port' was not declared in this scope
  480 | #define PORT              ((Port     *)0x41004400UL) /**< \brief (PORT) APB Base Address */
      |                             ^~~~
...

Compilation for other compile units from framework-arduino-samd-adafruit fail for the same reason. In particular: hooks.c, pulse.c, Uart.cpp and USBCore.cpp

Any ideas how to fix this? Thanks!

So you are working with the Arduino framework.

…but implement main()? The Arduino core already implements that, and calls into the standard user functions setup() and loop() after that. Overriding main like this very likely not going to work at runtime (in a sensible way, since all low-level initializion, including that of the C library, is skipped).

A correct “trivial program” for your platformio.ini is an empty Arduino sketch in a .cpp file (Arduino is a C++ framework, not C.).

#include <Arduino.h>
void setup() {}
void loop() {}

Can’t reproduce that, on the same Atmel-SAM platform 6.3.1 with the same code + platformio.ini, on either Windows or Linux.

$ pio run
Processing adafruit_metro_m0 (platform: atmelsam; board: adafruit_metro_m0; framework: arduino)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/atmelsam/adafruit_metro_m0.html
PLATFORM: Atmel SAM (6.3.1) > Adafruit Metro M0 Expresss
HARDWARE: SAMD21G18A 48MHz, 32KB RAM, 256KB Flash
DEBUG: Current (atmel-ice) External (atmel-ice, blackmagic, jlink)
PACKAGES:
 - framework-arduino-samd-adafruit 1.7.2
 - framework-cmsis 2.50400.181126 (5.4.0)
 - framework-cmsis-atmel 1.2.2
 - toolchain-gccarmnoneeabi 1.90301.200702 (9.3.1)
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 11 compatible libraries
Scanning dependencies...
No dependencies
Building in release mode
Compiling .pio/build/adafruit_metro_m0/src/main.c.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduinoVariant/variant.cpp.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/IPAddress.cpp.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/Print.cpp.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/Reset.cpp.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/SERCOM.cpp.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/Stream.cpp.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/Tone.cpp.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/USB/CDC.cpp.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/USB/PluggableUSB.cpp.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/USB/SAMD21_USBDevice.cpp.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/USB/USBCore.cpp.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/USB/samd21_host.c.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/Uart.cpp.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/WInterrupts.c.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/WMath.cpp.o
Archiving .pio/build/adafruit_metro_m0/libFrameworkArduinoVariant.a
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/WString.cpp.o
Indexing .pio/build/adafruit_metro_m0/libFrameworkArduinoVariant.a
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/abi.cpp.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/avr/dtostrf.c.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/cortex_handlers.c.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/delay.c.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/hooks.c.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/itoa.c.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/main.cpp.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/math_helper.c.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/new.cpp.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/pulse.c.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/pulse_asm.S.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/startup.c.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/wiring.c.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/wiring_analog.c.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/wiring_digital.c.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/wiring_private.c.o
Compiling .pio/build/adafruit_metro_m0/FrameworkArduino/wiring_shift.c.o
Archiving .pio/build/adafruit_metro_m0/libFrameworkArduino.a
Indexing .pio/build/adafruit_metro_m0/libFrameworkArduino.a
Linking .pio/build/adafruit_metro_m0/firmware.elf
Checking size .pio/build/adafruit_metro_m0/firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [          ]   2.6% (used 856 bytes from 32768 bytes)
Flash: [          ]   1.8% (used 4588 bytes from 262144 bytes)
Building .pio/build/adafruit_metro_m0/firmware.bin
=============== [SUCCESS] Took 3.31 seconds ===============

Which means either problem is Mac specific, or you have an unluckily named additional header file in the project that interferes with the SDK, or you have a corrupt SDK download. Try removing /Users/me/.platformio/packages/framework-arduino-samd-adafruit/ and /Users/me/.platformio/packages/framework-cmsis-atmel/ to trigger a redownload of that.

Note that if you don’t want to use Arduino, you can setup an PlatformIO project with only the (Atmel-)CMSIS device headers that you can program against in pure C. There’s a topic and example for that at Bare metal on arduino due / atmelsam. But using the Atmel-CMSIS headers also possible in Arduino, since it includes Atmel-CMSIS, you just have Arduino compiled in as a side-effect.

1 Like

I’ve also modified my referenced example to compile against a Metro M0 that should work with the regular Arduino bootloader: GitHub - maxgerhardt/pio-baremetal-atmel-cmsis at metro_m0

This only uses Atmel-CMSIS and compiles the bare-minimum C code.

I’ve uploaded this to my Adafruit Feather M0 (has the same MCU and the same LED pin) and it works nicely.

Note that you’ll have to double-tap the reset button on the board twice during uploading, once before pressing “Upload”, and once after the “Waiting for the new upload port…” message appears – the baremetal project does not implement any USB serial of course.

1 Like

Thanks for your detailed response! I think you have answered all my questions.

Indeed, I’ve been trying around a lot and apparently I had corrupted my SDK download somehow. Followed your advice and now it works like a charm with your the Arduino sketch you propose!

Yes, Arduino came in only because that’s what pio init had generated… I will look at this next.

Thanks for the link. That looks very helpful!