A week in the BLE desert

Long time no post, because, well, I didn’t feel like bragging about my struggle with the Nordic chip.

But here we are. Let’s make the most of it! The mission (I accepted): building the communication between the STM32 and the user’s client (a bluetooth low energy device).

Quick reminder: we had decided to use a SPI bus to connect our STM32 and the Nordic nRF51822 chip. But since we only added one chip select wire, we realized our schematic didn’t fit our purpose: both chips should be able to act as master and could want to initiate a transaction. Hence the decision to go back to the UART (we’d planned this, but not thoroughly enough: the RTS and CTS pins are not mapped, so we’ll lose the hardware flow control).

Starting from there, and discovering with enthusiasm that the last Nordic SDK 8.0.0, freshly released, was compatible with our evaluation board (PCA10001, embedding the same chip than us), I developed a custom 8.0 BLE service (with the numerous Nordic examples as a base).

I was able to flash it on both the evaluation board and the Expelliarose PCB, and the magic happened: the chip was advertising like a grown-up, able to connect, bind, send and receive characteristics. To go forward, I had to implement the UART protocol, again starting from the Nordic examples. Suddenly, the clouds darkened. The result was working well on the evaluation board, but our wand did not agree, deciding to hard-fault instead of sending data. How petty. And there it was: the famous and beloved pin 28, configured as the UART’s RX, attracted the wrath of our wand. The pin matrix of the STM32 being quite strict, we had no way to use one of the two orphan SPI wires instead.

That’s when the light faded in (or was it the cruel burn of the lightning?): Alexis and Sam made me realize that the revision of our chip was not officially supported by the SDK 8.0.0. Oh, yes, the evaluation board was compatible. But the PCA10001, not the PCA10001. That’s right, Nordic releases different, non-compatible, versions of the same chip, with no other way to differentiate them than watch them very closely with narrowed eyes. I guess that’s how they do it in Trondheim the industry, and I guess that’s how the rookies fall. I had no way to make sure this was causing the issue, but after countless hours of gdb (and some time spent worrying about this intriguingly warm chip; oh, wait, that was just an old JTAG connector reverse-soldered for a poorly made Chinese probe causing a short circuit: bad luck does choose its victims) , I decided to port my code to the SDK 6.1.0 (the most recent one supported by the QFAAG).

The story does not end here, unfortunately for the already-bored reader. But I have to make it up for quite a few silent days! The port was far from being painless, as I did not want to start from scratch (the SDK 6 examples are as rare as concise compared to the 8, and I had done most of the work − so I believed), but I could not start from the SDK 8 code either (the API said no, no, no). A few subtleties were troublesome to notice, added to the fact that the SoftDevice stack is proprietary and occasionally raises very laconic exceptions. I spent quite some time wandering around mysterious hangs, that were actually linked to the not-yet-ready clock, messy initializations, and 1-byte-too-long-strings because of the 128 bits vendor-specific BLE UUIDs (yup, Expelliarose’s a vendor. and we’re specific.).

Then, I made the UART work (even with the pin 28, take that SDK 8). And the BLE service. Charming, might you say. But it couldn’t be that easy: the two of them did not seem to get along well. I thought about cycling: something like 55ms with the BLE, 55ms with the UART, but that seemed slightly inefficient. So I realized I had way too many hair and decided to lose half.
Then I understood that as soon as the advertising started with sd_ble_gap_adv_start, we entered a new limbo of debugging in which we could break but not resume, as the interruption would messes up with the internal timers of the SoftDevice. So instead of checking that everything worked step-by-step, I simply had to let the firmware lives its life. D’oh.

A few details later (because the two clocks are not exactly in sync and because the nRF’s UART implements almost no integrity mechanism (but the parity bit)), the two best foes managed to talk. Yes, like “hey mate, someone just paired with me”. It might seem a bit tedious from an external perspective, and to be honest I didn’t think I’d rejoice in implementing a serial driver, but that was a relief (that has been paid for dearly!).

I’ve spared you the “our BLE dongles don’t seem to work on Arch and Fedora” complaint, that will probably require some Android developments, and I’ll let the details of “what we’ll do with this” to another day. And that way, I can put an end to this novel with a good news, which is great since we all love happy endings (but Georges R. R. Martin). I’ll probably sing a song tonight (hopefully, it shall bode well for the rest of the project)!

3 comments to A week in the BLE desert

  • Alexis Polti

    “I had way too many hair and decided to lose half” : pix or didn’t happen 🙂

  • +1
    A bit more seriously, you’d probably get extra points if you extract a kind of quick and simple “debugging tutorial” from your memories (with gdb instructions, problems and solutions).
    It’ll help your classmates but you’ll love it too when you’ll have forgotten most of it in the future !

  • lerela

    Hm yes I should do this! But it’ll probably have to wait for our prototype to work, that’s much more important than the points 😉