todbot / samd21-programming-notes

SAMD21 programming notes
22 stars 5 forks source link

SAMD21 Programming Notes

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)

Progress so far...

Reprogram bootloader via UF2 - Trinket M0

  1. Double-click button on Trinket M0 to get into UF2 bootloader

    • LED will heartbeat
    • Trinket M0 shows up as "TRINKETBOOT" disk
  2. Create new UF2 bootloader

    git clone https://github.com/Microsoft/uf2-samd21/
    cd uf2-samd21
    make BOARD=trinket
  3. Copy resulting file update-bootloader.uf2 to disk

  4. Tada, new bootloader installed

  5. Edit file boards/trinket/board_config.h to change bootloader id strings

Program Arduino sketch with UF2 - Trinket M0

  1. Create sketch as normal
  2. Open build tmp directory and copy out .bin file
  3. 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
  4. Copy uf2 file to TRINKETBOOT and tada programmed!
  5. TODO: Look into what bin2uf2 is doing

Connecting Jlink JTAG/SWD to Trinket M0

  1. Solder pads to SWD & SWC pins on back of Trinket M0

  2. 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 |
  3. 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.

Update bootloader via JLink JTAG/SWD w/ uf2-samd21 - Trinket M0

  1. Connect Jlink to Trinket M0 as above
  2. Install openocd with brew install openocd
  3. 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'
      1. Must have new openocd-script samd21-jlink.cfg:
      2. Run "make burn" in uf2-samd21
      3. Alternatively, run:
        cd uf2-samd21
        node ./scripts/dbgtool.js fuses
        node ./scripts/dbgtool.js ./build/trinket/bootloader.bin

Update bootloader via OpenOCD and JLink on commandline - Trinket M0

  1. Install openocd as above

  2. Get openocd_jlink_samd21.cfg

  3. Get the bootloader-trinket_m0-v3.16.0.bin file from adafruit/uf2-samdx1

  4. Connect Jlink to Trinket M0 as above

  5. 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. The at91samd bootloader 8192; re-enables bootloader protection. (from this adfruit forum post)

  6. 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"`
  7. Or list which targets are connected:

    openocd -f openocd_jlink_samd21.cfg -c "init; targets; shutdown"
  1. TODO: try:

    -c "init; targets; reset halt; program sketch.bin 0x00002000

Update bootlaoder via OpenOCD and Atmel ICE on the commandline - Trinket M0

  1. Install openocd and get bootloader-xxx.bin

  2. Get openocd_atmel-ice_samd21.cfg

  3. Connect Atmel ICE similar to JLink by using adapter like in image below

  4. 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. The at91samd bootloader 8192; re-enables bootloader protection. (from this adfruit forum post)

  5. 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

Update bootlaoder via OpenOCD and STLink v2 - Trinket M0

  1. Install openocd and get bootloader-xxx.bin

  2. Get openocd_stlink_samd21.cfg

  3. Connect Trinket M0 to STLink using only: GND, SWDIO, SWCLK, as in image below

  4. 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"
  5. 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

Useful links: