An embedded firmware developer view of “Vibe Coding” and general use of LLM for development.
Personal Context
Let’s get this out of the way. I’m an embedded firmware developer, and everything in this text only represent my own experience and opinion. My world is microcontrollers, datasheets, C, assembly, not the flashy web dev stuff. Code I write don’t need a fancy display, it need to talk to peripheric using SPI, I2C, and communicate with other system through RS232, RS485, Can, and Ethernet, but more importantly, it need to do so safely for the next 25 years with less available RAM than most landing page… I’m not trying ot say it’s harder than frontend or backend stuff, hell, I could never make a good looking web app. It’s just a diferent set of constraint and requirement. When the AI coding hype train started I was skeptical. I tried using ChatGPT and other models, but was never impressed by the outputs (this was pre GPT-4). But after some time watching Theo, I eventually gave Cursor a try… This was around September 2024, and the time, 2 hot model for dev were Claude 3.5 Sonnet and GPT-4. Now that I’ve spent time with LLM, and used more models, my feelings are… mixed. There is definitely some good stuff, but the limitation are also very real.
What AI can’t help me with
Starting with the rant…
That’s not a Pic register, that’s a RPI register
This is the biggest and most frustrating issue. I ask an Claude to help write a driver for a specific Microchip PIC32 microcontroller, I give it the relevant part of the datasheet, and it confidently spits out code that tries to write to registers that don’t exist on that chip. Maybe by providing it the data in another way, like writing the defines and part of the code it would do better, but…if I give it 75% of the code, it will be faster to write it all myself. When I use GPT-4.1, Claude 4 or Gemini 2.5 Pro, they all hallucinates registers from an Arduino or a Raspberry Pi. Why? Because that’s what it has been trained on. The vast ocean of public code on the internet is dominated by hobbyist platforms. The LLM is just a next token prediction machine, and it predicts that if you’re talking about microcontrollers, you must be using the most popular ones. It has no real understanding of a datasheet. It just knows that some words often follow other words. So, when I say “PIC32 SPI setup,” it mashes together every SPI example it has ever seen, and I end up with a Frankenstein code that is dangerously wrong. It’s like asking a chef for a cookie recipe and getting instructions that include motor oil because they’ve read a lot of car repair manuals.
Code reuse, copy and paste that fill the limited flash
An issue quite easy to see with current LLM models is that they will often copy and paste the same code block multiple times, and on a PC or a Server, that’s not a big deal, but on a microcontroller… It can easily fill the limited flash. One of the system I work with has 128KB of flash, that look like a lot, until you remember that you need space to safely update the firmware, so you split the flash in 2, one for the current firmware, and the other for the previous/next version.
We can’t have a device temporarily out of service because of a failed update, we need to have a valid copy of the firmware in flash at all time. But then you also need space to store the bootloader that receive the update, so the 128KB of flash become a 60K of usable flash. At this point a few copy and paste that look innocent can fill the flash quite fast. An AI just doesn’t get this. It doesn’t understand that the resource constraints from one system to the other are different. It’s trained on massive codebases where duplicating a few lines of code is meaningless. For me, it’s the difference between a successful firmware build and a successful update of a device in the field.
It can’t see the forest for the trees
Ask an AI to add a small feature to a large, existing codebase, and watch the chaos unfold. It has zero architectural awareness. It can’t comprehend the overall structure, the different modules, and how they are supposed to interact. It will happily jam code into the wrong file or introduce global variables because it doesn’t understand the concept of scope or encapsulation. Or it might simply start a side quest and add a new feature that is not related to the requested feature, I’m looking at you Claude 3.7 Sonnet. It’s like hiring a builder to add a window to your house, and they just start smashing a hole in a random wall with a sledgehammer without checking for pipes, wires, or whether it’s a load bearing wall. Or having an intern write new feature in a codebase on it’s first day. The cleanup job oftens takes more time than it would have to just do it right from the start.
What it can actually do
Ok, but what can it actually do for me? Is there any good use case for it? The answer is simply: Yes! AI can be genuinely useful for some tasks, even as a Firmware developer.
Automation Scripts
I’ll admit, AI is pretty good at writing simple scripts. Need a quick Bash script to automate a build process? Or a Python script to munge some data from a text file? It can usually get that done in one shot. These are small, self-contained tasks that don’t require deep architectural knowledge. It’s perfect for the “glue code” that connects different parts of a workflow.
Test tools
This has become a real time-saver for the boring stuff and some simple tasks. It’s great for generating small test applications to validate a piece of hardware or a new protocol. I can ask it to write a quick Python application to talk to a serial port and send specific commands to a device. It won’t be pretty, but it will be functional enough to get the job done and let me test my firmware without waiting for integration testing with other systems.
Data Parsing
I often need to parse data generated by a new device or a new type of record implemented in an existing system. Usually, I implement it in the system and generate some data to send to our data processing team, accompanied by a description of the data. Then… I wait… But with an AI, I can get a quick and dirty parser that will be good enough for simple tests and validation while I wait for the real parser to be implemented in our software suite.
Inline completion
This is where really AI shines. Tools like Cursor’s Tab Complete (and Supermaven) are fantastic for cutting down on boilerplate. Writing the same if (pointer != NULL) check in C or the classic if (err != nil) in Go for the hundredth time in a day is a real waste of time. Having an AI just give a single line or small block of code to fill that in with a single press of the Tab key is a small joy that adds up. It makes coding feel less like typing and more like assembling.
Code Review
It’s like having a robotic junior developer look over your shoulder. Tools like Coderabbit can read your code and point out obvious flaws. It’s surprisingly good at spotting potential null pointer dereferences or memory leaks. It’s also quite good at checking for CVEs It won’t catch subtle logic errors, but it filters out the simple mistakes before the official code review… when there is code review, because let’s be honest, with how fast we often need to ship, I often end up being the one to review my own code.
My Verdict
So, is the AI coming for my job? No. And if it can write all your code, you were probably either working on very small project, or an isolated set of features. But with each new model AI become better at being your personal intern, full of theorical knowledge, but with almost no practical experience.
The idea of a background AI agent silently writing your code is still a fantasy. I’m not sure I want it to become a thing, I’m a developer because I like to write code, if I wanted to tell someone else to write my code, I would just be a project manager. For good results, you need a human in control, guiding the tool. LLM are assistants, not replacements. The real star of the show right now is tab completion. It’s a simple, direct, and incredibly effective way to boost productivity by eliminating repetitive typing.
For embedded systems, my line is clear. If your definition of “embedded” is writing Arduino sketches for a hobby project, you’re probably fine using an AI. But if you’re writing low-level drivers for specific hardware, where a single incorrect register access can cause random crashes or even brick a device, you are far better off with a human who can actually read and understand a datasheet. For that kind of work, AI is best left to handle the boilerplate and the initial code review, before a real engineer gives it the final sign-off.
Leave a Reply