ESP32 Audio Sampling With Interrupts And IRAM

Interrupting while someone is talking is rude for humans, but smart for computers. [Ivan Voras] shows how to use interrupts to service the ESP32 analog to digital converters when sampling sound. Interestingly, he uses the Arduino IDE mixed with native ESP-IDF APIs to get the best performance.

Like most complex interrupt-driven software, [Ivan’s] code uses a two-stage interrupt strategy. When a timer expires, an interrupt occurs. The handler needs to complete quickly so it does nothing but set a flag. Another routine blocks on the flag and then does the actual work required.

Because the interrupt service routine needs to be fast, it has to be in RAM. [Ivan] uses the IRAM_ATTR attribute to make this work and explains what’s going on when you use it.

…the CPU cores can only execute instructions (and access data) from the embedded RAM, not from the flash storage where the program code and data are normally stored. To get around this, a part of the total 520 KiB of RAM is dedicated as IRAM, a 128 KiB cache used to transparently load code from flash storage.The ESP32 uses separate buses for code and data (“Harvard architecture”) so they are very much handled separately, and that extends to memory properties: IRAM is special, and can only be accessed at 32-bit address boundaries.

This is very important because some ESP-IDF calls — including adc1_get_raw — do not use this attribute and will, therefore, crash if they get pushed out to flash memory. At the end, he muses between the benefit of using an OS with the ESP32 or going bare metal.

If you want to know more about the Arduino on ESP32, we covered that. We also dug deeper into the chip a few times.

Does This Demo Remind You Of Mario Kart? It Should!

Here’s a slick-looking VGA demo written in assembly by [Yianni Kostaris]; it’s VGA output from an otherwise stock ATmega2560 at 16MHz with no external chips involved. If you’re getting some Super Mario Kart vibes from how it looks, there’s a good reason for that. The demo implements a form of the Super Nintendo’s Mode 7 graphics, which allowed for a background to be efficiently texture-mapped, rotated, and scaled for a 3D effect. It was used in racing games (such as Super Mario Kart) but also in many others. A video of the demo is embedded below.

[Yianni] posted the original demo a year earlier, but just recently added detailed technical information on how it was all accomplished. The AVR outputs VGA signals directly, resulting in 100×120 resolution with 256 colors, zipping along at 60 fps. The AVR itself is not modified or overclocked in any way — it runs at an entirely normal 16MHz and spends 93% of its time handling interrupts. Despite sharing details for how this is done, [Yianni] hasn’t released any code, but told us this demo is an offshoot from another project that is still in progress. It’s worth staying tuned because it’s clear [Yianni] knows his stuff.

Continue reading “Does This Demo Remind You Of Mario Kart? It Should!”

Embed With Elliot: Debounce Your Noisy Buttons, Part II

If you’ve ever turned a rotary encoder or pushed a cursor button and had it skip a step or two, you’ve suffered directly from button bounce. My old car stereo and my current in-car GPS navigator both have this problem, and it drives me nuts. One button press should be one button press. How hard is that to get right?

In the last session of Embed with Elliot, we looked into exactly how hard it is to get right and concluded that it wasn’t actually all that bad, as long as you’re willing to throw some circuitry at the problem, or accept some sluggishness in software. But engineers cut corners on hardware designs, and parts age and get dirty. Making something as “simple” as a button work with ultra-fast microcontrollers ends up being non-trivial.

And unsurprisingly, for a problem this ubiquitous, there are a myriad of solutions. Some are good, some are bad, and others just have trade-offs. In this installment, we’re going to look at something special: a debouncer that uses minimal resources and is reasonably straightforward in its operation, yet which can debounce along with the best of ’em.

In short, I’ll introduce you to what I think is The Ultimate Debouncer(tm)! And if you don’t agree by the end of this article, I’ll give you your money back.

Continue reading “Embed With Elliot: Debounce Your Noisy Buttons, Part II”

Code Craft: Subtle Interrupt Problems Stack Up

