2020-11-30
md
The XIAO as a USB-Serial Converter
<-Seeeduino XIAO Serial Communication Interfaces (SERCOM)

After struggling with the previous post, I decided to do something fun. Without any planning, I ended up using a Seeeduino XIAO as a USB to serial converter.

I wanted to revisit the obligatory blink sketch on a "blue pill" (STM32F103C8) obtained last July. Initially all attempts at flashing new firmware on that board using a direct USB connection failed. Luckily, it was relatively easy to load the firmware onto the STM32 flash memory using the serial port (PA9 is RX and PA10 is TX). The LED connected to pin PC13 flashing at the correct frequency confirmed that the board was not a dud. And since there was a working serial connection, it was a simple matter to start a terminal and display messages sent from the blue pill. The sketch is nothing fancy.

#include <Arduino.h> #define BAUD 115200 #define BEATS 2 void setup() { Serial.begin(BAUD); //I/O pins and LED_BUILTIN defined in ~/.platformio/packages/framework-arduinoststm32/variants/PILL_F103XX/variant.h pinMode(LED_BUILTIN, OUTPUT); Serial.printf("LED_BUILTIN (PC13): %d\n", LED_BUILTIN); Serial.println("Setup completed"); } void loop() { // Assymetric blink to verify that the LED is "active low" for (int i=1;i<=BEATS; i++) { digitalWrite(LED_BUILTIN, LOW); // Turn the LED on (Note that LOW is the voltage level) Serial.print("ON, "); delay(100); digitalWrite(LED_BUILTIN, HIGH); // Turn the LED off (Note that HIGH is the voltage level) delay(100); } //digitalWrite(LED_BUILTIN, HIGH); Serial.println(" OFF"); delay(2000); }

Every two seconds, the LED is flashed on for a specified number of times or "beats". The asymetric on and off times confirmed that the built in LED is turned on when pin PC13 is set LOW. Setting different values for the BEATS macro made it easy to check that a new version of the sketch had been successfully flashed on the STM32. The output in the terminal was not very exciting but again it confirmed that everything was working.

Setup completed ON, ON, OFF ON, ON, OFF ON,

Following the suggestion of many, I purchased an ST-LINK-V2 in-circuit debugger/programmer, not the real thing but the ubiquitous cheap version that can be seen to the right. That was a good decision, because flashing the blue pill became a very simple task. There's no fiddling with jumpers and pressing the reset button. Uploading to a STM32 with the ST-LINK is just as simple as uploading to an ESP8266 board such as the D1 Mini or nodeMCU. But beyond that, as the name suggest, it is possible to fully debug a sketch using the ST-LINK. Breakpoints can be set, the value of variables can be viewed or set, single stepping though the program is possible and so on. There's one little downside. To have access to the serial port of the blue pill from a terminal emulator on the desktop, it remains necessary to connect the board to a USB-Serial adapter.

This second time around, all the USB-Serial converters were either connected to a project or lost in some parts box. On the other hand there was a cute Seeeduino XAIO at hand. One of its serial communication interfaces is connected to the USB port and another interface is available on pins A6 (Tx) and A7 (Rx) (see Seeeduino XIAO Serial Communication Interfaces (SERCOM)), so why not try to use is a USB-serial converter.

When connected over USB, the XIAO shows up on the desktop as a USB and serial device.

michel@hp:~$ lsusb ... Bus 003 Device 058: ID 2886:802f Bus 003 Device 046: ID 0483:3748 STMicroelectronics ST-LINK/V2 ... michel@hp:~$ ls /dev/ttyACM* /dev/ttyACM0

Because there are no string descriptors for the idVendor and idProduct, it is not immediately obvious that 2886:802f is the XIAO. If the list of all USB devices is displayed with the lsusb before connecting the XAIO to the desktop and then again after connecting it, it will be easy to spot the new USB device and the new TTY device. Just to make sure, a verbose listing will confirm that the XIAO is connected.

michel@hp:~$ sudo lsusb -v -d 2886: Bus 003 Device 058: ID 2886:802f Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 239 Miscellaneous Device bDeviceSubClass 2 ? bDeviceProtocol 1 Interface Association bMaxPacketSize0 64 idVendor 0x2886 idProduct 0x802f bcdDevice 1.00 iManufacturer 1 Seeed iProduct 2 Seeeduino XIAO ...

To use the XAIO as as serial device all I had to do was to connect 3 wires for the serial link between the XIAO and the STM32. Do NOT connect the two device Vcc pins together as each device is indepently powered by the desktop USB port to which it is connected.

Not shown above is a Dupont wire from another ground pin on the blue pill which is only used to reset the XIAO when it needs to be put in programming mode. After completing the wiring, the correct software had to be created and flashed on the XAIO. This was quite easy.

#include <Arduino.h> void setup() { Serial1.begin(115200); // baudrate } void loop() { // Transmit on pin A6 (Tx of Serial 1) every byte // received over the USB connection (Serial) // while (Serial.available()) Serial1.write(Serial.read()); Serial1.flush(); // Tranmit over the USB link (Tx of Serial) every byte // received on pin A7 (Rx of Serial1) // while (Serial1.available()) Serial.write(Serial1.read()); Serial.flush(); }

