Linking or aliasing SerialUSB -> Serial on SAMD21G ?

Hello, Ï have build custom board based on SAMD21G18A MCU (Arduino Zero/M0). MCU part is mostly optimized design of Sparkfun SAMD21G Pro board. I loaded standart bootloader for this board and everything works very good.

But I noticed one detail. Anything like:

Serial.println("Hello")

Will not show up in terminal window, but:

SerialUSB.println("Hello")

Works flawlessly. This is fine in most cases, but many 3rd libraries have hard coded debug messages and other stuff to Serial and only option is to rewrite it everywhere in the code. I still use ATMEGA328P in many applications, so it would break compatibility there. Also I plan to use other serial ports for multiple devices.

I tested loading code as Arduino MKRZERO with its coresponding bootloader and it works with Serial out of the box.

Is there any way to tell IDE that Serial = SerialUSB ? Or in code itself like:

#ifdef __ARM__
GLOBAL_SERIAL=SerialUSB
GLOBAL_SERIAL1=Serial
GLOBAL_SERIAL2=Serial1
...
#endif

I checked the variant.cpp , but it seems to be defined somewhere else...

The instantiation of the SerialUSB object is here: https://github.com/arduino/ArduinoCore-samd/blob/1.8.4/cores/arduino/USB/CDC.cpp#L348

Several of the variants do this in variant.h: https://github.com/arduino/ArduinoCore-samd/blob/1.8.4/variants/mkrzero/variant.h#L207

#define Serial                      SerialUSB

why do you select M0?

pert: The instantiation of the SerialUSB object is here: https://github.com/arduino/ArduinoCore-samd/blob/1.8.4/cores/arduino/USB/CDC.cpp#L348

Several of the variants do this in variant.h: https://github.com/arduino/ArduinoCore-samd/blob/1.8.4/variants/mkrzero/variant.h#L207

#define Serial                      SerialUSB

Ahh, variant.h Completely missed this. I will try to modify this tomorow when I have access to board. Is there any chance to set that temporary in sketch? I think probably not, I guess ?

Juraj: why do you select M0?

Well I actually chose SAMD21 Dev Breakout from Sparkfun as design reference:

https://github.com/sparkfun/SAMD21_Dev_Breakout

Basic reason was that SAMD21G is possible to solder by hot air with bare hands. Actually boards are made and assembled in Europe by special company.

My changes include: - faster Li-Ion charger (500mA) - full SD card slot (high quality push-push type) - precision RTC - DS3231 with big coin battery backup - precision GPS/Glonass/Beidou receiver - Ublox M8N

Good news is that community will have access to design when finished. It will be released as Open Hardware.

I meant why do you select the Arduino M0 in the Tools menu? As far I know it is the only one in the Arduino SAMD boards package with Serial not mapped to native USB

Juraj: I meant why do you select the Arduino M0 in the Tools menu? As far I know it is the only one in the Arduino SAMD boards package with Serial not mapped to native USB

Well I tried all boards with same CPU because initially I had trouble with differently mapped pins. This is my first ARM custom made board. I used to make a lot of ATMEGA328P boards where everything was much easier. Here I was initially confused that every SAMD21G board has almost completely different pin mappings. I would like to make complete new menu entry for my board, still looking for some "template" how to do that. Arduino M0 has least pin mapping differences with my custom buard than e.g. MKRZERO that is completely different and has much less GPIOs connected.

Helium328PU: still looking for some "template" how to do that

The template is the existing board definitions in Arduino SAMD Boards. There is also general documentation here: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification

If you get stuck on anything specific while making the new entry, let us know and we'll help you out.

the

Helium328PU: Well I tried all boards with same CPU because initially I had trouble with differently mapped pins. This is my first ARM custom made board. I used to make a lot of ATMEGA328P boards where everything was much easier. Here I was initially confused that every SAMD21G board has almost completely different pin mappings. I would like to make complete new menu entry for my board, still looking for some "template" how to do that. Arduino M0 has least pin mapping differences with my custom buard than e.g. MKRZERO that is completely different and has much less GPIOs connected.

the template https://github.com/jandrassy/my_boards

Thank you very much pert !

I solved it by your guideance. I added this at the end of variant.h :

// Alias Serial to SerialUSB
#define Serial                      SerialUSB

