Programm SAMD21 directly

Hello everyone,

i want to do my first steps using the SAMD21-series. For my upcoming project i want to programm a ATSAMD21E17A directly but i dont understand the platformio/platform-atmelsam library. Somehow you can specify the mcu but you also need a board specification???

Is this supported? Do i have to write my own board.json or just the correct platformio.ini entry?
I want to use the Arduino framework and i also got an Atmel-ICE.

Thanks in advanced and greetings from Germany!

Hm in PlatformIO speak that’s a platform, a collection of possible boards and code needed to use them in a framework (like, Arduino).

PlatformIO does not yet have a board which contains this MCU (per PlatformIO Registry), but a close one would include SAMD21E18A based boards like the Adafruit Trinket M0, which may be used as a base.

PlatformIO always thinks in board (configurations), which contain a certain MCU, have a known clock speed, are mapped to a specific Arduino variant of a certain Arduino core, are compatible with certain upload and debugging protocols, etc. You cannot choose a “raw” MCU, this information has to be connected to it in a board definition.

As said above not directly, but PlatformIO is expandable if you want to go that route.

Yes, basically. As documented in the docs.

Starting from the original definition I’ve created an adapted custom_atsamd21e17a.json with a modified linker script (to accomodate the changed size of the chip, halved from E18A) and some example code. I’d appreciate some feedback on GitHub - maxgerhardt/pio-custom-samd21e17a-board: An example on how to define a custom board for the Atmel SAM platform and the Arduino (Adafruit variant) framework if you can test it.

1 Like

@maxgerhardt first of all thanks for your detailed description and your work! My SAMD devices will be delivered next year and then i will test them. I really apriciate your work!

Grüße aus deiner Nachbarstadt Herne bzw. Nachbar-Uni HS BO :stuck_out_tongue:

1 Like

@maxgerhardt one question about the custom variant. i guess you used the the adafruit trinket m0 as a base right or was it actually the files from the arduino zero? Is the framework with all the variants from platformio on github?


1 Like

Das ist tatsächlich direkt nebenan :smiley:

The variant folder is a copy of ArduinoCore-samd/variants/trinket_m0 at master · adafruit/ArduinoCore-samd · GitHub with modifications to the linker script (half RAM + flash) and openocd scripts (correct chip name).

PS: Adafruit has a really good page on modifying the variant.cpp/.h files regarding the serial communication interfaces ("SERCOM"s in the chip, can be configured for UART or SPI or I2C) and pins and pads and pin mappings. So that page comes in handy when customizing your variant.

The used Adafruit SAMD core (=framework) source page is at GitHub - adafruit/ArduinoCore-samd.

PlatformIO has its own package management system, so it does not directly use this page but makes a copy of it and packages them with version information, stored here, btw. So PIO’s currently used Adafruit core version is 1.6.4 (which is also the latest as of now).

PS: Be aware that for the SAMD chips, multiple different Arduino-core implementations exist. Here I based the work off of the Adafruit version (just because the Trinket M0 was the next-closest match and that was in the Adafruit core), but there’s also GitHub - arduino/ArduinoCore-samd: Arduino Core for SAMD21 CPU from directly Arduino. Similiar, but different still.

Hey max,

first of all thanks for all the support. You gave me a good starting point with your example project.
I already wrote my custom board with custom SERCOMs and pin defenitions. Everything works fine!

But now i want to try out the debugging. Maybe you can help here too.
My Atmel-ICE and OpenOCD works fine. I can upload without a problem. If i try to do PIO Debug i get the following error message:

[Window Title]
Visual Studio Code

Could not find the specified task.

[Configure Task] [Open launch.json] [Cancel]

Do you have any clue? :thinking:

Best Regards,

Full platformio.ini and board JSON file? PIO pulls info from those to create the OpenOCD invocations.

Does going into the “debug” sidebar and pressing the play button there make a difference?


Same behavior when the “PIO Debug (skip pre-debug)” option is selected?

When do upload_protocol = atmel-ice and upload it works fine?

PlatformIO should automatically generate a .vscode/launch.json file, e.g. for an Uno


