Skip to main content
Blog

Rapid prototyping using PMOD and Zephyr

By August 8, 2023No Comments

Written by Benjamin Lindqvist, Firmware hacker at Elektronikutvecklingsbyrån

Introduction

In this blog post I will briefly describe the Pmod specification and how we combine it with Zephyr to achieve production-grade rapid prototyping. We also present our (designed with Zephyr RTOS in mind) open hardware devkit `kite_nrf52840`.

The prototyping problem

I think almost everyone would agree that prototyping is a crucial aspect of embedded development. Letting an Adafruit breakout board dangle around an off-the-shelf devkit with jumper wires in between is an exercise most developers are highly familiar with. And there’s nothing wrong with this approach – it’s the fastest (and funnest) way to familiarize yourself with new hardware. But the limitations of this approach becomes evident rather quickly too.

A while ago, I was working on a project where the custom hardware got massively delayed, which left us no option but to do our firmware hacking on pieced together breakouts. The problem was that this particular product had two I2C sensors, an eight-pin SPI peripheral and three external antennas. On top of that we also needed to hook up the power, SWD and UART pins.

My desk ended up looking like someone had spilled a bowl of spaghetti tricolore on it, but what can you do? If work on the firmware doesn’t start until the first hardware batch arrives, you’re doing it wrong. On the other hand, production grade prototyping is an amazing advantage, if you can achieve it without sacrificing too much speed and agility.

The solution is not standardization alone, but standardization with some community traction around it. There are plenty of peripheral pinout standards out there, but they always seem to either be too simple, too complicated, too over-engineered, too specific, require too much or just have an unshakable whiff of vendor lock-in.

But we’ve found one we think might have a chance – Pmod. The Pmod (“Peripheral MODule”) specification was released by Digilent in 2011 and is still being maintained. The last revision was released in October 2020.

The main thing Pmod has going for it is that it’s about as far from being over-engineered as you can get, being based on simple 2.54 mm pin headers and fully fleshed out by a twelve page PDF. Despite this, it still remains fairly comprehensive, well thought out and, perhaps most importantly, easy to diverge from when the need arises.

You can check the link to the specification above for more details, but the gist of it is this: A Pmod connector is either a 1×6 or a 2×6 2.54 mm pitch pin header with a standardized pinout depending on the peripheral type you want to use (SPI, I2C, UART, etc). Generally, you’ll want to mount right-angled headers on both the host side and the peripheral side so that the peripheral board connects “edge-to-edge” without the need for any wiring.

As you can imagine, this instantly makes the prototype feel more industrialized, as jamming this into a 3D-printed enclosure and sending it off to a customer for testing is entirely unproblematic, which is more than you could say about the spaghetti tricolore contraption I mentioned earlier.

The Diligent Store has a pretty good selection of breakouts including sensors, CAN and RS485 transceivers, RF modules, OLED displays, DACs and so on but obviously, every peripheral won’t have an off-the-shelf Pmod breakout but thanks to the simplicity of the standard, even a non-hardware guy like myself can easily whip up a board using KiCad and send it off for manufacturing in a matter of hours.

While Pmod breakouts will work completely fine using any old DK, the real power of Pmod isn’t harnessed until you have a host board actually built to utilize them. Sadly, there doesn’t exist many good DK options in the ecosystem yet. There’s a handful of upstream boards with a single Pmod connector, but this did not really satisfy our needs. So we did what makers do best – we maked!

The board in the picture above is the `kite_nrf52840`, the first board of what we call the “Kite” series (partly a nod to our love for Zephyr, partly a reference to our kite-flyer. Don’t worry, we’re not trying to sell you anything – all you need to get it manufactured is publicly availably including schematic, BOM and gerbers. If anything is unclear, just open an issue and we’ll make sure to help you out.

Pending getting merged upstream, you can find a West module containing the Zephyr board files here. Thanks to a recently merged PR, combining Pmod and Zephyr is extremely smooth, as we will show below.

Here’s another example, this time of the work in progress `kite_nrf9160`, connected to two Pmod boards of our own making: – a surface mounted SD card board with SPI comms, – an UART/USB converter board as well as a (possibly accidentally) Pmod compatible NFC tag from NXP.

Generating and using Pmod bindings in Zephyr

Note: if you haven’t interacted closely with the pinctrl system, see the excellent introduction here.

Clearly you could make a Pmod-focused DK for any SoC but when you target Nordic things get even nicer due to the extremely flexible pin configuration – basically any pin can be muxed to any functionality, which means generating pinctrl nodes for your board essentially boils down to enumerating combinations, which can be done programmatically. For this board, we made a yaml file describing the pin mappings, after which this script was used to generate the dtsi files.

Two dtsi files will plop out on the other side: one containing the GPIO nexus mappings and one containing the pinctrl nodes for UART, SPI, etc.

These are included by your DTS (or DTS overlay) file. For example, a LIS2DH breakout board might be integrated like this:

This is quite a lot quicker and less error-prone than overlaying existing pinctrl nodes, digging around in the DK board files, triple-checking pin numbers on the silk, making sure you avoid conflicts while trying to find conveniently placed GND and VDD pins.

Rapid prototyping with Zephyr

One of the nicest things about Zephyr is the separation between hardware description and code. It’s easy to argue that this property is what truly enables agile embedded development. Thanks to Zephyr, all we really need to start hacking on a prototype is a rough idea of what the customer wants to achieve – requirements tend to crystallize a lot faster when they get something in their hands that they can test and play around with. If suitable breakouts for the preliminary peripherals does not exist, we make sure to design them ASAP so that they can be evaluated quickly.

During iteration, the peripherals might change – hell, even the SoC might change – but this usually won’t affect a well-written Zephyr application all that much. By designing the hardware in parallel, the first board round will usually be ready to order after a few iterations and we can either construct custom board files for it or, if the project is simple enough, stick to adding dts overlays to the Kite board.

Many simple but costly errors (MOSI/MISO flips, missing capacitors, mismatched voltage levels, etc) are avoided because they have already been turned into cheap errors in the Pmod trial round. This means bringing up Zephyr on the final board is usually pretty painless and, surprisingly often, simply a `west flash`away.

Conclusion

It’s pretty clear that no other RTOS can match what Zephyr has to offer when it comes to modularity and portability (unless you count Linux as a RTOS that is). To be fair, the Pmod standard offers way less, but that can actually be the very reason it could gain traction – the less complex the standard is, the harder it is to find stuff to bicker about.

If you wanna join the Pmod hype train, or just chat about how awesome Zephyr is, feel free to reach out to “luegofuego” on the Zephyr discord, drop us an email or visit our homepage.

To learn more about Zephyr, subscribe to the Zephyr quarterly newsletter or connect with us on @ZephyrIoTZephyr Project LinkedIn or the Zephyr Discord Channel to talk with community and TSC members.

Zephyr Project