After this I had some compiler error because of multiple definition of serial object, so I have to edit also end of the variant.cpp to look like this:

Uart Serial2( &sercom0, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
Uart Serial1( &sercom5, PIN_SERIAL_RX, PIN_SERIAL_TX, PAD_SERIAL_RX, PAD_SERIAL_TX ) ;
void SERCOM0_Handler()
{
  Serial1.IrqHandler();
}

void SERCOM5_Handler()
{
  Serial2.IrqHandler();
}

Serial (previously declared as SerialUSB) now works fine as default. But I will stil have to make some tweak about Serial1 that I have physically broken out on PA10 / PA11 . This is currently not working, I am sure that after studying SERCOM structure in datasheet it will make clear what to change next. These SERCOMs look awesome but these are quite new to me, since on AVR everything was much more easier... :)

https://arduino.stackexchange.com/questions/54484/adding-a-custom-board-to-the-arduino-ide/60660#60660

You're welcome. I'm glad to hear it's working now.

The links Juraj has posted explain a very useful trick for extending on existing hardware packages by adding your own custom board definitions. The Arduino IDE has a very useful feature that allows you to reference resources from other installed hardware packages. This means you can create your own hardware package, installed to the hardware subfolder of your sketchbook folder, that only contains the boards.txt with the definition of your custom board and, in this case, the variant files. You can reference everything else from the Arduino SAMD Boards installation: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification#referencing-another-core-variant-or-tool

The disadvantage of modifying Arduino SAMD Boards directly is that all the changes you make need to be re-done every time you update to a new version of Arduino SAMD Boards. By making your changes in a custom hardware package that references Arduino SAMD Boards, your customizations will persist through updates.

If you have any questions on this subject, I'm sure Juraj or I can answer them.

Helium328PU: These SERCOMs look awesome but these are quite new to me, since on AVR everything was much more easier... :)

I have the same sentiment. It is really amazing, but I haven't dug into it beyond a quick play based on Arduino's tutorial: https://www.arduino.cc/en/Tutorial/SamdSercom

Hello everyone, hope you all had a good holidays!

Thank you both for your contributions. With your help, I was at the meantime able to achieve everything I needed. I rewrote board definitions, so now I have actually 3 serial ports working on my SAMD21G custom board. Serial in sketch outputs to USB VCOM and Serial1 and Serial2 I have broken out on my board.

I am adding here my board definition, it might help somebody in the future when doing custom definitions. Both codes are cut-offs of changes, cannot post full files because of post size limitations.

variant.cpp

// This is cutout of variant.cpp !!!

// Multi-serial objects instantiation
SERCOM sercom0( SERCOM0 ) ;
SERCOM sercom1( SERCOM1 ) ;
SERCOM sercom2( SERCOM2 ) ;
SERCOM sercom3( SERCOM3 ) ;
SERCOM sercom4( SERCOM4 ) ;
SERCOM sercom5( SERCOM5 ) ;

