Help adding Seeeduino XIAO (SAMD21) to XOD supported devices (Updated, looking for @dev help)

Hi all,

In an effort to reduce my project size and get more program storage, I’ve decided to try running my code on Seeeduino XIAO which is supposed to be based on the Amtel SAMD21. I see that XOD supports SAMD21, as I tried to install the drivers by pushing an upload to “Arduino Zero ( tried both native usb port and programming port)” and the com port the device is registered on. The compiler runs fine and compiles test code that normally runs on my Arduino Nanos (Amtel 328).

I can’t seem to find a way to upload this code to this board. XOD sees it, but I can’t find a “board model” in the drop down to choose that works.

Is this board compatible? The error I get:

Uploading compiled code to the board…
Error: open port: Serial port busy
Can’t perform reset via 1200bps-touch on serial port
Upload failed
Command Process exited with code 1
Make sure the board is connected, the cable is working, the board model set correctly, the upload port belongs to the board, the board drivers are installed, the upload options (if any) match your board specs.

I’ve tried uploading to the board without it attached to anything just to be sure it wasn’t my wiring. No good.

Anyone have any recommendations on pushing code to this board? I’d really love to use this one, it’s perfect for my needs. I’d be happy to provide log data, or whatever is needed to diagnose. I’ve tried installing the drivers from Arduino’s sketch manager, too. No dice.

Any help getting this board working would be highly appreciated, since it’s a powerhouse and tiny. Please and thanks!

Edit: More info

If I double-click-bridge the “reset” pins on the board with a looped dupont cable, it does switch over to USB mode, and I can see drive contents on the board - so I’m pretty sure USB connectivity is good and windows drivers are good. I think XOD IDE just needs to be set up to choose the right board and upload settings. Also worth noting that I get a similar error in Arduino Sketchbook when trying to upload, after adding Seeeduino XIAO M0 from the boards manager and official seeduino repo.

