7 expert tips for writing embedded software with ChatGPT – Embedded
Advertisement
Advertisement
Embedded.com
Advertisement
The world today is buzzing with the potential that AI models like ChatGPT have to offer. The potential for AI to revolutionize how people work and play is staggering and, to some, a little scary. To give you some perspective, NVIDIA stock year to date (June 2023) has tripled as investors pile in with expectations of nearly unbridled demand for AI hardware. With a new gold rush underway, it might leave embedded developers wondering how they can leverage AI to write better code faster. In this post, we’ll explore seven expert tips for writing embedded software with ChatGPT and LLMs that will help you be more efficient, less error-prone, and less likely to get bit by an AI-generated error.
One of my least favorite activities in embedded software development is debugging. While some developers love the challenge of figuring out why a system is buggy, I always found Jack Ganssles’ statement about debugging elucidating: “If there is a debugging phase, then there must have been a bugging phase”. Embedded developers aren’t supposed to be great debuggers; we are supposed to prevent the bugs from getting into the system in the first place! Embedded systems are complex systems today, and despite using the most modern techniques and processes available, there will be bugs and unexpected behaviors that developers need to work through.
For example, I recently integrated a trace recorder into a client’s custom-built system. I followed the integration instructions perfectly, only to discover that I was getting compilation errors due to multiple definitions. The trace recorder relied on some “linker voodoo” to get the trace library to substitute an RTOS library with recorder-wrapped versions. The voodoo wasn’t working! Looking at the make file quickly, everything looked ok. Great! A day of debugging was about to unfold.
Looking at the compiler outputs, I noticed some macro expansions were not working correctly. Instead of going about my normal debugging process, I decided to ask ChatGPT using the following prompt:
You can see the response from the model below:
Sadly, the response to changes to the makefile to resolve the issue was incorrect; However, the response got my mind thinking. Perhaps the macro expansion definition was not in the right place. From the model’s response, some automatic variables might not work correctly. What happens if I give ChatGPT my makefile and try again? Below is the answer that I received:
Interesting! As I suspected, there might have been an issue with the automatic variable. In addition, the build recipe required a slight adjustment. After trying the suggested changes, I found that the macro expansion did work correctly now! I wasn’t terribly happy with the exact recommendation from ChatGPT, so I refactored the adjustments and made sure it “looked pretty”.
Had I not used ChatGPT to debug this issue, I might have spent several hours poring through the makefile to figure out what was wrong. Instead, I literally spent 10 minutes in total. Speeding up the debug time, being more efficient, and enhancing my prompt skills for working with AI models.
You might have noticed in the previous tip that my first attempt to get a solution to my problem failed. I was not very specific when I first interacted with the ChatGPT model. Yes, I clearly defined my intent to resolve an issue but didn’t initially provide my makefile. Only when I gave the model enough information and was specific and clear on my intent was it able to provide me with an output that solved my problem.
When working with AI models to develop embedded software, it’s critical that you are specific and clear in your intent. Now, in some cases, this could be an issue. If you are writing your company’s secret sauce, you can’t just throw that into ChatGPT, which you need to consider to be public domain. However, there are a lot of generic software problems that you can solve and write your code using an AI model.
The more information you provide to the model, the better the results will be. For example, if you tell the AI model, “I need to connect to a sensor”, that’s not very specific, and the model will not know what you need. Just for fun, I put that into ChatGPT, and here is the response that I got:
That approach can be okay if you want to use an iterative approach, which we will discuss shortly, but it won’t get you to your desired result quickly. However, if you rephrase that request to:
“I need to write a function in C for an embedded system that communicates with a TMP36 temperature sensor using the I2C protocol. The function should initiate a connection to the sensor, read the temperature data every 5 seconds, convert the raw data to Celsius, and return the temperature value. Also, the function should include error handling for scenarios where the sensor fails to respond.”
The ChatGPT model delivers something much closer to what I want on the first try:
Not only do I get some sample code, but I also get a description of the code and the areas I might need to modify based on my end purpose. Not the greatest, but not bad!
I’ve been working with embedded systems for over 20 years, consulting for over half that time. If there is one area, I see teams and developers skimp on every time; it’s error handling. I see so much code where return values are ignored, and errors can run rampant because no one knows they are occurring. Most code is written with the assumption that everything will be okay. I love the optimism, but it’s poorly placed in this case.
You can ask the model to include error handling if you generate code using an AI model like ChatGPT. In fact, I did just that in the last tip when I wrote my more specific prompt. Error handling is a critical piece of writing robust firmware. Instead of ignoring it, ask an AI model to generate the error-handling code. It’ll make your software more robust, and you won’t need to spend much time on it other than a quick code review.
In an earlier tip, I mentioned that you want to be specific to get your desired output. Sometimes, you might not know what you want, or you have an idea but are unsure how to ask for everything you want specifically. When this happens, you can utilize iterative interactions to find the path to the code you want to write.
Iterative interactions with an AI model can start with a general idea or need and then, through multiple interactions with the model, slowly work towards a more granular and well-defined result. For example, in a recent blog post entitled, “An Iterative Approach to USART HAL Design using ChatGPT”, I used this approach to develop a USART HAL. My initial prompts gave the AI model a lot of leniency to generate a draft interface, but subsequent prompts provided incremental improvements until I achieved the desired result. I did not need to fully specify the details upfront, although if I knew exactly what I wanted, I could have tried.
At some point in every developer’s career, you’ll encounter code you don’t understand. Perhaps you’re starting to learn a new language, or some developer thought they’d be clever and wrote something they could only understand. When these cases come along, an AI model can help you verify that your understanding of the code is, in fact, correct.
For example, let’s say you are an entry-level C developer and come across an application that uses function pointers for the first time. A simple application like the following:
If you didn’t know what the code or application was doing, paste it into an application like ChatGPT and ask, “What does the following code do?”
When I put this into ChatGPT, I get the following results:
I could certainly then ask follow-up questions until I was satisfied that I understood the software.
Code reviews are an essential process that every embedded software team should use; However, I’ve often found that teams are not very well disciplined at doing code reviews. Business pressures often cause them to skip reviews and get the code out the door as quickly as possible. An interesting use for AI models is to perform code reviews. Let’s run the code example from the previous tip through ChatGPT again, but this time, we’ll ask it to perform a code review and provide us with recommendations for improvements.
The results that I got can be seen below:
All of these are good catches, even though we have a straightforward program that we started with. I find it interesting that when asking ChatGPT to review the code, it not only reviewed it but also generated a new version of the code with these changes implemented. You can see the updated version below:
Usually, a developer would have to take the recommended changes and go back and rewrite their code. In this case, the updates were automatically generated.
The last expert tip I can leave you with today for writing embedded software with ChatGPT is not to trust it. I know this seems counter-intuitive, given how I’ve just droned on about how helpful ChatGPT can be to write software. It absolutely is, but that doesn’t mean you should blindly trust it. You must carefully monitor the code it generates and perform your code reviews to ensure the code functions as you expect. Use AI models for all these purposes and use the methods we’ve discussed, but make sure you carefully review the output and test it. When you start to trust it too much, that is when you are going to end up with a real problem.
Always verify that the output from the model makes sense. These models are just statistical models that generate the next highly probable token in a sequence. The chances are high that today’s models are not trained on high-reliability code. Don’t get me wrong, you can use these techniques to write excellent embedded software, but ensure you don’t get too comfortable with the output.
The latest advances in large language models have enabled AI to generate code, particularly embedded software. In this post, we’ve explored some expert tips for interacting with AI models to write embedded software. The results you can achieve can be pretty helpful. You can decrease development time and costs, but you must be very careful about how you interact with the models. You don’t want to submit proprietary information or code. You also can’t blindly trust the output from the models.
The advent of LLMs will dramatically affect how we design embedded systems in the future. That future might not be here yet, but it may be much closer than you realize. Jacob Beningo is an embedded software consultant who specializes in real-time, microcontroller-based systems. He actively promotes software best practices through numerous articles, blogs, and webinars on topics from software architecture design, embedded DevOps, and implementation techniques. Jacob has 20 years of experience in the field and holds three degrees including a Masters of Engineering from the University of Michigan.
Related Contents:
Advertisement
You must Sign in or Register to post a comment.
This site uses Akismet to reduce spam. Learn how your comment data is processed.
Advertisement
Advertisement
Advertisement