I recently started working with a Cortex M0+ board from MattairTech. Their MT-D21E board hosts an Atmel SAM D/C/L21 Cortex M0+ microcontroller and is compatible with the Arduino IDE.
Now, I don’t like using the Arduino IDE. I find it clunky and lacking in all the richness an actual editor can give you. A year ago I created an Arduino makefile project so that I could avoid using the IDE (and, by extension, their bloated libraries). I wanted to do the same for this Cortex M0+ board, but ran into issues.
The Cortex M0+ board doesn’t use avrdude
to flash the code onto the device; it uses BOSSA instead. The usage of bossac
is fairly straight forward:
1 |
$ ./bossac -i -d --port=ttyACM0 -e -w <PATH_TO_BINARY> ...etc... |
But, bossac
didn’t seem to like my device most of the time. I received a range of odd behaviour failing to find the device on /dev/ttyACM0
to the device being busy.
1 2 3 4 5 6 7 8 9 10 11 |
$ ./bossac -i -d Trying to connect on ttyACM0 Set binary mode Send auto-baud Set binary mode Trying to connect on ttyS3 Trying to connect on ttyS2 Trying to connect on ttyS1 Trying to connect on ttyS0 Auto scan for device failed Try specifying a serial port with the '-p' option |
1 2 |
$ ./bossac -i -d --port=ttyACM0 No device found on ttyACM0 |
Frustrated, I spent a few hours searching and digging through the internet. There were a good number of websites stating that the device needs to be set to 1200 baud so that it can switch into the bootloader. This voodoo should be triggered via:
1 |
$ stty -F /dev/ttyACM0 1200 cs8 raw -clocal -echo -icrnl |
But, it doesn’t quite work all the time. So, instead, I started to poke through the Arduino source code to find out exactly what they did to properly trigger the bootloader. Their solution is to open the serial, set the boad rate to 1200, disable DTR, and finally close. I’d bet that the stty
command doesn’t do this exactly and, therefore, cannot always reset the serial port.
The solution was to write a quick python script to do those steps exactly:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#!/usr/bin/python # usage: python cdc_reset.py <DEVICE> # where <DEVICE> is typically some /dev/ttyXXX import sys import serial ser = serial.Serial() ser.port=sys.argv[1] ser.open(); ser.baudrate=1200 # This is magic. ser.rts = True ser.dtr = False ser.close() |
And that’s it. Run this script before calling bossac
and it should do the job. Code is also available on github.