Pre-Ramble 2: Turbo

The goal of this post is to install the tool chain for cross compiling for ARM, install OpenOCD 0.9.0 w/ buspirate SWD driver patch on Ubuntu 14.04 LTS, compile the blinky LED demo, and write it to the badge's flash memory and have it execute.

I'll keep this pre-ramble brief. OpenOCD's driver for the buspirate doesn't do Serial Wire Debug (SWD) out of the box, but OpenOCD does support SWD. SWD provides much of the functionality of a JTAG TAP interface with only the need for 2 wires (I2C), the equivalent of TCK and TDI/TDO on each pin. I'm new to SWD but I've had my fair share of battles with OpenOCD, remote GDB and other painstaking endevours to find bugs. Luckily for us this won't be so hard.

There is an unmerged pull request which adds SWD support to the bus pirate.

If you don't mind tainting your system you can skip all the package management and go straight for the OpenOCD offical git repo and build/install it dirty.

I also suggest updating your buspirate to the latest bootloader (4.4) and firmware (6.1) before starting.

I skip over much of the repo cloning and package building here because I've covered it in this post

Installing the toolchain and other prerequisites

I'm going to assume we are running on a fresh ubuntu install, so lets start with the prerequesites.

$ sudo apt-get install build-essential automake gcc-arm-none-eabi git \
                       libhidapi-dev libjim-dev pkg-config dh-autoreconf \
                       libtool autoconf autogen
$ sudo apt-get build-dep openocd

Cloning the debian OpenOCD unstable package source

$ git clone git://anonscm.debian.org/crosstoolchain/openocd.git
Cloning into 'openocd'...
remote: Counting objects: 51303, done.
remote: Compressing objects: 100% (9403/9403), done.
remote: Total 51303 (delta 42014), reused 50961 (delta 41742)
Receiving objects: 100% (51303/51303), 15.27 MiB | 1.27 MiB/s, done.
Resolving deltas: 100% (42014/42014), done.
Checking connectivity... done.
cd openocd
~/openocd$ git checkout debian/0.9.0-1
~/openocd$ # start magic to sync package to our ubuntu env
~/openocd$ autoreconf --force --install
~/openocd$ ./configure
~/openocd$ make maintainer-clean
~/openocd$ autoreconf --install
~/openocd$ # end magic
~/openocd$ sed -i '/--disable-internal-jimtcl/d' debian/rules
~/openocd$ your-editor-here debian/changelog

Here is my changelog

openocd (0.9.0-2~drkns) unstable; urgency=low

  * Applied buspirate driver patch to support SWD
  * Enabled internal jimtcl for ubuntu compatibility

 -- Tim Noise <[email protected]>  Sun, 14 Sep 2015 22:40:00 +1000

Patching the Bus Pirate driver

We're simply going to overwrite the existing driver with this unmerged version, with the devices I have tested there have been no problems.

$ cd ~/openocd/src/jtag/drivers
~/openocd/src/jtag/drivers$ curl -o buspirate.c 'http://openocd.zylin.com/gitweb?p=openocd.git;a=blob_plain;f=src/jtag/drivers/buspirate.c;h=ad33d94aff1644768cbdb2c344bd384ab8be3f40;hb=8f39e8f6fd25f5b13cccccf9af5fd885b365e9f4'

Compiling OpenOCD packages and Installing them

~/openocd$ dpkg-buildpackage -us -uc -b

Beverage break

~/openocd$ cd
$ ls -l
total 2248
drwxrwxr-x 11 ubuntu ubuntu    4096 Nov 16 00:55 openocd
-rw-rw-r--  1 ubuntu ubuntu     812 Nov 16 00:56 openocd_0.9.0-2~drkns_amd64.changes
-rw-r--r--  1 ubuntu ubuntu 2290880 Nov 16 00:56 openocd_0.9.0-2~drkns_amd64.deb
$ sudo dpkg -i openocd*deb
Selecting previously unselected package openocd.
(Reading database ... 75508 files and directories currently installed.)
Preparing to unpack openocd_0.9.0-2~drkns_amd64.deb ...
Unpacking openocd (0.9.0-2~drkns) ...
Setting up openocd (0.9.0-2~drkns) ...
Processing triggers for man-db (2.6.7.1-1ubuntu1) ...
Processing triggers for install-info (5.2.0.dfsg.1-2) ...
$ openocd -v
Open On-Chip Debugger 0.9.0 (2015-11-16-00:56)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html

Well now the hard work is done!

Cloning the badge Demos

$ git clone https://github.com/peterfillmore/RuxconBadge2015.git
Cloning into 'RuxconBadge2015'...
remote: Counting objects: 467, done.
remote: Total 467 (delta 0), reused 0 (delta 0), pack-reused 467
Receiving objects: 100% (467/467), 25.17 MiB | 2.22 MiB/s, done.
Resolving deltas: 100% (211/211), done.
Checking connectivity... done.

Configuring OpenOCD and the demo Makefile

We're going to work with the blinky demo, this is just the LEDs blinking in a sequence based on CPU cycles.

cd ~/RuxconBadge2015/firmware/blinky

We do a reallyclean to make sure our whole toolchain is working and not just enough to compile main.c

~/RuxconBadge2015/firmware/blinky$ make reallyclean