[Elliot Williams’] column, Embed with Elliot, just did a great series on interrupts. It came in three parts, illustrating the Good, the Bad, and the Ugly of using interrupts on embedded systems. More than a few memories floated by while reading it. Some pretty painful because debugging interrupt problems can be a nightmare.

One of the things I’ve learned to watch out for over the years is the subtlety of stack based languages, like C/C++, which can ensnare the unwary. This problem has to do with the corruption of arrays of values on a stack during interrupt handling. The fix for this problem points up another one often used by black hats to gain access to systems.

Continue reading “Code Craft: Subtle Interrupt Problems Stack Up”

Embed With Elliot: Interrupts, The Ugly

Welcome to part three of “Interrupts: The Good, the Bad, and the Ugly”. We’ve already professed our love for interrupts, showing how they are useful for solving multiple common microcontroller tasks with aplomb. That was surely Good. And then we dipped into some of the scheduling and priority problems that can crop up, especially if your interrupt service routines (ISRs) run for too long, or do more than they should. That was Bad, but we can combat those problems by writing lightweight ISRs.

This installment, for better or worse, uncovers our least favorite side effect of running interrupts on a small microcontroller, and that is that your assumptions about what your code is doing can be wrong, and sometimes with disastrous consequences. It’s gonna get Ugly

TL;DR: Once you’ve started changing variables from inside interrupts, you can no longer count on their values staying constant — you never know when the interrupt is going to strike! Murphy’s law says that it will hit at the worst times. The solution is to temporarily turn off interrupts for critical blocks of code, so that your own ISRs can’t pull the rug out from under your feet. (Sounds easy, but read on!)
Continue reading “Embed With Elliot: Interrupts, The Ugly”

Embed With Elliot: Interrupts, The Bad

We love interrupts in our microcontroller projects. If you aren’t already convinced, go read the first installment in this series where we covered the best aspects of interrupts.

But everything is not sunshine and daffodils. Interrupts take place outside of the normal program flow, and indeed preempt it. The microcontroller will put down whatever code it’s running and go off to run your ISR every time the triggering event happens. That power is great when you need it, but recall with Spider-Man’s mantra: With great power comes great responsibility. It’s your responsibility to design for the implicit high priority of ISRs, and to make sure that your main code can still get its work done in between interrupt calls.

Put another way, adding interrupts in your microcontroller code introduces issues of scheduling and prioritization that you didn’t have to deal with before. Let’s have a look at that aspect now, and we’ll put off the truly gruesome side-effects of using interrupts until next time.

Continue reading “Embed With Elliot: Interrupts, The Bad”

Embed With Elliot: Interrupts, The Good…

What’s the biggest difference between writing code for your big computer and a microcontroller? OK, the memory and limited resources, sure. But we were thinking more about the need to directly interface with hardware. And for that purpose, one of the most useful, and naturally also dangerous, tools in your embedded toolchest is the interrupt.

Interrupts do exactly what it sounds like they do — they interrupt the normal flow of your program’s operation when something happens — and run another chunk of code (an interrupt service routine, or ISR) instead. When the ISR is done, the microcontroller picks up exactly where it left off in your main flow.

Say you’ve tied your microcontroller to an accelerometer, and that accelerometer has a “data ready” pin that is set high when it has a new sample ready to read. You can wire that pin to an input on the microcontroller that’s interrupt-capable, write an ISR to handle the accelerometer data, and configure the microcontroller’s interrupt system to run that code when the accelerometer has new data ready. And from then on everything accelerometer-related happens automagically! (In theory.)

This is the first part of a three-part series: Interrupts, the Good, the Bad, and the Ugly. In this column, we’ll focus on how interrupts work and how to get the most out of them: The Good. The second column will deal with the hazards of heavyweight interrupt routines, priority mismatches, and main loop starvation: the Bad side of interrupts. Finally, we’ll cover some of the downright tricky bugs that can crop up when using interrupts, mainly due to a failure of atomicity, that can result in logical failures and corrupted data; that’s certainly Ugly.

Continue reading “Embed With Elliot: Interrupts, The Good…”