Sketch uses 59956 bytes (22%) of program storage space. Maximum is 262144 bytes.
at cc.arduino.packages.uploaders.SerialUploader.uploadUsingPreferences(
at cc.arduino.UploaderUtils.upload(
Caused by: Error touching serial port ‘COM3’.
at cc.arduino.packages.uploaders.SerialUploader.uploadUsingPreferences(
… 5 more
Caused by: jssc.SerialPortException: Port name - COM3; Method name - openPort(); Exception type - Port busy.
at jssc.SerialPort.openPort(
… 6 more

Update -

This board seems to switch modes when being programmed and I can’t tell if it’s being programmed correctly. XOD now sees (both) USB modes in the menu but will only program when in one of two modes (ok, solved that one, it appears I can now upload code to the board).

I believe disabling windows driver signing by GPedit solved the connection issue but can’t confirm, as I still see the error when the board is in its alternate mode.

Of note, debug “seems” to connect but no watches or updates seem to work. I suspect this is because the USB mode changes once the chip is programmed, as once programming finishes, it seems to load the file explorer for the usb storage on the board (shows as a windows drive). I have to close the debug tab as the STOP button does not work.

Lastly can’t tell whether or not it’s the fault of the debug mapping, or the internal pin to IO mapping that may be missing for this particular board. Does anyone know how to set a board up and/or create a pin map for this board? I doubt it exists yet for XOD but I’d like to help get it added.

Hi, sometimes after loading, it is necessary to do a manual reset so that the similarity starts in the watches, I think that on the back it has a reset test point.

Just for the sake of conversation, I pulled the bootloader code from xod<proj>_packages_\arduino\hardware\samd\1.8.6\bootloaders\zero\board_definitions_zero.h to see what the pinmapping on another Cortex M0 controller looked like - here’s the dump. I’m pretty sure I would need to generate a new one of these, and add it along with the other menu items in these folders to get it added to XOD.

Anyone know of a way to find the virtual IO pin to hardware pin map for this board? At the very least I can stuff the settings into another board item I’m never going to use, to see if it works.

Copyright © 2015 Arduino LLC. All right reserved.
Copyright © 2015 Atmel Corporation/Thibaut VIARD. All right reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA



  • USB device definitions
    #define STRING_PRODUCT “Arduino Zero”
    #define USB_VID_HIGH 0x23
    #define USB_VID_LOW 0x41
    #define USB_PID_HIGH 0x00
    #define USB_PID_LOW 0x4D


  • If BOOT_DOUBLE_TAP_ADDRESS is defined the bootloader is started by
  • quickly tapping two times on the reset button.
  • BOOT_DOUBLE_TAP_ADDRESS must point to a free SRAM cell that must not
  • be touched from the loaded application.
    #define BOOT_DOUBLE_TAP_ADDRESS (0x20007FFCul)
    #define BOOT_DOUBLE_TAP_DATA (
    ((volatile uint32_t *) BOOT_DOUBLE_TAP_ADDRESS))


  • If BOOT_LOAD_PIN is defined the bootloader is started if the selected
  • pin is tied LOW.
    //#define BOOT_LOAD_PIN PIN_PA21 // Pin 7
    //#define BOOT_LOAD_PIN PIN_PA15 // Pin 5


/* Master clock frequency */
#define CPU_FREQUENCY (48000000ul)

/* Frequency of the board main oscillator */
#define VARIANT_MAINOSC (32768ul)

/* Calibration values for DFLL48 pll */


  • LEDs definitions
    #define BOARD_LED_PORT (0)
    #define BOARD_LED_PIN (17)

#define BOARD_LEDRX_PORT (1)
#define BOARD_LEDRX_PIN (3)

#define BOARD_LEDTX_PORT (0)
#define BOARD_LEDTX_PIN (27)


Thanks for the reply, @cesars, but I power cycling the board doesn’t seem to do anything with a known working patch on my 328, so I suspect it’s a pin config somewhere. I can’t get the I2C OLED to connect on SDA/SCL either, which was working on the 328 as well. It does get warm, but that’s it. I have that disconnected for now.

I believe I’ve found the pin definition file location I’d need to add an entry to -

_packages_\packages\arduino\hardware\samd\1.8.6\variants<board> where in this case board is <arduino_zero> . This is the contents of the variant.h file which looks to be the full hardware pinmap for the Arduino Zero implementation of the Cortex SAMD21.

So - one step closer, I think. Hoping someone knows more about this than I do :slight_smile:

Copyright © 2014-2015 Arduino LLC. All right reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA


// The definitions here needs a SAMD core >=1.6.10


  •    Definitions


/** Frequency of the board main oscillator */
#define VARIANT_MAINOSC (32768ul)

/** Master clock frequency */
#define VARIANT_MCK (48000000ul)


  •    Headers


#include “WVariant.h”

#ifdef __cplusplus
#include “SERCOM.h”
#include “Uart.h”
#endif // __cplusplus

#ifdef __cplusplus
extern “C”
#endif // __cplusplus


  •    Pins


// Number of pins defined in PinDescription array
#ifdef __cplusplus
extern “C” unsigned int PINCOUNT_fn();
#define PINS_COUNT (PINCOUNT_fn())
#define NUM_DIGITAL_PINS (20u)
#define NUM_ANALOG_INPUTS (6u)
#define analogInputToDigitalPin§ ((p < 6u) ? § + 14u : -1)

#define digitalPinToPort§ ( &(PORT->Group[g_APinDescription[P].ulPort]) )
#define digitalPinToBitMask§ ( 1 << g_APinDescription[P].ulPin )
//#define analogInPinToBit§ ( )
#define portOutputRegister(port) ( &(port->OUT.reg) )
#define portInputRegister(port) ( &(port->IN.reg) )
#define portModeRegister(port) ( &(port->DIR.reg) )
#define digitalPinHasPWM§ ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )


  • digitalPinToTimer(…) is AVR-specific and is not defined for SAMD
  • architecture. If you need to check if a pin supports PWM you must
  • use digitalPinHasPWM(…).
    // #define digitalPinToTimer§

// LEDs
#define PIN_LED_13 (13u)
#define PIN_LED_RXL (25u)
#define PIN_LED_TXL (26u)
#define PIN_LED PIN_LED_13


  • Analog pins
    #define PIN_A0 (14ul)
    #define PIN_A1 (15ul)
    #define PIN_A2 (16ul)
    #define PIN_A3 (17ul)
    #define PIN_A4 (18ul)
    #define PIN_A5 (19ul)
    #define PIN_DAC0 (14ul)

static const uint8_t A0 = PIN_A0;
static const uint8_t A1 = PIN_A1;
static const uint8_t A2 = PIN_A2;
static const uint8_t A3 = PIN_A3;
static const uint8_t A4 = PIN_A4;
static const uint8_t A5 = PIN_A5;
static const uint8_t DAC0 = PIN_DAC0;

// Other pins
#define PIN_ATN (38ul)
static const uint8_t ATN = PIN_ATN;


  • Serial interfaces
    // Serial (EDBG)
    #define PIN_SERIAL_RX (31ul)
    #define PIN_SERIAL_TX (30ul)
    #define PAD_SERIAL_TX (UART_TX_PAD_2)

// Serial1
#define PIN_SERIAL1_RX (0ul)
#define PIN_SERIAL1_TX (1ul)


  • SPI Interfaces

#define PIN_SPI_MISO (22u)
#define PIN_SPI_MOSI (23u)
#define PIN_SPI_SCK (24u)
#define PERIPH_SPI sercom4
#define PAD_SPI_TX SPI_PAD_2_SCK_3

static const uint8_t SS = PIN_A2 ; // SERCOM4 last PAD is present on A2 but HW SS isn’t used. Set here only for reference.
static const uint8_t MOSI = PIN_SPI_MOSI ;
static const uint8_t MISO = PIN_SPI_MISO ;
static const uint8_t SCK = PIN_SPI_SCK ;


  • Wire Interfaces

#define PIN_WIRE_SDA (20u)
#define PIN_WIRE_SCL (21u)
#define PERIPH_WIRE sercom3

static const uint8_t SDA = PIN_WIRE_SDA;
static const uint8_t SCL = PIN_WIRE_SCL;


  • USB
    #define PIN_USB_HOST_ENABLE (27ul)
    #define PIN_USB_DM (28ul)
    #define PIN_USB_DP (29ul)


  • I2S Interfaces
    #define I2S_INTERFACES_COUNT 1

#define I2S_DEVICE 0
#define PIN_I2S_SD (9u)
#define PIN_I2S_SCK (1u)
#define PIN_I2S_FS (0u)

#ifdef __cplusplus


  •    Arduino objects - C++ only


#ifdef __cplusplus

/* =========================

  • =========================
    extern SERCOM sercom0;
    extern SERCOM sercom1;
    extern SERCOM sercom2;
    extern SERCOM sercom3;
    extern SERCOM sercom4;
    extern SERCOM sercom5;

extern Uart Serial;
extern Uart Serial1;


#ifdef __cplusplus
extern “C” {
unsigned int PINCOUNT_fn();
#ifdef __cplusplus

// These serial port names are intended to allow libraries and architecture-neutral
// sketches to automatically default to the correct port name for a particular type
// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
// the first hardware serial port whose RX/TX pins are not dedicated to another use.
// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor
// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial
// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library
// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins.
// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX
// pins are NOT connected to anything by default.
// Serial has no physical pins broken out, so it’s not listed as HARDWARE port


Alright, I found the exact variants folder I need in my Arduino install that includes the official Seeeduino XIAO M0 variant package.


Anyone know how to add this whole thing to XOD? It looks like all of the dirty work is done, and I should be able to copy/paste these assets into the XOD folder structure to add and use them appropriately. Anyone done this before? I’m still winging it.

well I think I understand what it refers to, I made a node for ESP8266, which addresses the port.
It would have to see if I can make one for SAMD21.

The node is in library cesars/utils

This isn’t an add-on module for an arduino board, it’s a full dev board like a lilypad or nano or any one of the other micro dev boards. It’s got similar stats to the Amtel Mega2650 but it’s got a lot more horsepower. This XIAO board is a super-tiny dev board for wearables and other high-performance projects. I don’t think it needs a node implementation like the ESP boards do, as it’s not an add-on.

It’s like a beefed up 2650 with just a few pins and a super compact package.

The way XOD appears to define each board ‘variant’, I’d need to add the variant data to XOD’s hardware definitions to get this board working properly.

In comparing the 2 variant.h files, there are definitely big differences in the pin mapping. I’ll probably need to spend some serious time evaluating the variant definitions to try and get this board working. I’ll keep picking away at it…

It occurs to me that you could do a mapping manually, for example connect a led to a pin and send a pulse as you raise the port value, list up to 17 or more, if you create a table I can help you

As you say it is very different, and I don’t have the hardware to try something

The mapping is already done in the variants.h file for the Seeeduinio XIAO M0 official Arduino install. It’s a matter of translating the variant.h files and configs from the Arduino official hardware definitions over to a set that XOD can ingest, then dumping them into the right locations in the XOD app directories to populate them into the “upload” menu.

you have not understood me, if it is in variant.h but I xod does not take those values. The same was true with ESP taking D5 when actually assigning D1.

So I tell him that he has to send a high pin-by-pin and see which one he assigns and which sends a signal.

There is no variant.h for a XOD implemenation of this XIAO board yet, and I think that’s why we’re mis-communicating. The Variant.h for XIAO belongs to the Arduino implementation and is supplied by the vendor. I have not tried the values in the XIAO Arduino implementation in XOD yet so the XIAO pin values are untested in XOD.

edit to further clarify: I was able to upload code to the board using the Arduino Zero profile in XOD, and the upload seemed to take, so I know XOD can talk to the XIAO now - just a matter of mapping the device and generating the proper XOD variant files for it :slight_smile:

I understand what you mean by doing the pin testing, but wouldn’t this already be done? Considering there is a working variants.h file for Arduino we can then use the vendor provided mapped values from in XOD, or does XOD use different internal pin values and names? If XOD maps the pins differently than Arduino all I’d need is that map.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.