Explorations into how to program SAMD21 chips like those in Trinket M0, Arduino Zero, etc.
How to program a SAMD21 (or other ARM chip really) using a variety of methods, in order to burn a UF2 bootloader or my own programs.
Ways to program a SAMD21 board: (e.g. Trinket M0, QTPy M0, etc)
- Reprogram bootloader using UF2
- Program with Arduino sketches using uf2
- Talk to chip w/ GDB using JTAG/SWD programmer (OpenOCD / JLink via commandline, no Atmel Studio)
- Reprogram bootloader with JTAG/WWD programmer (OpenOCD / JLink via commandline, no Atmel Studio)
- Program chip with Arduino sketch using JTAG/SWD programmer
Progress so far...
- Double-click button on Trinket M0 to get into UF2 bootloader
- LED will heartbeat
- Trinket M0 shows up as "TRINKETBOOT" disk
- Create new UF2 bootloader
git clone https://github.com/Microsoft/uf2-samd21/
cd uf2-samd21
make BOARD=trinket
- Copy resulting file
update-bootloader.uf2
to disk - Tada, new bootloader installed
- Edit file
boards/trinket/board_config.h
to change bootloader id strings
- Create sketch as normal
- Open build tmp directory and copy out .bin file
- Use uf2-samd21 'bin2uf2.js' script (from 'scripts' in uf2-samd21 repo) to convert to uf2:
node uf2-samd21/scripts/bin2uf2.js sketch_nov24a.ino.bin sketch_nov24a.uf2
- Copy uf2 file to TRINKETBOOT and tada programmed!
- TODO: Look into what bin2uf2 is doing
- Solder pads to SWD & SWC pins on back of Trinket M0
- Connect following pins from JLink to Trinket M0:
| black | Jlink Gnd | Trinket M0 Gnd pin |
| red | Jlink VTref | Trinket M0 3v3 pin |
| green | Jlink SWDIO | Trinket M0 SWD solder pad |
| blue | Jlink SWCLK | Trinket M0 SWC solder pad |
- Power Trinket M0 via USB. Power Jlink via USB.
"VTref" is used to detect target power is applied. It is a signal TO the programmer.
- Connect Jlink to Trinket M0 as above
- Install openocd with
brew install openocd
- Modify
uf2-samd21/scripts/dbgtool.js
to use Jlink instead of EDBG.- Change openocd path to use 0.1.0 or better: let openocdBin = "/usr/local/bin/openocd"
- Modify
uf2-samd21/scripts/dbgtool.js
: let zeroCfg = '/Users/tod/projects/samd/openocd-scripts/samd21-jlink.cfg'
- Must have new openocd-script samd21-jlink.cfg:
- Run "
make burn
" inuf2-samd21
- Alternatively, run:
cd uf2-samd21
node ./scripts/dbgtool.js fuses
node ./scripts/dbgtool.js ./build/trinket/bootloader.bin
-
Install
openocd
as above -
Get the
bootloader-trinket_m0-v3.16.0.bin
file from adafruit/uf2-samdx1 -
Connect Jlink to Trinket M0 as above
-
Program on commandline:
openocd -f ./openocd_jlink_samd21.cfg \ -c "init; targets; halt; " \ -c "at91samd bootloader 0;" \ -c "program bootloader-trinket_m0-v3.16.0.bin verify;" \ -c "at91samd bootloader 8192; reset; shutdown"
NOTE: the
at91samd bootloader 0;
disables bootloader protection and allows you to rewrite the bootloader. Theat91samd bootloader 8192;
re-enables bootloader protection. (from this adfruit forum post) -
Can also erase entire chip (assuming no bootloader lock):
openocd -f ./openocd_jlink_samd21.cfg -c "init; targets; at91samd chip-erase; shutdown"`
or in a more general way:
openocd -f ./openocd_jlink_samd21.cfg -c "init; targets; flash erase_sector 0 1 last; shutdown"`
-
Or list which targets are connected:
openocd -f openocd_jlink_samd21.cfg -c "init; targets; shutdown"
- TODO: Get programming to work for Arduino sketches (specifically, can program but sketch doesn't run)
-
TODO: try:
-c "init; targets; reset halt; program sketch.bin 0x00002000
-
Install
openocd
and getbootloader-xxx.bin
-
Connect Atmel ICE similar to JLink by using adapter like in image below
-
Program on commandline:
openocd -f ./openocd_jlink_samd21.cfg \ -c "init; targets; halt; " \ -c "at91samd bootloader 0;" \ -c "program bootloader-trinket_m0-v3.16.0.bin verify;" \ -c "at91samd bootloader 8192; reset; shutdown"
NOTE: the
at91samd bootloader 0;
disables bootloader protection and allows you to rewrite the bootloader. Theat91samd bootloader 8192;
re-enables bootloader protection. (from this adfruit forum post) -
You can also choose to install
telnet
and do these commands interactively:
In one terminal window run openocd
:
% openocd -f ./openocd_atmel-ice_samd21.cfg
Open On-Chip Debugger 0.12.0
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
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 = 01.00.0021
Info : CMSIS-DAP: Serial# = J41800054170
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 : [at91samd21e18.cpu] Cortex-M0+ r0p1 processor detected
Info : [at91samd21e18.cpu] target has 4 breakpoints, 2 watchpoints
Info : starting gdb server for at91samd21e18.cpu on 3333
Info : Listening on port 3333 for gdb connections
And in another terminal window, run telnet
and then openocd commands:
% telnet localhost 4444
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> targets
TargetName Type Endian TapName State
-- ------------------ ---------- ------ ------------------ ------------
0* at91samd21e18.cpu cortex_m little at91samd21e18.cpu running
> reset halt
[at91samd21e18.cpu] halted due to debug-request, current mode: Thread
xPSR: 0x21000000 pc: 0x00000264 msp: 0x20002de0
> at91samd bootloader 0
> flash erase_sector 0 1 last
SAMD MCU: SAMD21E18A (256KB Flash, 32KB RAM)
erased sectors 1 through 1023 on flash bank 0 in 6.106292s
> program bootloader-trinket_m0-v3.16.0.bin verify
[at91samd21e18.cpu] halted due to debug-request, current mode: Thread
xPSR: 0x21000000 pc: 0x00000264 msp: 0x20002de0
** Programming Started **
** Programming Finished **
** Verify Started **
** Verified OK **
> at91samd bootloader 8192
> reset
> shutdown
-
Install
openocd
and getbootloader-xxx.bin
-
Connect Trinket M0 to STLink using only: GND, SWDIO, SWCLK, as in image below
-
Program on commandline:
openocd -f ./openocd_atmel-ice_samd21.cfg \ -c "init; targets; halt; program bootloader-trinket_m0-v3.16.0.bin verify reset; shutdown"
- Or interactively:
% telnet localhost 4444
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> reset halt
[at91samd21g18a.cpu] halted due to debug-request, current mode: Thread
xPSR: 0x61000000 pc: 0x00000264 msp: 0x20002de0
> targets
TargetName Type Endian TapName State
-- ------------------ ---------- ------ ------------------ ------------
0* at91samd21g18a.cpu hla_target little at91samd21g18a.cpu halted
> flash erase_sector 0 1 last
SAMD MCU: SAMD21E18A (256KB Flash, 32KB RAM)
erased sectors 1 through 1023 on flash bank 0 in 5.069648s
> program /Users/tod/Downloads/bootloader-trinket_m0-v3.16.0.bin verify reset
[at91samd21g18a.cpu] halted due to debug-request, current mode: Thread
xPSR: 0x61000000 pc: 0x00000264 msp: 0x20002de0
** Programming Started **
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **
- https://learn.adafruit.com/adafruit-feather-m0-express-designed-for-circuit-python-circuitpython/uf2-bootloader-details
- https://learn.adafruit.com/debugging-the-samd21-with-gdb/setup
- https://learn.adafruit.com/proper-step-debugging-atsamd21-arduino-zero-m0/lets-go
- http://www.instructables.com/id/ATSAMD21g18-Bootloader-With-J-link-Debugger/
- https://github.com/geomatsi/stm32-tests/blob/master/boards/stm32f103-mini/scripts/openocd-jlink-swd.cfg
- https://learn.adafruit.com/programming-microcontrollers-using-openocd-on-raspberry-pi/wiring-and-test
- https://omzlo.com/articles/programming-the-samd21-using-atmel-ice-with-openocd-(updated)