// PIO Unified Debugger
// Documentation:
// Configuration:

    "version": "0.2.0",
    "configurations": [
            "type": "platformio-debug",
            "request": "launch",
            "name": "PIO Debug",
            "executable": "/home/max/pio_tests/uno/.pio/build/uno/firmware.elf",
            "projectEnvName": "uno",
            "toolchainBinDir": "/home/max/.platformio/packages/toolchain-atmelavr/bin",
            "preLaunchTask": {
                "type": "PlatformIO",
                "task": "Pre-Debug"
            "internalConsoleOptions": "openOnSessionStart"
            "type": "platformio-debug",
            "request": "launch",
            "name": "PIO Debug (skip Pre-Debug)",
            "executable": "/home/max/pio_tests/uno/.pio/build/uno/firmware.elf",
            "projectEnvName": "uno",
            "toolchainBinDir": "/home/max/.platformio/packages/toolchain-atmelavr/bin",
            "internalConsoleOptions": "openOnSessionStart"

if that’s not the case, you may also try to do delete the .vscode folder again and do a project tasks → Miscellaneous → Rebuild IntelliSense for regeneration.

Thanks for your quick answer!

Yeah the launch.json got generated. Skip pre-debug gives me some kind of gdb error.
You can see both tasks running here:

Yeah got the expected results of openocd.

CURRENT: upload_protocol = atmel-ice
Uploading .pio\build\control\firmware.bin
xPack OpenOCD, x86_64 Open On-Chip Debugger 0.10.0+dev-00378-ge5be992df (2020-06-26-09:29)
Licensed under GNU GPL v2
For bug reports, read
debug_level: 1

target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x00005230 msp: 0x20004000
** Programming Started **
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **
shutdown command invoked

My platformio.ini

default_envs = control

monitor_speed = 9600
extra_scripts = pio/
build_flags = -D MON_SPEED=${common.monitor_speed}

platform = atmelsam
board_build.variants_dir = customBoards
board = control_board
framework = arduino
monitor_speed = ${common.monitor_speed}
build_flags = ${common.build_flags}
extra_scripts = ${common.extra_scripts}
src_filter = +<*> -<counter.cpp> -<function_gen.cpp>
upload_protocol = atmel-ice
debug_tool = atmel-ice


    "build": {
      "arduino": {
          "ldscript": "flash_without_bootloader.ld"
      "core": "arduino",
      "cpu": "cortex-m0plus",
      "extra_flags": [
      "f_cpu": "48000000L",
      "hwids": [
      "mcu": "samd21e17a",
      "usb_product": "Custom ATSAMD21E17A Board",
      "variant": "control_board"
    "debug": {
      "jlink_device": "ATSAMD21E17",
      "openocd_chipname": "at91samd21e17",
      "openocd_target": "at91samdXX",
      "svd_path": "ATSAMD21E174.svd"
    "frameworks": [
    "name": "Custom ATSAMD21E17A Board",
    "upload": {
      "disable_flushing": true,
      "maximum_ram_size": 16384,
      "maximum_size": 131072,
      "native_usb": true,
      "offset_address": "0x0000",
      "protocol": "atmel-ice",
      "protocols": [
      "require_upload_port": true,
      "use_1200bps_touch": true,
      "wait_for_upload_port": true
    "url": "",
    "vendor": "mc8051"

I remember EPIPE being a problem in some buggy intermediate PlatformIO version (Cannot debug STM32: "Failed to launch GDB: Error: write EPIPE") that was supposedly fixed however.

Are all your VSCode extension versions up-to-date? Upgrading the latest PIO core and platforms (CLIpio upgrade --devpio platform update → VSCode restart) and makes no difference?

Also a sanity check would be good. Open a CLI as linked above, then cd into C:\Users\<user>\.platformio\tool-openocd. Then execute

bin\openocd -s scripts -f interface/cmsis-dap.cfg -c "set CHIPNAME at91samd21e17" -f target/at91samdXX.cfg

Can OpenOCD connect to the target chip?

If yes, Ctrl+C again to abort. You can try to add

; change build type to debug so that uploaded firmware is directly debug firmware
; remove for release
build_type = debug
debug_tool = custom
debug_server =
debug_port = localhost:3333
debug_init_break = tbreak setup

in the platformio.ini, while removing the old debug_tool declaration. Upload once again. Open a new terminal (Windows+R → cmd.exe), cd into the same directory and start openocd again with the command above. Then try and start the PIO debugger again, with either of the tasks.

Do you then see in the OpenOCD window that a GDB client connects at some point?

1 Like

Once again, thanks for your quick answers!

No difference after update and restart :confused:

you can find the full update log here

gurkengewuerz@DESKTOP-XXXXXXX MINGW64 ./EDC_Firmware (main)
$ pio upgrade --dev
Please wait while upgrading PlatformIO ...
PlatformIO has been successfully upgraded to 5.0.5b4
Release notes:

gurkengewuerz@DESKTOP-XXXXXXXX MINGW64 ./EDC_Firmware (main)
$ pio platform update
Please wait while upgrading PlatformIO...
PlatformIO has been successfully upgraded to 5.0.5b4!

Yeah it can :thinking:

xPack OpenOCD, x86_64 Open On-Chip Debugger 0.10.0+dev-00378-ge5be992df (2020-06-26-09:29)
Licensed under GNU GPL v2
For bug reports, read
Info : auto-selecting first available session transport "swd". To override use 'transport select <transport>'.
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: JTAG Supported
Info : CMSIS-DAP: FW Version = 1.0
Info : CMSIS-DAP: Serial# = J42700010946
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 1 TDO = 1 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : clock speed 400 kHz
Info : SWD DPIDR 0x0bc11477
Info : at91samd21e17.cpu: hardware has 4 breakpoints, 2 watchpoints
Info : starting gdb server for at91samd21e17.cpu on 3333
Info : Listening on port 3333 for gdb connections

Hmm have i done something wrong? It didn’t connected to the localhost ocd server. I still get the same task error like before. PIO Debug => Could not find the specified task; PIO Debug (Skip Pre-Debug) => EPIPE Error.

platform = atmelsam
board_build.variants_dir = customBoards
board = control_board
framework = arduino
monitor_speed = ${common.monitor_speed}
build_flags = ${common.build_flags}
extra_scripts = ${common.extra_scripts}
lib_deps =
src_filter = +<*> -<counter.cpp> -<function_gen.cpp>
upload_protocol = atmel-ice
; change build type to debug so that uploaded firmware is directly debug firmware
; remove for release
build_type = debug
debug_tool = custom
debug_server =
debug_port = localhost:3333
debug_init_break = tbreak setup

Do you still have any clue? :pleading_face:

I can’t reproduce that behavior.

First of all, if just using the builtin debug_tool = atmel-ice, you should be getting some output instead of an error message. Try this: Unplug your Atmel-ICE, then run PIO Debug.

It should compile the project in debug mode, invoke OpenOCD, which should then tell you that no Atmel-ICE is connected. I’ve tested that with your exact JSON file content, too.

Does it give the same output? If not, something is fundamentally wrong already.

Further when using the exact

lines I’ve posted, while having an openOCD gdbserver open, you should get a connection attempt.

Info : starting gdb server for stm32f1x.cpu on 3333
Info : Listening on port 3333 for gdb connections
Info : accepting 'gdb' connection on tcp/3333
Info : device id = 0x20036410
Info : flash size = 128kbytes
Info : dropped 'gdb' connection

(I’m using an STM32 CPU as an example here, output will differ for you).

If that is again not the case something is wrong.

Some generic troubleshooting steps would include:

  • disabling antivirus software (yes, I’ve seen those heavily interfere)
  • removing all but your target project folder from the workspace in VSCode
  • Removing the C:\Users\<user>\.platformio\packages\tool-openocd folder to force a re-download of openocd in case anything is corrupted there
  • Shutting down VSCode, removing the .vscode folder of the project, the re-opening VSCode and Project Task → Miscellaneous → Rebuild IntelliSense for regeneration
  • Making sure the PlatformIO extension is version 2.2.1
  • Disabling all VSCode extensions but PlatformIO and C/C++ by Microsoft, reopening VSCode and retrying.
  • Trying PlatformIO extension version 2.1.0 (VSCode extension sidebar > Cogwheel on PlatformIO → Install Another Version → 2.1.0)
  • Testing if the problem is computer or operating-system specific. E.g., testing on a spare computer, or, using a virtual linux machine with the USB devices forwarded (I always keep a machine with Ubuntu 20.04 installed around for these tests)

If none of these help, bug reports for the VSCode GUI go to Issues · platformio/platformio-vscode-ide · GitHub.

1 Like

Actually, what is that shell here in VSCode? Not the standard Powershell? My shell starts with

PS C:\Users\Max\Documents\PlatformIO\Projects\stm32_flash_alloc_test> pio system info

your shell seems like a Git bash or Cygwin/MSYS2 thing. If that’s set as the default shell in PlatformIO, it might possibly interefer in this special case.

thank you for your effort!
I don’t know what is wrong :confused:

I still got the task not found.

I’m using just the Windows-Defender.

no fix


nothing changed

yep. It works. I downgraded and PIO Debug (skip Pre-Debug) is now working but still PIO Debug gives Could not find the specified task.
Is Issues · platformio/platformio-vscode-ide · GitHub the correct repo to report the issue?

I will test my laptop tomorrow with dual boot for Linux and Windows to evaluate the issue a bit more, but i think it is something with my pc.

once again a big thanks for your effort!

yeah git bash is my default shell in VSCode. I will try the windows shell just to rule it out

HIGHLY interesting. Yes please file a bug there since we downgraded only that component and suddenly debugging works for your custom board definition. Please also state the full platformio.ini there (whether it was just with debug_tool = atmel-ice or the custom definitions). Then @ivankravets can e.g. have a look at it and its reproducability (since it behaves differently on my PC alltogether).

1 Like

Could someone summurize what is goging wrong here?

A custom Atmel SAMD21E17 chip is supposed to be debugged in VSCode. The platformio.ini and board JSON definition are below.

When using the latest core and PIO VSCode extension version, the error “Could not find specified task” appears for the “PIO Debug” target and a GDB “EPIPE” error for “PIO Debug (skip pre-debug)”. See

The behavior on my computer is that OpenOCD is started (but an error is thrown due to me not having an adapter plugged in), without GDB errors or launch errors.

No antivirus is used, but instead of the powershell in VSCode, a custom MinGW shell / bash is used.

The error goes away when downgrading PIO extension to 2.1.0, that’s the interesting part.

changed my shell today to power shell and restarted VSCode but nothing changed there.

@ivankravets i will test my project as i said on my laptop with linux and windows to evaluate the issue a bit more. I will also try all versions until it no longer works. after that i will open an issue on platformio/platformio-vscode-ide with my results and also point to this forum entry.

Alright i opened an issue with more information “Debugger no working since v2.1.1 · Issue #2324 · platformio/platformio-vscode-ide”. Thanks once again Max for your effort! :raised_hands: