Friday, June 18, 2010

Common Interrupt Pitfalls

I just want to share some interesting facts that I found in SDCC Compiler User Guide. From my experience, I think these facts are very important to keep in mind of a firmware programmer. Last time, I got an experience that my program executed wrongly even though I could not find any fault in my program. Suddenly, I remembered stack overflow problem and the program worked correctly after I changed the stack size.


Variable not declared volatile

If an interrupt service routine changes variables which are accessed by other functions these variables have to be declared volatile. See http://en.wikipedia.org/wiki/Volatile_variable.

Non-atomic access

If the access to these variables is not atomic (i.e. the processor needs more than one instruction for the access and could be interrupted while accessing the variable) the interrupt must be disabled during the access to avoid inconsistent data. Access to 16 or 32 bit variables is obviously not atomic on 8 bit CPUs and should be protected by disabling interrupts. You’re not automatically on the safe side if you use 8 bit variables though. For example, on the 8051 the harmless looking ”flags |= 0x80;” is not atomic if flags resides in xdata. Setting ”flags |= 0x40;” from within an interrupt routine might get lost if the interrupt occurs at the wrong time. ”counter += 8;” is not atomic on the 8051 even if counter is located in data memory. Bugs like these are hard to reproduce and can cause a lot of trouble.

Stack overflow

The return address and the registers used in the interrupt service routine are saved on the stack so there must be sufficient stack space. If there isn’t enough stack space, variables or registers (or even the return address itself) will be corrupted. This stack overflow is most likely to happen if the interrupt occurs during the ”deepest” subroutine when the stack is already in use for i.e. many return addresses.

Use of non-reentrant functions

Calling other functions from an interrupt service routine is not recommended, avoid it if possible. Furthermore nonreentrant functions should not be called from the main program while the interrupt service routine might be active. They also must not be called from low priority interrupt service routines while a high priority interrupt service routine might be active. You could use semaphores or make the function critical if all parameters are passed in registers. Good luck with your programming!

Thursday, June 10, 2010

Circular Buffered UART Com Module for 8051 Microcontroller

A lot of embedded systems uses UART communication. That is why, I would like to share a circular buffered UART comm module here. I have developed the module for 8051 microcontroller but it can easily be modified for other microcontrollers as well.

Using Circular Buffered UART Com Module

You need to put the header files in the module you want to use them. In my example, I put all my header files into 'headers.h' file and I just need to include that file. Transmit and receive buffer sizes need to be defined in ComConfig.h file. And then, define a function to call on receive event. In the main function, poll the ComChkRx() function to retrieve the received data from the buffer. The source code for the example can be seen at

UART-Timer-8051 on GitHub

Thursday, June 3, 2010

Soft-Timer Module for 8051 Microcontroller

Almost every embedded system uses timers in their firmware. 8051 microcontroller has only two or three hardware timers, and generally, it is not enough to use hardware for all the timers your system needs to have. Furthermore, not all timers need to have hard timing requirement. For example, blinking an LED indicator every second is accurate enough if the timing error is less than a few millisecond. That is why, I normally use software to implement all the timers that have soft timing requirement. Here, I would like to share a soft-timer module that I developed for 8051 microcontroller but it can easily be modified for other microcontrollers as well. The source code for the example can be seen at

UART-Timer-8051 on GitHub


Using soft-timer module

You need to put the header files for soft-timer in the module you want to use them. In my example, I put all my header files into 'headers.h' file and I just need to include that file.
Write a function to be called when the timer time out. Write another function to set the timing parameters and start the timer. In my example, they are SysSBYLEDTmrTO() and SysSBYLEDInit() in System.c module.
Open TmrConfig.h and follow the 3 steps as indicated in the comment. If your compiler does not support function pointers, you can always replace with switch structure.
In the main function, initialize and poll the timer module by calling TmrInit() and TmrTask() respectively which are defined in Tmr.c module.