Uart Serial1( &sercom0, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;// Serial 1 on PA10/PA11 (pin 0/1)
Uart Serial2( &sercom5, PIN_SERIAL2_RX, PIN_SERIAL2_TX, PAD_SERIAL2_RX, PAD_SERIAL2_TX ) ;// Serial 2 on PA22/PA23 (pin 30/31)

void SERCOM0_Handler()
{
  Serial1.IrqHandler();
}

void SERCOM5_Handler()
{
  Serial2.IrqHandler();
}

variant.h

// This is cutout of variant.h !!!

// Serial (EDBG)
#define PIN_SERIAL_RX       (31ul)
#define PIN_SERIAL_TX       (30ul)
#define PAD_SERIAL_TX       (UART_TX_PAD_2)
#define PAD_SERIAL_RX       (SERCOM_RX_PAD_3)

// Serial1
#define PIN_SERIAL1_RX       (0ul)
#define PIN_SERIAL1_TX       (1ul)
#define PAD_SERIAL1_TX       (UART_TX_PAD_2)
#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_3)

// Serial2
#define PIN_SERIAL2_RX       (30ul)
#define PIN_SERIAL2_TX       (31ul)
#define PAD_SERIAL2_TX       (UART_TX_PAD_2)
#define PAD_SERIAL2_RX       (SERCOM_RX_PAD_3)


/*  =========================
 *  ===== SERCOM DEFINITION
 *  =========================
*/
extern SERCOM sercom0;
extern SERCOM sercom1;
extern SERCOM sercom2;
extern SERCOM sercom3;
extern SERCOM sercom4;
extern SERCOM sercom5;

extern Uart Serial;
extern Uart Serial1;
extern Uart Serial2;


#define SERIAL_PORT_USBVIRTUAL      SerialUSB
#define SERIAL_PORT_MONITOR         SerialUSB
// Serial has no physical pins broken out, so it's not listed as HARDWARE port
#define SERIAL_PORT_HARDWARE        Serial1
#define SERIAL_PORT_HARDWARE_OPEN   Serial1
#define SERIAL_PORT_HARDWARE        Serial2
#define SERIAL_PORT_HARDWARE_OPEN   Serial2

// Alias Serial to SerialUSB
#define Serial                      SerialUSB

pert, thank you for suggesting how to make custom board package. I exactly ran into these problems with overwritten files by update. Currently I have all changes stored in special files and everytime I am chnaging everything manually.

I tried you r suggestin to make my definitions in local sketch folder. I copied whole package I was editing to there, rename my board definition as "V2" while keeping currently working "V1" in standart path Sketches compiles fine when V2 is selected, but when I declare SPI.h I get this error:

In file included from /home/marekhelebrant/Arduino/board_init_test/board_init_test.ino:3:0:
/home/marekhelebrant/Arduino/hardware/samd/1.6.2/libraries/SPI/SPI.h: In member function 'void SPISettings::init_AlwaysInline(uint32_t, BitOrder, uint8_t)':
/home/marekhelebrant/Arduino/hardware/samd/1.6.2/libraries/SPI/SPI.h:67:42: error: 'SPI_MIN_CLOCK_DIVIDER' was not declared in this scope
     this->clockFreq = (clock >= (F_CPU / SPI_MIN_CLOCK_DIVIDER) ? F_CPU / SPI_MIN_CLOCK_DIVIDER : clock);

                                          ^~~~~~~~~~~~~~~~~~~~~
/home/marekhelebrant/Arduino/hardware/samd/1.6.2/libraries/SPI/SPI.h:67:42: note: suggested alternative: 'SPI_CLOCK_DIV32'
     this->clockFreq = (clock >= (F_CPU / SPI_MIN_CLOCK_DIVIDER) ? F_CPU / SPI_MIN_CLOCK_DIVIDER : clock);

                                          ^~~~~~~~~~~~~~~~~~~~~
                                          SPI_CLOCK_DIV32

That is strange, because it uses library that is included in board definitions (customized for Arduino Zero) and in standart path it compiles fine. Any guesses ?

I see the SPI_MIN_CLOCK_DIVIDER macro is conditionally defined in SPI.h if the ARDUINO_ARCH_SAMD macro is defined: https://github.com/arduino/ArduinoCore-samd/blob/020b419fc1dbca49b23b7c0b5e47d50fb2a04485/libraries/SPI/SPI.h#L40-L46

#if defined(ARDUINO_ARCH_SAMD)
  // The datasheet specifies a typical SPI SCK period (tSCK) of 42 ns,
  // see "Table 36-48. SPI Timing Characteristics and Requirements",
  // which translates into a maximum SPI clock of 23.8 MHz.
  // Conservatively, the divider is set for a 12 MHz maximum SPI clock.
  #define SPI_MIN_CLOCK_DIVIDER (uint8_t)(1 + ((F_CPU - 1) / 12000000))
#endif

Is the ARDUINO_ARCH_SAMD macro defined when compiling for your board? You can check by compiling this sketch for your custom board:

#ifndef ARDUINO_ARCH_SAMD
#error ARDUINO_ARCH_SAMD not defined
#endif
void setup() {}
void loop() {}

that macro is normally defined in the compilation recipes in platform.txt via the -DARDUINO_ARCH_{build.arch} option. {build.arch} is defined according to the name of the architecture folder of your hardware package: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification#hardware-folders-structure

pert: I see the SPI_MIN_CLOCK_DIVIDER macro is conditionally defined in SPI.h if the ARDUINO_ARCH_SAMD macro is defined.

Exactly, thats what I have checked first. But it seemed to me strange since I copied whole working package from standart path to "sketches" hardware folder.

pert: Is the ARDUINO_ARCH_SAMD macro defined when compiling for your board? You can check by compiling this sketch for your custom board:

#ifndef ARDUINO_ARCH_SAMD
#error ARDUINO_ARCH_SAMD not defined
#endif
void setup() {}
void loop() {}

This is a good point, compiler complains thats undefined. I really dont know why, I guess it has something to do with absolute/relative paths maybe? Or maybe that hardware package in "sketches" folder is not parsed in exactly same way as in standart path. Because paths and files are completely unchanged and are working when copied back to standart hardware folder.

Anyway, when looking through the code, it brought me to an idea. Since the "platform.txt" in my package defines only compiler options for my custom board, what about just hard defining architecture there in these three lines that are describint compiling recipes:

## Compile c files
recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {compiler.arm.cmsis.c.flags} {includes} "{source_file}" -o "{object_file}"

## Compile c++ files
recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {compiler.arm.cmsis.c.flags} {includes} "{source_file}" -o "{object_file}"

## Compile S files
recipe.S.o.pattern="{compiler.path}{compiler.S.cmd}" {compiler.S.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {compiler.arm.cmsis.c.flags} {includes} "{source_file}" -o "{object_file}"

all lines like this:

## Compile c files
recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_SAMD {compiler.c.extra_flags} {build.extra_flags} {compiler.arm.cmsis.c.flags} {includes} "{source_file}" -o "{object_file}"

Since board is always 100% SAMD21G there is actually no usable reason of dynamic definition of architecture. It shouldnt make any harm or incompatibies anywhere in the future right?

I don't see any problem with that workaround. Still, I'd be interested to know what the actual cause of the problem is. If you haven't made the change yet, go ahead and do a compilation with File > Preferences > Show verbose output during: compilation checked, then take a look at the output in the black console window at the bottom of the Arduino IDE window. There, you will see the commands generated from the compilation recipes with the {build.arch} property expanded.

is the architecture folder of your custom hardware package named samd?

Helium328PU:
Exactly, thats what I have checked first. But it seemed to me strange since I copied whole working package from standart path to “sketches” hardware folder.

why did you do that? didn’t you read how to create a custom definition for a board and refer the official package for core and tools? you need only boards.txt and variants folder for custom board

OK, so with workaround I came with previous post its working fine:

/bin/arm-none-eabi-gcc -mcpu=cortex-m0plus -mthumb -c -g -Os -w -std=gnu11 -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -MMD -DF_CPU=48000000L -DARDUINO=10808 -DARDUINO_SAMD_ZERO -DARDUINO_ARCH_SAMD -D__SAMD21G18A__ -DUSB_VID=0x1B4F -DUSB_PID=0x8D21 -DUSBCON "-DUSB_MANUFACTURER=\"Custom Manufacturer\"" "-DUSB_PRODUCT=\"Custom Product\""

I checked verbose output and here its how its compiled in unmodified version:

/bin/arm-none-eabi-g++ -mcpu=cortex-m0plus -mthumb -c -g -Os -w -std=gnu++11 -ffunction-sections -fdata-sections -fno-threadsafe-statics -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -w -x c++ -E -CC -DF_CPU=48000000L -DARDUINO=10808 -DARDUINO_SAMD_ZERO -DARDUINO_ARCH_1.6.2 -D__SAMD21G18A__ -DUSB_VID=0x1B4F -DUSB_PID=0x8D21 -DUSBCON "-DUSB_MANUFACTURER=\"Custom Manufacturer\"" "-DUSB_PRODUCT=\"Custom product\""

So its clear there is some sort of incorrect parsing of architecture that is "ARDUINO_ARCH_1.6.2" instead of "ARDUINO_ARCH_SAMD". Folder structure is fine:

/home/marekhelebrant/Arduino/hardware/samd/1.6.2/
├── boards.txt
├── bootloaders
├── cores
├── drivers
├── libraries
├── platform.txt
├── programmers.txt
└── variants

5 directories, 3 files

So now we know culprit at least :)

Juraj: why did you do that? didn't you read how to create a custom definition for a board and refer the official package for core and tools? you need only boards.txt and variants folder for custom board

https://arduino.stackexchange.com/questions/54484/adding-a-custom-board-to-the-arduino-ide/60660#60660

Well I really considered that. This might be clearer solution, but in case I wont look carefully what changes in core libraries, my board package might break up in future. Because I plan to release this board open to allow some software cooperation internationally I am afraid of problem with various IDE versions, libraries versions...

Packing everything separatedly will be much safer. I guess its the reason how Sparkfun and others are distributing their board definitions too...

Helium328PU:
OK, so with workaround I came with previous post its working fine:

/bin/arm-none-eabi-gcc -mcpu=cortex-m0plus -mthumb -c -g -Os -w -std=gnu11 -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -MMD -DF_CPU=48000000L -DARDUINO=10808 -DARDUINO_SAMD_ZERO -DARDUINO_ARCH_SAMD -D__SAMD21G18A__ -DUSB_VID=0x1B4F -DUSB_PID=0x8D21 -DUSBCON "-DUSB_MANUFACTURER=\"Custom Manufacturer\"" "-DUSB_PRODUCT=\"Custom Product\""

I checked verbose output and here its how its compiled in unmodified version:

/bin/arm-none-eabi-g++ -mcpu=cortex-m0plus -mthumb -c -g -Os -w -std=gnu++11 -ffunction-sections -fdata-sections -fno-threadsafe-statics -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -w -x c++ -E -CC -DF_CPU=48000000L -DARDUINO=10808 -DARDUINO_SAMD_ZERO -DARDUINO_ARCH_1.6.2 -D__SAMD21G18A__ -DUSB_VID=0x1B4F -DUSB_PID=0x8D21 -DUSBCON "-DUSB_MANUFACTURER=\"Custom Manufacturer\"" "-DUSB_PRODUCT=\"Custom product\""

So its clear there is some sort of incorrect parsing of architecture that is “ARDUINO_ARCH_1.6.2” instead of “ARDUINO_ARCH_SAMD”.
Folder structure is fine:

/home/marekhelebrant/Arduino/hardware/samd/1.6.2/

├── boards.txt
├── bootloaders
├── cores
├── drivers
├── libraries
├── platform.txt
├── programmers.txt
└── variants

5 directories, 3 files




So now we know culprit at least :)