Now we can just run make to cross compile the application

$ make

Create a new file in extra/ called buspirate.cfg

interface buspirate

# you need to specify port on which BP lives
buspirate_port /dev/ttyUSB0
buspirate_speed normal
buspirate_vreg 0
buspirate_mode open-drain
buspirate_pullup 1

reset_config srst_only
transport select swd

source [find target/stm32f0x.cfg]

init

proc stm_flash {IMGFILE} {
   reset halt
   sleep 100
   wait_halt 2
   flash write_image erase $IMGFILE 0x08000000
   sleep 100
   verify_image $IMGFILE 0x08000000
   sleep 100
   reset run
}

proc stm_erase {} {
    reset halt
    sleep 100
    stm32f1x mass_erase 0
    sleep 100
}

Next we need to remove some config from the Makefile and add our new buspirate.cfg

~/RuxconBadge2015/firmware/blinky$ sed -i 's/ -f \$(OPENOCD_BOARD_DIR)\/stm32f030k6.cfg//g' Makefile
~/RuxconBadge2015/firmware/blinky$ sed -i 's/stm32f0-openocd/buspirate/g' Makefile

Connecting to the Bus Pirate

Adding yourself to the dialout group

By default, the bus pirate will be assigned to /dev/ttyUSB0, there are some common solutions to being able to use it, including adding a udev rule to add a static device name when the device is hotplugged. The quickest way to get this done however is just add yourself to the dialout group, if you have made it this far I assume you have root anyway.

$ dmesg
usb 2-2.1: new full-speed USB device number 5 using uhci_hcd
usb 2-2.1: New USB device found, idVendor=0403, idProduct=6001
usb 2-2.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 2-2.1: Product: FT232R USB UART
usb 2-2.1: Manufacturer: FTDI
usb 2-2.1: SerialNumber:
ftdi_sio 2-2.1:1.0: FTDI USB Serial Device converter detected
usb 2-2.1: Detected FT232RL
usb 2-2.1: FTDI USB Serial Device converter now attached to ttyUSB0
$ ls -la /dev/ttyUSB0
crw-rw-r-- 1 root dialout 188, 0 Nov 16 01:20 /dev/ttyUSB0
$ id
uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lpadmin),111(sambashare)
$ sudo usermod -a -G dialout `whoami`
$ logout
login as: ubuntu
$ id
uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),20(dialout),24(cdrom),27(sudo),30(dip),46(plugdev),110(lpadmin),111(sambashare)

Testing

Now to test we can open /dev/ttyUSB0

$ screen /dev/ttyUSB0 115200 8N1
HiZ>i
Bus Pirate v3.a
Firmware v6.1 r1676  Bootloader v4.4
DEVID:0x0447 REVID:0x3046 ()
http://dangerousprototypes.com
HiZ>

Exit screen with ^a:quit

Make sure you do not leave it attached! The device must be free'd up to use it again

Almost home now! Now to connect the hardware!

Connecting the Bus Pirate to the SWD interface

The image below has the pinouts color coded - the P6 header is labeled on the bottom of the PCB.

Writing the badge demos to the badge

Using the Makefile

~/RuxconBadge2015/firmware/blinky$ make
~/RuxconBadge2015/firmware/blinky$ make program
openocd -s /usr/share/openocd/scripts/ -f extra/buspirate.cfg -c "stm_flash `pwd`/main.bin" -c shutdown
Open On-Chip Debugger 0.9.0 (2015-11-16-00:56)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : Buspirate SWD mode enabled
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
none separate
cortex_m reset_config sysresetreq
Info : Buspirate two-wire mode configured correctly
Info : Buspirate SWD Interface ready!
Info : This adapter doesn't support configurable speed
Info : SWD IDCODE 0x0bb11477
Info : stm32f0x.cpu: hardware has 4 breakpoints, 2 watchpoints
stm_erase
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0xc1000000 pc: 0x080002dc msp: 0x20001000
auto erase enabled
Info : device id = 0x10006444
Info : flash size = 32kbytes
verified 916 bytes in 0.733821s (1.219 KiB/s)
shutdown command invoked
Info : Shutting down buspirate.

DIY with OpenOCD

Remove the init line from buspirate.cfg first

~/RuxconBadge2015/firmware/blinky$ openocd -f extra/buspirate.cfg

Then in another terminal

$ telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> reset halt
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0xc1000000 pc: 0x080002dc msp: 0x20001000
> stm32f1x mass_erase 0
stm32x mass erase complete
> flash write_image erase /home/ubuntu/RuxconBadge2015/firmware/blinky/main.bin 0x08000000
auto erase enabled
wrote 1024 bytes from file /home/ubuntu/RuxconBadge2015/firmware/blinky/main.bin in 2.139482s (0.467 KiB/s)
> verify_image /home/ubuntu/RuxconBadge2015/firmware/blinky/main.bin 0x08000000
verified 916 bytes in 0.541034s (1.653 KiB/s)
> reset run

Conclusion

After your efforts you will get something like this

While this seems like a stack of effort to get some flashing LEDs this is a very simple example. Some of the other examples include wifi connectivity, oled screens and other SPI/I2C interaction.

Should time permit, I have an example using the UART interface in conjunction with the onboard buttons I would like to post, maybe tomorrrow :)