Burning Zero bootloader with Beaglebone as SWD programmer

OpenOCD has support for bitbanging the jtag or swd protocol over gpio’s. So if you have a board that can run OpenOCD and on which you have access to gpio’s, you can use that as a jtag or swd programmer. The following describes how to use a beaglebone for this purpose but any board with 3V3 gpio’s (e.g. raspberry pie) will do…

I followed these instructions to set up the beaglebone. I opted for the debian file system.

Following list of things to install before building OpenOCD will probably save you from having to iteratively install packages untill OpenOCD builds. Of coarse the exact list will change if the initial content of the debian file system changes:

openocd is now installed in /usr/local/bin and the scripts it uses are in /usr/local/share/openocd/scripts.

We need an extra config file to describe the beaglebone programmer. I added it here: /usr/local/share/openocd/scripts/interface/bb.cfg. The choice of the gpio’s is up to you, I picked gpio 38 (i.e. gpio1[6], pin header P8_03) and 39 (i.e. gpio1[7], pin header P8_04) as swd_io and swd_sck respectively, so bb.cfg looks like this:

#
# Config for beaglebone interface
#
# This is best used with a fast enough buffer but also
# is suitable for direct connection if the target voltage
# matches bone's 3.3V
#
# Do not forget the GND connection.
#
interface sysfsgpio
# minimal swd setup
sysfsgpio_swdio_num 38
sysfsgpio_swclk_num 39
# (Did not manage to make srst work:)
# sysfsgpio_srst_num 45

Store dot-cc’s bootloader (samd21_sam_ba.bin) in a directory of your choice on the beaglebone.

In that dir, create a openocd.cfg file. OpenOCD will read this file to know what it has to do, and how. In our case the file instructs OpenOCD to use the beaglebone as interface (programmer) and tells it we’re programming a samd21 chip.

OpenOCD is now constantly polling the device and it is ready to accept new instructions from us via telnet or gdb. You could log into openocd using telnet from your pc (or from the bone) and inspect memory, run code, start debugging…

If on the other hand you are just interested in burning the bootloader, you could add following line at the end of openocd.cfg and start openocd again.

Thanks as well for these instructions; it gives me hope that I won’t need to lay down an Atmel embedded debugger to flash the bootloader from my BBB.

I’m having some issues, however, in that I have followed your guide precisely, but I’m not able to successfully “examine” the board from OpenOCD, so all subsequent functions fail as well. My setup is nearly identical to yours, the only difference being that I am using a Beaglebone Black instead of the original Beaglebone. I have tried several different pins, but to no avail. Is there something in your setup that I might be missing, such as manually handling the chip reset lines from the BBB, since OpenOCD doesn’t seem to be able to? I also did a comparison between the output from an atmel ice programmer (successful) and my unsuccessful bitbanging with a logic analyzer, and the output looks completely different. I also tried running openocd with nice –20 and just about everything killed on the BBB, no difference.

Any guidance on what might be the issue? If needed, I can send my logic analyzer captures or other information.

On the BBB, many of the pins on header P8 are already used by the BBB board itself for the eMMC or the lcd (hdmi). Carefully select the gpio’s for openocd. If you would pick such a conflict pin, you will probably damage your BBB. So carefully read the section “BeagleBoneBlack Cape Compatibility” in the user manual. On header P8: pin 7 (gpio 66) as swdio and pin 8 (gpio 67) as swclk are OK. I gave it a quick try with these pins on BBB, and it worked.

Hmm. I tried those exact pins, making sure no other drivers were using them, and my logic analyzer output looks a bit more sane now, but I’m still seeing the same openocd errors. Here are all of the details:

I’ve tried on both an Arduino Zero Pro and a custom SAMD21 board, both of which are able to be programmed successfully using the ICE programmer. In both cases, the boards were properly powered and grounded.

A bit stumped at this point; any more ideas? Thanks again for your help!

Grabbed a completely fresh beaglebone black and worked through the guide again word for word, using pins 66 and 67. Slightly different result, but still can’t get past the examination step:http://pastebin.com/tEkGaR3P

I did a git pull in my OpenOCD repo in order to have the most recent version. Guess what, I now have the same problem: the very first swd transaction fails like this:
Debug: 243 152 bitbang.c:449 bitbang_swd_read_reg(): JUNK DP read reg 0 = ffffffff .Odd enough the problem persists if I go revert to my previous version using git reset –hard dfc6658. …

Forget what I wrote above: it was a manipulation error: the M0’s USB cable was not connected, so I was trying without the target powered.

I have now the same version as yours (git commit dfc6658), and it works fine on BBB.

So the difference must be the target. You probably already triple checked wiring and power… Just spawning some ideas: for the Pro: I wonder whether the edbg chip nicely tristates the swd signals when it is or should be idle? (For my M0, it is simple: the swd headers are connected only to the samd). Do you have another target to test with? a due (never tried that myself though…)? incidently an stm32f4 discovery board? (those are easy to disconnect from their on board programmer…)

