Building a Device Driver from Scratch — with an AI Wingman

Building a Device Driver from Scratch — with an AI Wingman

Jul 23, 2025

by

Justin Noel

Over the past few weeks, I’ve been sharing this story with coworkers and friends, and I figured it was time to share it here too. It’s a tale about a programmer (me) teaming up with an AI chatbot to solve a surprisingly tricky low-level problem. The assistant wasn’t always right — but when it was, it really moved the needle.

A Simple Task That Wasn’t

The task sounded simple on paper: write a device driver to monitor the core temperature on an i.MX 8M Plus using QNX 7.1. Unlike Linux, QNX doesn’t come with a ready-made driver for the Thermal Management Unit (TMU) on this SoC, at least not from Blackberry’s BSP. 

Linux has spoiled me with device trees and a wealth of stock drivers. I haven’t had to write, or even touch, a real device driver in years. So, it was back to basics. I rolled up my sleeves, opened the 7,000-page NXP datasheet for the i.MX 8M Plus, and flipped to page 680 — where the TMU section lives. (To see the datasheet for yourself you can use this link and then click on "Reference Manual" -- but you must be logged into NXP for access.)

Good news! The TMU is simply a collection of a dozen or so registers accessed via mapped RAM addresses. Ignoring thresholds, interrupts and calibration I should be able to get something reporting a temperature by setting a few bits on the probe select register then bits in the enable register and finally reading sections of the immediate temperature register. I used QNX’s mmap_device_memory() function and set the bits as I saw appropriate, compiled and then ran the app.

Bad news: it didn’t work. 

The bits were set, but the temperature register? Always zero.

After some quality time staring at the datasheet and triple-checking my base address offsets, I had to admit — either the TMU was broken or I was missing something subtle (and probably obvious in hindsight).

When Nothing Works, Ask a Bot

Back in the day, I’d rope in a coworker to squint at the code and trade theories. These days, I can ask the AI!

For this particular task I chose Anthropic Claude Sonnet 3.5 – mostly because I had luck with it in the past and I have a paid subscription.

I asked Claude to help me “write an application for QNX 7.1 in C that would enable and read the values of the temperature probes on an imx8mp”. The first thing I noticed was that it tried to make a full device driver with functions to set most of the registers, deal with calibration, etc. I then asked Claude for the least amount of code to enable the TMU, select the probes and read the temperatures. 

After correcting the offset to the read register and reminding Claude that I am working on QNX and to replace mmap /dev/null with mmap_device_memory what came out looked similar to what I had, compiled and still did not work in the exact same way.

Playing Twenty Questions with an AI

I told Claude it did not work, and sent back the console output of the application that simply wrote the temperature in a loop with an usleep interval. Claude conjectured it might have something to do with sampling rates or calibration (unlikely) and modified the to code to set some bits in those registers and added some code to dump the values of those and some other registers. 

The code still didn’t work, so I kept feeding Claude the latest compile errors and console output. Round and round we went. After a few more stabs in the dark, Claude suggested enabling the TMU’s clock. Before the code even finished generating, it hit me: I’d completely forgotten about the clock! Classic “dawn breaks over Marblehead” moment.

The code Claude added would not have compiled as I know clocks can’t be set from userspace, but I opened up the startup code for our QNX kernel and lo and behold there was no line to enable the clock for the TMU in imx_init_clocks.c. Claude didn’t get the name of the clock correct, but reading over the Clock Control Manager (CCM) section of the datasheet I found the TSENSOR clock around page 285. Once the clock was enabled my original code and Claude’s generated code started reporting temperatures. 

When the Pieces Finally Click

Looking back, I probably would have figured it out eventually — but having Claude there was like pair programming with a very fast, slightly overconfident junior dev who just never gets tired. It didn’t hand me the answer directly, but it nudged me toward it. 

That back-and-forth loop, the fast feedback, the slightly off guesses — it kept my brain engaged and ultimately helped me break through. The real win wasn’t perfect code generation, but the way the AI kept me moving and thinking. 

Next time I’m up against a wall with obscure hardware and a 7,000-page datasheet, I’ll definitely be looping in my AI assistant a lot sooner.

About the author

Justin Noel

Justin is a Sr. Software Architect at Integrated Computer Solutions (ICS), with over 20 years of experience in developing and maintaining complex software systems. His strong leadership and technical skills enable him to successfully guide teams and solve challenging engineering problems. As a technical trainer, he has taught Qt/QML, UX/UI and embedded courses as well as presented at numerous international conferences. Justin earned his B.S. in Computer Technology from Northeastern University.

©2025 Boston AI® • A Division of ICS • Privacy PolicyCookie Policy

230 Second Avenue • Waltham, MA 02451 • Phone: 781.552.3715

©2025 Boston AI® • A Division of ICS
Privacy PolicyCookie Policy

230 Second Avenue • Waltham, MA 02451 • Phone: 781.552.3715