Close

Programming a SAMD bootloader using JLink & Linux

tom-magnierTom Magnier wrote 03/13/2019 at 09:14 • 3 min read • Like

I have a custom board using a SAMD21 microcontroller (as used in Arduino Zero and other dev boards).

After soldering, the chip is blank and a bootloader is useful to upload code via the USB connection. 

I found an excellent (as always) tutorial by Adafruit using a JLink probe to upload their custom bootloader here : https://learn.adafruit.com/how-to-program-samd-bootloaders/overview

Unfortunately, directions are only provided for a Windows computer, using Atmel Studio.

Here is how to do it using the JLink command line software under Linux (and it should work with Mac as well).

To enable/disable the bootloader protection, I found very useful information here : https://roamingthings.de/posts/use-j-link-to-change-the-boot-loader-protection-of-a-sam-d21/

You should create two files with the info from the above post :

File SAMD_set_bootloader_protection_8k.mot :

S214804000FAC7E0D85DFCFFFFFFFFFFFFFFFFFFFF63
S9030000FC

File SAMD_clear_bootloader_protection.mot :

S214804000FFC7E0D85DFCFFFFFFFFFFFFFFFFFFFF5E
S9030000FC

In the same directory, download the Adafruit bootloader from https://learn.adafruit.com/how-to-program-samd-bootloaders/setup

So here is the complete process to burn a bootloader to a blank SAMD21 chip :

cd ATSAMD21_Bootloader
$ JLinkExe
SEGGER J-Link Commander V6.32h (Compiled Jul  5 2018 18:15:02)
DLL version V6.32h, compiled Jul  5 2018 18:14:58

Connecting to J-Link via USB...O.K.
Firmware: J-Link Lite-Cortex-M V8 compiled Sep 15 2016 12:05:01
Hardware version: V8.00
S/N: 518006749
License(s): GDB
VTref=3.313V


Type "connect" to establish a target connection, '?' for help
J-Link>connect
Please specify device / core. : ATSAMD21G18
Type '?' for selection dialog
Device>atsamd21g18
Please specify target interface:
  J) JTAG (Default)
  S) SWD
TIF>s
Specify target interface speed [kHz]. : 4000 kHz
Speed>
Device "ATSAMD21G18" selected.


Connecting to target via SWD
InitTarget()
Found SW-DP with ID 0x0BC11477
Scanning AP map to find all available APs
AP[1]: Stopped AP scan as end of AP map has been reached
AP[0]: AHB-AP (IDR: 0x04770031)
Iterating through AP map to find AHB-AP to use
AP[0]: Core found
AP[0]: AHB-AP ROM base: 0x41003000
CPUID register: 0x410CC601. Implementer code: 0x41 (ARM)
Found Cortex-M0 r0p1, Little endian.
FPUnit: 4 code (BP) slots and 0 literal slots
CoreSight components:
ROMTbl[0] @ 41003000
ROMTbl[0][0]: E00FF000, CID: B105100D, PID: 000BB4C0 ROM Table
ROMTbl[1] @ E00FF000
ROMTbl[1][0]: E000E000, CID: B105E00D, PID: 000BB008 SCS
ROMTbl[1][1]: E0001000, CID: B105E00D, PID: 000BB00A DWT
ROMTbl[1][2]: E0002000, CID: B105E00D, PID: 000BB00B FPB
ROMTbl[0][1]: 41006000, CID: B105900D, PID: 001BB932 MTB-M0+
Cortex-M0 identified.
J-Link>loadfile SAMD_clear_bootloader_protection.mot
Downloading file [SAMD_clear_bootloader_protection.mot]...
Comparing flash   [100%] Done.
Erasing flash     [100%] Done.
Programming flash [100%] Done.
Verifying flash   [100%] Done.
J-Link: Flash download: Bank 1 @ 0x00804000: 1 range affected (16 bytes)
J-Link: Flash download: Total time needed: 0.050s (Prepare: 0.037s, Compare: 0.002s, Erase: 0.000s, Program: 0.003s, Verify: 0.000s, Restore: 0.006s)
O.K.
J-Link>r
Reset delay: 0 ms
Reset type NORMAL: Resets core & peripherals via SYSRESETREQ & VECTRESET bit. 
J-Link>loadbin bootloader-feather_m0-v2.0.0-adafruit.9.bin,0
Downloading file [bootloader-feather_m0-v2.0.0-adafruit.9.bin]...
Comparing flash   [100%] Done.
Verifying flash   [100%] Done.
J-Link: Flash download: Bank 0 @ 0x00000000: Skipped. Contents already match
O.K. 
J-Link>loadfile SAMD_set_bootloader_protection_8k.mot
Downloading file [SAMD_set_bootloader_protection_8k.mot]...
Comparing flash   [100%] Done.
Erasing flash     [100%] Done.
Programming flash [100%] Done.
Verifying flash   [100%] Done.
J-Link: Flash download: Bank 1 @ 0x00804000: 1 range affected (16 bytes)
J-Link: Flash download: Total time needed: 0.050s (Prepare: 0.037s, Compare: 0.002s, Erase: 0.000s, Program: 0.003s, Verify: 0.000s, Restore: 0.006s)
O.K.

Now unplug and plug back your board and the SAMD21 should enumerate as a composite USB mass storage device and serial interface.

Like

Discussions

deʃhipu wrote 01/30/2022 at 11:35 point

Thank you for this! Previously I would just burn the bootloader on new chips without caring for the lock, and then use the UF2 to upgrade the bootloader, which sets the lock.

If you want an alternative to jlink, but don't want to have to use openocd, the black magic probe can be flashed onto a blue pill board, and used to program those chips (I think, I didn't try myself).

  Are you sure? yes | no

lbdroidman wrote 09/03/2019 at 23:22 point

I like this, but if you're going to do something, you might as well go all the way.

While the Linux version of j-link software is a good step from the msbinarypit, it's still closed source software, which is the polar opposite of the spirit of writing and running your own code. To do this all the way means replacing j-link software with OpenOCD.

Create a directory, put your bootloader.bin in it, create an openocd.cfg file with the following contents, and then just execute "openocd":

source [find interface/jlink.cfg]
transport select swd
set CHIPNAME at91samd21e18
source [find target/at91samdXX.cfg]
init
reset
halt
at91samd bootloader 0
reset
program bootloader.bin verify reset
shutdown

  Are you sure? yes | no

Tom Magnier wrote 09/26/2019 at 12:04 point

Thanks! I tried a long time ago to get started with openOCD and finally gave up, I will have to give it a try next time. It sure looks as easy as jlink, and for sure easier to integrate into custom scripts.

  Are you sure? yes | no

Alex wrote 01/29/2022 at 23:41 point

Great comment! Will probably play around with this and openOCD soon. Not tested this myself yet, but is a extra line like this

"at91samd bootloader 8192"
needed at the end to enable the bootloader protection again

  Are you sure? yes | no