Well I really considered that. This might be clearer solution, but in case I wont look carefully what changes in core libraries, my board package might break up in future. Because I plan to release this board open to allow some software cooperation internationally I am afraid of problem with various IDE versions, libraries versions... 

Packing everything separatedly will be much safer. I guess its the reason how Sparkfun and others are distributing their board definitions too...

you folder structure is wrong. vendor folder is missing

Adafruit and SparckFun boards packages refer the Arduino SAMD package.

Juraj: you folder structure is wrong. vendor folder is missing

Adafruit and SparckFun boards packages refer the Arduino SAMD package.

Well my folder structure is exact copy of original Sparkfun package. so it should not be wrong because its working. I dont see any "vendor" folder in any original packages either. So if you say that Sparkfun board package refers to Arduino SAMD package, so do my custom copy/clone is refering to it also :)¨

Anyway I dont see a point to continue this thread. My workaround in previos post works flawlessly and it should work fine in future.

I spilled a lot of Karma across you both of you guys - pert & Juraj.

Thank you very much for all the help provided here!

Helium328PU: Well my folder structure is exact copy of original Sparkfun package.

The folder structure is different for packages installed in the sketchbook folder. It goes:

{Sketchbook folder} |hardware |{vendor folder} |_{architecture folder} |_boards.txt

There is no version folder for the sketchbook installed packages.

So you can see that your package had a vendor of "samd" and an architecture of "1.6.2".

Helium328PU: So if you say that Sparkfun board package refers to Arduino SAMD package, so do my custom copy/clone is refering to it also :)¨

Juraj is talking about this reference system: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification#referencing-another-core-variant-or-tool That allows you to create very minimal custom hardware packages that may contain as little as a single boards.txt file, and reference all other resources from another hardware package.

Helium328PU: My workaround in previos post works flawlessly and it should work fine in future.

I'm glad to hear it's working!

Helium328PU: Thank you very much for all the help provided here!

You're welcome. Enjoy! Per