Once that was downloaded to the XIAO, it was possible to see the blue pill output to its Serial device.

Setup completed ON, ON, OFF ON, ON, OFF ON,

It is relavely easy to write a string to the STM32 over the serial connection using a terminal emulator on the desktop. The STM32 will respond by echoing each line of text received to the terminal. It will be more responsitve if all timing delays are removed from the blink sketch.

#include <Arduino.h> #define BAUD 115200 #define BEATS 2 #define DELAY 4000 void setup() { Serial.begin(BAUD); pinMode(LED_BUILTIN, OUTPUT); Serial.println("Setup completed"); } unsigned long lastblink = 0; // last time a set of led blinks were sent unsigned long lastbeat = 0; // last time the LED was turned on or off String s = ""; // buffer where received chars are stored until echoed char c; // last char received from Serial int beat = 0; // number of bool ledOn = false; void loop() { if (millis() - lastblink > DELAY) { lastblink = millis(); lastbeat = millis(); beat = BEATS; digitalWrite(LED_BUILTIN, LOW); // Turn the LED on (Note that LOW is the voltage level) Serial.print("ON, "); ledOn = true; } if (beat > 0 && millis() - lastbeat > 100) { if (ledOn) { digitalWrite(LED_BUILTIN, HIGH); // Turn the LED off (Note that HIGH is the voltage level) ledOn = false; beat--; if (!beat) Serial.println(" OFF"); } else { digitalWrite(LED_BUILTIN, LOW); // Turn the LED on (Note that LOW is the voltage level) Serial.print("ON, "); ledOn = true; } lastbeat = millis(); } while (Serial.available()) { c = Serial.read(); if (c == 0xA) { Serial.printf("\nRx: %s\n", s.c_str()); s = ""; } else { s += c; } } }

Here is the output displayed on the terminal connected to /dev/ttyACM0. The first string typed into the terminal was "hi" which was done at the same time as the blue pill was blinking its LED and writing to the same serial link.

ON, ON, OFF hON, iON, OFF Rx: hi ON, ON, OFF ON, ON, OFF ON, ON, OFF hello Rx: hello ON, ON, OFF

The second string, "hello" was typed in the 3 or 4 seconds between LED flashes so the input from the keyboard and the echo from the blue pill, preceeded with "Rx :" are clearly visible. That's very good, it works. Note that once the second blink sketch is flashed on the STM32, it is possible to disconnect the ST-LINK programmer. Of course, it will then be necessary to provide power to the blue pill from the XIAO. Either the 3.3 volts or 5 volts lines can be connected together, just don't mix them up. Sending 5 volts to a device expecting 3.3 volts will not give a good result.

The next test seemed obvious: update the blue pill firmware using the serial protocol with the XIAO as the USB to serial adapter. Unfortunately, this did not work.

Configuring upload protocol... AVAILABLE: blackmagic, dfu, jlink, serial, stlink CURRENT: upload_protocol = serial Looking for upload port... Auto-detected: /dev/ttyACM0 Uploading .pio/build/genericSTM32F103C8/firmware.bin Failed to read ACK byte Unexpected reply from device on command 0x01 stm32flash Arduino_STM32_0.9 http://github.com/rogerclarkmelbourne/arduino_stm32 Using Parser : Raw BINARY Interface serial_posix: 115200 8E1 *** [upload] Error 1

According to the output displayed on the terminal, acknowledgement of command 0x01 was not provided by the XIAO. In any case, that was a long shot.

For those who would like to replicate this experiment, here is the configuration file, platformIO.ini, for the blink project on the blue pill.

[env:genericSTM32F103C8] platform = ststm32 board = genericSTM32F103C8 ;board = bluepill_f103c8 framework = arduino upload_protocol = stlink monitor_speed = 115200 monitor_flags = --eol LF --echo

It does not seem to matter which board definition is used, genericSTM32F103C8 or bluepill_f103c8. And here is the configuration file for the terminal project on the XIAO

[env:seeed_xiao] platform = atmelsam board = seeed_xiao framework = arduino monitor_speed = 115200

I'll end with a reference to an entry in the Seeed Wiki: How to use Seeeduino XIAO to log in to your Raspberry PI. It is basically the same as what is done above except that the XIAO is connected to the serial port of a Raspberry Pi. When comparing the two terminal programs, don't forget that SerialUSB and Serial refer to the same device.

// Alias Serial to SerialUSB
#define Serial SerialUSB

Those are the two last lines of the variant.h file in the Seeed fork of the "Arduino Core for SAMD21 and SAMD51 CPU". On my Linux desktop system, that file is found in the .platformio/packages/framework-arduino-samd-seeed/variants/XIAO_m0/ directory in my home directory.

<-Seeeduino XIAO Serial Communication Interfaces (SERCOM)