Adventures in tinkering, or how I jailbroke my BLE Sense

Last updated: 2021-03-13

Would you like to program your Arduino 33 BLE Sense with something other than Arduino?

What is the BLE Sense?

The BLE Sense is without a doubt a great little board. It has a fast yet power-efficient Cortex-M4 class microcontroller, lots of memory, Bluetooth Low Energy connectivity, and a whole bunch of sensors:

It is pretty much the board when it comes to machine learning on embedded devices: it’s featured in the TinyML book, the TinyML course by HarvardX and the Embedded Machine Learning course by Coursera. It’s also officially supported by EdgeImpulse, which will allow you to start experimenting with TinyML right away.

In general, Arduino (as in programming language, the C/C++ dialect) is pretty great, especially if you want to focus on the project itself and not the bare metal details. Sometimes it’s a little opaque, though, and abstracts a whole bunch of things away from the user.

So what if you want to go beyond the Arduino?

In my case, I wanted to try programming it with Rust*. I already had some experience with the nRF52840 on the Adafruit’s ItsyBitsy board with the same MCU, but then the BLE Sense has all those nice sensors, too, so I wanted to give it a try.

* you could also use C/C++ with or without Nordic SDK, or (something I haven’t tried myself) TinyGo or CircuitPython

The problem is, BLE Sense has its own specific bootloader. It works well with Arduino IDE, but that’s pretty much it. In order to do anything else you need to replace it with some other bootloader that will allow you to flash the board with the firmware of your choice, e.g. written in Rust. Adafruit to the rescue!

Making the bootloader

What you need to do is clone the repository with Adafruit nRF52 Bootloader, and then build it for the Nano 33 BLE board like so:

git clone https://github.com/adafruit/Adafruit_nRF52_Bootloader.git
cd Adafruit_nRF52_Bootloader
git submodule update --init
make BOARD=arduino_nano_33_ble all

This will take a moment, and after it’s done, you’ll see that there’s now a folder _build/build-arduino_nano_33_ble with multiple files. The one you need is this one:
arduino_nano_33_ble_bootloader-0.4.1_s140_6.1.1.hex (it also contains the Nordic SoftDevice S140 v.6.1.1).

But how can we flash the board with it?

Exposing the SWD interface

Here’s where you need to do a little modification to the board itself. It’s not very difficult, but requires some basic soldering skills, and some patience.
Arduino designers didn’t include any pins for the Serial Wire Debug (SWD) interface, but luckily left the soldering pads exposed at the bottom of the board:

SWD soldering pads

You can also see it on the pinout.

In hindsight I can tell that only the two pins (SWDIO and SWDCLK) seem necessary for this operation, I didn’t connect the RESET pin. It also makes a lot of sense to somehow secure the attached wires to the board, as they may easily detach otherwise.

Flashing the bootloader

Once we have the SWD interface available, all we need is to put this .hex file on the board. It can be done with Segger J-Link, but I didn’t have one handy, so I used the Black Magic Probe instead. To be specific, I used the cheap “blue pill” STM32F103 board with the BMP firmware flashed, as explained here and here. It’s limited compared to the original, as it only has SWD interface and no JTAG, but will do just fine here.

All you need to do is connect the new SWDIO and SWCLK of the BLE Sense board to their relative BMP counterparts, and also connect +3V3 and GND from the BMP to the right pins of the BLE Sense (check pinout for the correct pins). After that you run GDB on your computer, and run the following commands:

gdb
target extended-remote /dev/ttyACM0
monitor swdp_scan
attach 1 (Nordic nRF52 M4) 
load arduino_nano_33_ble_bootloader-0.4.0-2-g4ba802d_s140_6.1.1.hex
kill

It does the following:

Let there be blinkenlight!

Now after you disconnect the BMP and attach the BLE Sense to the computer, you’ll see that it shows up as NANO33BOOT flash drive. To test whether everything went smoothly, you can flash it with this simple blink example I made with Rust (GitHub repository here).
All you need to do is install Adafruit’s version of nRFutil, put the board into bootloader mode (you’ll see a drive named NANO33BOOT appear) and then execute the following instruction in the folder where you stored the blinky.zip:

adafruit-nrfutil dfu serial --package blinky.zip -p /dev/ttyACM0 -b 115200

blinkenlightAnd here’s a BLE Sense (with SWD wires still attached) happily blinking the blue LED with the Rust code. I really wish I had secured the wires better, they detached shortly after flashing the bootloader, which is a bummer as I can’t use BMP or J-Link to debug the board (but the flashing over the bootloader works great).

To be continued! In the next post I will explain more about the Rust code, and how to get the sensors to work.

Stay tuned!


 

Categories:   rust  embedded  arduino  tinyml 

Comments

comments powered by Disqus