In case you want to try with an arduino due as target (this would rule out something is driving the swd pins against the bbb), I have checked that this works with the bbb setup.
Here is an openocd.cfg that flashes a blink sketch (compiled with the ide) to the arduino due:

Good news, I was able to successfully flash the SAMD21 from pins 66 and 67 on my BBB by rolling back to d52070c like you mentioned. I’ve been touching base with Paul Fertser, who originally wrote the SWD GPIO interface, on the OpenOCD IRC and plan to provide him with a bisect when I get some free time and figure out where things went south. Your help has been invaluable in working through this, so thanks much! Will post an update here when normal functionality is restored, or we get to the bottom of what might be wrong with configuration changes, if the issue lies there.

Good to hear it works. However I don’t think there is a regression: programming failed with the newer version because I made a manipulation error: the target was not powered. That is why it persisted when I reverted. I have edited my reply above. Sorry for the confusion. I think in your setup, something works intermittently and that coincidently it started to work after reverting. Could that be the case?

You were correct in that it was an intermittent issue, haha. Turns out I had a floating Reset pin, which worked some days and didn’t work other days. Learned this when I ported all of the flashing scripts to the Raspi2 and it exhibited some of the same issues, even with its bcm2385gpio driver. Got both working with the master branch now!

In your script, ‘reset halt’ is one command so it should be on one line.

I mean time I bought an nrf51822 dev board as I want to try out the m0 based nrf myself. So far I just tried a blink example. I could flash it by adding following lines to the openocd.cfg:
flash write_image erase main.hex
verify_image main.hex
reset run
shutdown

What about nrst? why isn’t that working in the sysfs gpio? I’m having that problem. The clock and data are working but I need the reset to be able to debug.
In my logic pro output, it looks like the reset signal is in input mode at about 2.4 Vdc. If I manipulate that bit myself, I can reset the target.
Thanks!
Chris

I managed to burn the samd21_sam_ba.bin bootloader withou trouble and it works. I am using a Raspberry Pi2 and reduced adapter speed to 100 kHz to prevent wiering faults.

But I was not able to get back to the M0 bootloader. To me it looks like openocd is interpreting the hex-file not correct. Any hints?
Trying to burn Bootloader_D21_M0_150515.hex I get the following output from openocd:

That is weird indeed. Apparently openocd fills the whole 256KB flash. Is the hex file intact?
You could convert the hex into a bin file and program that. I tend to use the objcopy that comes with arduino to do this:
arm-none-eabi-objcopy -I ihex -O binary Bootloader_D21_M0_150515.hex Bootloader_D21_M0_150515.bin

Thank you for this excellent tutorial. I am currently working with a setup of BBB Wireless and Arduino M0 where I would like to be able to deploy OTA updates to the SAMD21 bootloader / sketches via the BBBW. Insofar, I have been able to achieve the OTA bootloader via openocd as you explained, only with the d52070c commit of the master branch of openocd on the standard debian distro of BBBW (similar issues C. Cross posted for his case – d52070c solved the problem for me as well).

It looks like your boot loader is ‘auto erased’:** Programming Started **
auto erase enabled
The command ‘at91samd bootloader 0’ in my openocd.cfg to burn the bootloader script removes bootloader protection.
Try to put it back in after you program the bootloader, so adapt the bootloader burning script like this:

This protects the first 0x2000 (8192) bytes of the flash.
Can’t try it out soon myself though…

Interesting project. Btw what is the ‘OTA bootloader’? Is it the regular arduino at91samd bootloader? (so the ota mains you go over the air between a pc and the bbb and go wired between the latter and the m0?)

Thanks a lot for the prompt reply and sorry for my delay, I was travelling and could not try out your suggested fix.

Bottom line it did not work with the openocd version I was running with as I was always receiving the following NVM lock error and the entire data at the beginning of the section was erased and thus the bootloader corrupted.

Playing around with the commands I saw that the entire flash partition at the beginning was seen as a huge block in comparison to the size of the bootloader. Splitting it such that one could write the sketch at the right position was leading to erasing the entire memory partition and thus the bootloader itself, hence the initial error.

I knew that the Arduino CC community has its own port of openocd, and look into the diffs of the port (still running on 0.9.0, but that is irrelevant as far as at91samd flasher driver is concerned) wrt the master. There are 2 fundamental commits which fix this problem.

Hence, I just built the openocd arduino branch (https://github.com/arduino/OpenOCD/tree/arduino) on the BBBW and retried with the original cfgs I had and it worked without any problem. Afterwards, I included your changes, since they made sense related to the bootloader protection, and also cleaned the sketch uploader.

That is a really interesting insight. Thanks.
I wonder why this patch was not upstreamed. Maybe the arduino devs did simply have no time to deal with it. Or maybe the solution is not (yet) completely worked out to be genericly applicable, outside the arduino ide…