Search:

PmWiki

pmwiki.org

edit SideBar

Main / Fwarch

Peripheral Interrupts

Love this write-up by Jason over at EE Times, about using interrupts instead of polling for an ADC.

Abstracting the Interrupt

One problem that developers often encounter when writing drivers is that when they develop an interrupt driven solution, they often tightly couple their interrupt to the application code. Optimally the interrupt would reside with the driver code, which is in the driver layer, not in the application code which is at the highest layer in the architecture. Tightly coupling the interrupt to the application code can make it difficult to port the code and even scale it in some cases.

One solution that developers can use to keep the interrupt in the driver layer and still customize it for an application is to use a callback. A callback function is a reference to executable code that is passed as an argument to other code that allows a lower-level software layer to call a function defined in a higher-level layer. A callback function at its simplest is just a function pointer that is passed to another function as a parameter. In most instances, a callback will contain three pieces: The callback function, A callback registration, Callback execution.

The argument is basically in favor of a HW abstraction layer so that the application code can be mostly HW agnostic. You can still put the interrupt handler in the application code, which makes sense because it's the application that contains the intelligence to know what to do when the interrupt triggers.

I/O

If you have code making multiple writes to a serial port, pay attention to the blocking nature of the call opening the port for writing. If you set O_NONBLOCK, you could have a speed mismatch between the capability of the serial port to send out data and the processor's high rate of writing to it. You may need to block so that the port has time to clear out before the next chunk of bytes come in.

ECC

Using ECC requires extra bits to be stored that can validate data. This in turn is best initialized with a process on boot to write the whole of ECC-protected memory so that all the check bits are stored for each memory location. With the Zynq for example, this is done by modifying the Xilinx FSBL.

Switch Debounce

Brian Cuthie responded to the article on debouncing in the last Muse:

Just for the record, people make switch debouncing seem a LOT harder than it is in practice. For Man-Machine Interfaces, the dominant factor is the required response time to a human, which is always >> the bounce time of the switch. The other thing is to treat switch actions are events. But many embedded SW people seem to get that wrong, too, which leads to all kinds of complex logic and spaghetti.

For almost all real applications, the following works just fine:

uint8_t  oldSwitchState = 0;
while(true)  {
               uint8_t  newSwitchState = readSwitch();
if  (newSwitchState != oldSwitchState) {
               if  (newSwitchState) {
               //  do whatever happens when the user presses the switch
               switchDownEvent();
               }
               else  {
               //  do whatever happens when the user releases the switch
               switchUpEvent();
               }
               }
               oldSwitchState  = newSwitchState;
//  this delay has to be longer than the settling time of the switch
               delay(100ms);
               }

Of course, this is a great example of how an RTOS can be helpful in an embedded system. You can put this in a thread of its own (possibly with some LED cadence management) and then the rest of the SW system just gets notified of switch events without needing to know how that happens.


Page last modified on January 08, 2024, at 10:48 PM