katolicki-tjednik.com
Menu
RSS
January 20, 2023

Network management – Embedded Flakes

maximios ⋅ IT

SAE J1939 specifiction defines decentralized network management which means each control unit must implement minimum set of functions. The network management functions are described in the document SAE J1939/81. SAE J1939…

January 2, 2023

Diagnostics – Embedded Flakes

maximios ⋅ IT

Diagnostics functionality is very crucial for repairing and maintaining any system. The complex system often need to identify and communicate faults to different subsystems, need calibration functionality, need the ability…

January 2, 2023

J1939 Diagnostics – Embedded Flakes

maximios ⋅ IT

Diagnostics functionality is very crucial for repairing and maintaining any system. The complex system often need to identify and communicate faults to different subsystems, need calibration functionality, need the ability…

July 1, 2022

Email Protection | Cloudflare

maximios ⋅ IT

The website from which you got to this page is protected by Cloudflare. Email addresses on that page have been hidden in order to keep them from being accessed by malicious bots. You must enable Javascript in your browser in order to decode the e-mail address.

If you have a website and are interested in protecting it in a similar way, you can sign up for Cloudflare.

August 15, 2018

Interrupts – Embedded Flakes

maximios ⋅ IT

New Software programmers often get confused with the concept of interrupts. It is very simple to understand if we consider an analogy with our daily tasks. Assume you are cooking food and you get a phone call. What do you do in such situation? You first checks who is calling?

  1. If the caller is not important then you just ignore the call and continue cooking.
  2. If caller is important; then you stop cooking. Probably you switch off the cooking stove. Then you answer the call. Once you finish talking, you again resume back to cooking routine.

This is exactly how interrupts work in embedded systems.

Interrupts are signals to processor that indicate an asynchronous event. Interrupts can be initiated by external peripheral devices or internally in the CPU. Broadly interrupts can be categorized in to 5 different types based on how they are generated.

  1. Events occuring on peripheral device
  2. Involuntary events internal to CPU
  3. Voluntary events inside CPU
  4. Actions by operator
  5. Timer interrupts

1. Events occurring on peripheral devices

These interrupts are generated to notify CPU of some events occurred on connected devices. For example, RTC tick after every second or external ADC signal indicating that ADC conversion is complete.

Such external interrupts can be used for scheduling specific tasks in operating system.

2. Involuntary events internal to CPU

These interrupts are generated internally to handle some error conditions or exceptions such as divide by zero or accessing memory location which are not available. Such exceptions are handled through branching in microcode. A carefully written code shall handle such exceptions to make the system fault tolerant.

3. Voluntary events inside CPU

Sometimes flow of program needs to be modified so that control can go from application to OS or to supervisory tasks. Such transitions can be handled through purposefully generated interrupts such as SVC (supervisory call) or software interrupts.

4. Actions by operator

Such interrupts are used to detect asynchronous actions triggered by operators such as key press. Sometimes actions are triggered by non-human operators such as temperature increase by engine, or mechanical movement because of external force. Interrupts can be used to identify such event by means of sensors. For example mechanical movement can be detected by limit switch interfaced to microcontroller. An interrupt generated on this event can be used to control actuators.

5. eTimer interrupts

These interrupts are generated by internal or external timer registers. This is categorized separately because in most operating systems timer interrupts are required for task scheduling.

Internal Handling Of Interrupts

Once an interrupt signal is received, the CPU completes the instruction that is currently being executed. Then the contents of program counter are saved to interrupt return location or on stack. In many cases complete CPU state is saved so that any previous instruction information can be saved. This is done by pushing CPU flags and status register to stack. This process is often called as context saving.

Once context is saved, program counter is loaded with memory location address of interrupt handler or ISR (interrupt service routine). Then the ISR is executed. Once the ISR execution is complete control shall return to main program. This is done by fetching the saved context back to CPU registers. This is simply done by poping the information saved on stack in reversed order.

Diagrams below explains sequence of simple interrupt handling.

Interrupt handling step 1: Interrupt is detected. CPU first complete the execution of running instruction Interrupt handling step 2: Contents of PC, Program status register and other CPU registers pushed to stack Interrupt handling step 3: Program counter is loaded with Interrupt Vector (address of ISR) Interrupt handling step 4: Execution of ISR started Interrupt handling step 5: Execution of ISR complete.
Content loaded on stack are poped in reverse order. Program counter is loaded with address of next instruction. Interrupt handling step 6: Main program execution resume back.

Modern microprocessors and microcontrollers provide way to handle multiple interrupts. In some microcontrollers, interrupts have fixed priority whereas most of the modern architectures provide configuration options to change interrupt priorities.

CPU provides instructions to enable and disable all interrupts globally. Individual interrupts also can be enabled or disabled using interrupt control registers. Once an interrupt is generated other interrupts are disabled. If any other interrupt is active then its state is stored so that it can be serviced once first ISR execution is complete. Some architecture even supports nested interrupts. A higher priority interrupt can stop lower priority ISR. Then program counter and other CPU status registers are saved to stack and program counter is loaded with address of higher priority interrupt vector. Once the higher priority ISR is execution is complete the saved content are reloaded and previous low priority ISR continues.

We will see how interrupts are handled in some popular micro-controllers in next sections.

Part 2: Interrupt handling in 8051

Part 3: Interrupt handling in Renesas R8C series micro-controllers (coming soon)

Part 4: Interrupt handling in AVR micro-controller (coming soon)

Part 5: Programmable interrupt controllers (coming soon)

Mohan is working in embedded system design since 12 years. In his career Mohan worked in different fields like research and development, consumer electronics, process automation, device driver development and automotive software development. He has hands on experience in hardware design, board bring up and production, software architecture and design. He is passionate about robotics, automation, automotive software development and sensors. He loves talking about control systems, predictive control, embedded software optimization.

January 19, 2018

The Basic Guide of Switch Debouncing – Embedded Flakes

maximios ⋅ IT

Switches are very important part of machine interface. Pressing horn in your car or hitting the call button on your cell phone, we interact with daily various machines through switches. There are varieties of switches we press, rotate or touch daily. Your funky radio jumps 2 or 3 channels ahead when you press tuning button only once. Sometimes your TV does not respond and you have to press the remote button very hard.  Have you seen a counter in mall door advances several digits when only one person is passed through the door? These are classic problems with bad switch debouncing. Novice embedded designers often face issues in switch debounce design. This article is a small introduction to the switch debouncing techniques.

Interfacing a switch with microcontroller looks very simple thing; but a lot of things happen behind the scene when a user presses a button. Understanding the behaviour of switches helps in designing a good switch debouncing policy.

When the contacts of a mechanical switch are pressed, they rebound several times with different frequencies and then settle down to a fixed state. The rebound of mechanical contact is known as bounce. We have variety of switches; push buttons, SPDT, DPDT, latch-able buttons, rotary switches, joysticks etc. Again these switches come in different size and different current ratings. Because of such variations in switches, the bounce is also different in each type of switches. People press buttons in different ways. Some people press buttons very quickly, some push it very slowly, some use do it by hand, some use different objects to reach to the switches. So the designing the debouncing solution could be tricky sometimes.

What type of switch you choose is mainly depends on the application needs. Once you know the bounce timing stats of a particular switch, you can easily design switch debouncing policy. First crucial step is to find Maximum bounce time of switch contacts. One can observe voltage levels at the switch contacts using oscilloscope and can easily find maximum bounce time. Operate switch with different techniques, slow, fast, with soft touch, with hard touch, release gently, release fast. Try different combinations of these techniques and collect the bounce statistics. With this statistics you can easily arrive at the Maximum bounce time for your switches. Bounce time during open to close transition of switch can be different than the bounce time during close to open transition.

There are some proven techniques used to remove the effect of switch bounce in digital applications. You can use hardware or software switch debouncing methods. Hardware switch  debouncing consists of simple hardware filters, digital switch debouncing circuits and dedicated ICs. Software switch debouncing method utilizes different algorithms, some are microcontroller platform dependent using specific interrupts, some use counters and some use simple delays before re-sampling the inputs.

Hardware solutions

Simple RC filter

Most common type of the switches used in small appliances are single throw buttons, tactile push button and board mounted plates. Using a simple RC filter circuit is a lot cheaper solution than any other hardware debouncing technique. Low pass RC filter removes high frequency changes in the switch bounce.

RC debounce circuit

When the switch is open the voltage across capacitor C rises at a rate determined by values of R1, R2 and C. Bouncing of the switch slows down the charging rate of capacitor C. In time the capacitor charge and the output of the NOT gate (Schimtt trigger) gives logical zero output.

When the switch is closed the capacitor starts discharging via R2. Till the time the capacitor is discharged to a significant level, NOT gate sees logical one at its input. Once the switch settled in stable closed position after bouncing the capacitor C discharges completely and reach level zero. And the NOT gate gives logical one output.

Values of resistors in RC filter

Consider discharging cycle of the capacitor C,

Where

Vc= Voltage across capacitor C at time t

V0= initial voltage across capacitor C

t = time in seconds

To calculate R2, select Vc such that it is greater than switching voltage of the NOT gate in the above circuit.

So the equation for R2 will become

Now consider charging cycle of capacitor C.

Let R = R1 + R2 then

Therefore equation for R becomes

Vf  is the final voltage of the charged capacitor. It could be 5V or 3.3V or any other value based on your digital circuit. To calculate R, select Vc such that the less than the lower switching limit for high going signal for NOT gate.

Values of R1 and R2 can be calculated by above formulas.

RC filter with diode

If the value of R is less than R2, then use diode parallel to the R2 as shown in the diagram below so that you can eliminate R2 from the charging path.

Simple RC Debouncing circuit with diode

SR flip flop latch

SR flip flop latch is very good debouncer for switches with double throw. It consist of 2 NAND gates connected as shown in below diagram.

SR Latch used for debounsing SPDT switch input

When we move switch to a position as shown in the diagram above, the output of the latch will be one. If we move the switch to another position, the output of the latch will be zero. When we move the switch between contacts, it bounces little bit on one contact but do not touch the other contact. So we get a stable, bouncing free output from the SR latch.

Switch Debouncing ICs

Since the cheaper alternatives available to fix the bouncing problem, specialized switch debounce ICs are not very popular. Maxim Integrated Products Inc. is the one leading manufacturer of debounce ICS. They have different variants with single, dual and octal switch debouncers in one package. These debouncing ICs provide inbuilt ESD protection.

More information can be found in application note 287.

Handling Switch Debouncing in Software

Basic idea in software debouncing is to sample the input at regular interval and filter out the glitches. There are number of different ways to implement switch debouncing. If you are not much concerned about real time performance just check the switch input state, then wait a bit and recheck again. If the same state is detected then that can be considered as a stable state of the switch. Another way is to use counter and check for how long the switch is low or high and if it is consistently low or high for predefined time then it is considered stable state of switch. Sometimes EMI can produce false signals on the microcontroller pin inputs. Software debouncing also filters such noise.

Programmers must take some care while designing debouncing policy. Avoid sampling of switch input at rate synchronous to other events which can create EMI, e.g. motor direction change frequency or 50Hz/60Hz frequency. Do not connect undebounced switches directly to the interrupt pins of microcontrollers. Some microcontrollers provide special interrupt pins which have inbuilt RC filter. Such pins can be used as switch interrupts.

Hardware debouncing involve some cost of components and also need some space on circuit board. So software debouncing is very popular and people are using different algorithms for implementing switch debouncing.

Mohan is working in embedded system design since 11 years. In his career Mohan worked in different fields like research and development, consumer electronics, process automation, device driver development and automotive software development. He has hands on experience in hardware design, board bring up and production, software architecture and design. He is passionate about robotics, automation, automotive software development and sensors. He loves talking about control systems, predictive control, embedded software optimization.

January 19, 2018

Essentials of Interrupt handling in 8051 – Embedded Flakes

maximios ⋅ IT

Interrupt handling in 8051 is very simple. To learn interrupts handling in 8051 microcontroller; first of all we must understand what different types of interrupts available in 8051 microcontroller.

Types of interrupts in 8051

  1. External hardware interrupt – INT0
  2. External hardware interrupt – INT1
  3. Timer 0 overflow interrupt – TF0
  4. Timer 1 overflow interrupt – TF1
  5. Serial communication interrupt – RI/TI

Timer and serial interrupts are internally generated by the inbuilt timer and USART peripherals modules.

External interrupts are generated by external interfacing devices such as Switches, number pad, RTC etc.

When interrupt occurs, microcontroller first finishes the instruction which it is executing and then jumps to the memory location corresponding to the interrupt. This memory location is also known as interrupt vector. 8051 microcontroller have fixed interrupt vectors for each interrupt as shown in below table.

Interrupt number Description Memory Address
0 External hardware interrupt INT0 0003h
1 Timer/Counter 0 interrupt 000Bh
2 External hardware interrupt INT1 0013h
3 Timer/Counter 1 interrupt 001Bh
4 Serial communication interrupt 0023h

Interrupt Priority:

In 8051, each interrupt can have either high priority or low priority. Priority level of interrupt can be set to high by setting corresponding bit in Interrupt Priority (IP) resister or it can be set to low by clearing corresponding bit in IP register.

(MSB) IP.7 IP.6 IP.5 IP.4 IP.3 IP.2 IP.1 (LSB) IP.0
Direct Address B8H – – PT2 PS PT1 PX1 PT0 PX0
Bit Address BF BE BD BC BB BA B9 B8
Bit 7: Reserved
Bit 6: Reserved
Bit 5: PT2 0: Low priority for Timer 2 interrupt

1: High priority for Timer 2 interrupt

Bit 4: PS 0: Low priority for Serial interrupt

1: High priority for Serial interrupt

Bit 3: PT1 0: Low priority for Timer 1 interrupt

1: High priority for Timer 1 interrupt

Bit 2: PX1 0: Low priority for External interrupt INT1

1: High priority for External interrupt INT1

Bit 1: PT0 0: Low priority for Timer 0 interrupt

1: High priority for Timer 0 interrupt

Bit 0: PX0 0: Low priority for External interrupt INT0

1: High priority for External interrupt INT0

If multiple interrupts of different priority level are received simultaneously then high priority interrupt is serviced first. If requests of the same priority level are received simultaneously, an internal polling sequence determines which request is to be serviced, Thus within each priority level is a second priority structure determined by the polling sequence. Polling sequence is shown in table below.

Source Priority within Level
1 External hardware interrupt INT0 Highest
2 Timer/Counter 0 interrupt
3 External hardware interrupt INT1
4 Timer/Counter 1 interrupt
5 Serial communication interrupt Lowest

Combination of IP register and polling sequence gives unique priorities to all 5 interrupts in 8051 microcontroller. If all bits in IP register are cleared then external interrupt INT0 will have highest priority, timer 0 will be next and serial communication interrupt will have lowest priority. If multiple interrupts are triggered at same time, then the interrupts are serviced according to priority. For instance, if external hardware interrupt INT1 and external hardware interrupt INT0 are triggered at exactly same time, then external hardware interrupt INT0 will be serviced first.

Enabling Interrupt:

Upon reset, all interrupts are disabled (masked), meaning that none will be responded to by the microcontroller if they are activated. The interrupts must be enabled by software in order for the microcontroller to respond to them. There is a register called IE (interrupt enable) that is responsible for enabling (unmasking) and disabling (masking) the interrupts.

In 8051 microcontroller, interrupts can be enabled or disabled by setting or clearing corresponding bits in Interrupt Enable (IE) Register. Also all interrupts can be enabled or disabled globally using EA bit in IE register.

(MSB) IE.7 IE.6 IE.5 IE.4 IE.3 IE.2 IE.1 (LSB) IE.0
Direct Address A8H EA – ET2 ES ET1 EX1 ET0 EX0
Bit Address AF AE AD AC AB AA A9 A8
Bit 7: EA 0: Disable all interrupts

1: Enable all interrupts according to individual enable bits

Bit 6: Reserved
Bit 5: ET2 0: Disable Timer 2 interrupt

1: Enable Timer 2 interrupt

Bit 4: ES 0: Disable Serial interrupt

1: Enable Serial interrupt

Bit 3: ET1 0: Disable Timer 1 interrupt

1: Enable Timer 1 interrupt

Bit 2: EX1 0: Disable External interrupt INT1

1: Enable External interrupt INT1

Bit 1: ET0 0: Disable Timer 0 interrupt

1: Enable Timer 0 interrupt

Bit 0: EX0 0: Disable External interrupt INT0

1: Enable External interrupt INT0

Timer Control Register (TCON):

(MSB) TCON.7 TCON.6 TCON.5 TCON.4 TCON.3 TCON.2 TCON.1 (LSB) TCON.0
Direct Address 88H TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0
Bit Address 8F 8E 8D 8C 8B 8A 89 88
Bit 7: TF1 Timer 1 overflow bit set by controller when timer 1 overflows.

Cleared when processor vectors to execute interrupt service routine located at program address 001Bh.

Bit 6: TR1 0: Turn Off Timer 1

1: Turn On Timer 1

Bit 5: TF0 Timer 0 overflow bit set by controller when timer 0 overflows.

Cleared when processor vectors to execute interrupt service routine located at program address 000Bh.

Bit 4: TR0 0: Turn Off Timer 0

1: Turn On Timer 0

Bit 3: IE1 External interrupt 1 Edge flag. Set to 1 when a high-to-low edge signal is received on port 3.3 (INT1).

Cleared when processor vectors to interrupt service routine at program address 0013h. Not related to timer operations.

Bit 2: IT1 0: External interrupt INT1 triggered on low level

1: External interrupt INT1 triggered on falling edge

Bit 1: IE0 External interrupt 0 Edge flag. Set to 1 when a high-to-low edge signal is received on port 3.2 (INT0).

Cleared when processor vectors to interrupt service routine at program address 0003h. Not related to timer operations.

Bit 0: IT0 0: External interrupt INT0 triggered on low level

1: External interrupt INT0 triggered on falling edge

TF0 and TF1 bits of TCON register are set by controller when all bits of timer 0 or timer 1 roll over from 1 to 0. TF0 and TF1 bits can be polled to detect timer overflow event. These bits are automatically cleared when processor executes interrupt service routine (ISR) located at respective timer vector address.

TR0 and TR1 bits are used to run or stop timer 0 and timer 1 respectively.

IT0 and IT1 bits are used for external interrupts. External interrupt will be triggered on low level of signal if IT0/IT1 bit is set to 0. External interrupt will be triggered on falling edge of signal if IT0/IT1 is set to 1.

IE0 and IE1 bits are external interrupt flags. These bits are set to 1 if falling edge is received on external interrupt pins.

Interrupt flags (TF0, TF1, IE0, IE1) are set by controller when respective interrupt event is received and these bits are cleared automatically when respective ISR is executed by the controller. If interrupts are disabled and interrupt flags are polled through program, then program must take care of clearing respective flags.

Other Related Registers:

Timer 0 Registers – TH0 and TL0 are timer high byte and timer low byte. TH0 and TL0 are byte addressable registers. TH0 and TL0 together make a 16 bit timer register. Since 8051 is 8 bit controller; timer register accessed in two bytes, one byte for TH0 and one for TL0.

Timer 1 Registers – TH1 and TL1 are timer high byte and timer low byte. These are byte addressable registers.

Timer Mode Register (TMOD) – TMOD is used to set timer mode. 8051 controller supports 4 timer modes.

  • 13 bit timer
  • 16 bit timer
  • 8-bit Auto reload
  • Split timer mode
(MSB) TMOD.7 TMOD.6 TMOD.5 TMOD.4 TMOD.3 TMOD.2 TMOD.1 (LSB) TMOD.0
Direct Address 89H GATE1 C/T1 M1 M0 GATE0 C/T0 M1 M0
TMOD is not bit Address
Bit 7: GATE1 0: Timer 1 runs regardless of state of INT1

1: Timer 1 runs when INT1 P3.3 is high

Bit 6: C/T1 0: Timer 1 incremented every machine cycle

1: Timer 1 incremented every falling edge on INT1 P3.3 (event counter)

Bit 5: M1 Timer 1 Mode bits

M1 M0

0    0 : Timer 1 mode 0 – 13 bit timer

0    1 : Timer 1 mode 1 – 16 bit timer

1     0 : Timer 1 mode 2 – 8 bit auto reload

1     1 : Timer 1 mode 3 – Spilt timer mode

Bit 4: M0
Bit 3: GATE0 0: Timer 0 runs regardless of state of INT0

1: Timer 0 runs when INT0 P3.2 is high

Bit 2: C/T0 0: Timer 0 incremented every machine cycle

1: Timer 0 incremented every falling edge on INT1 P3.3 (event counter)

Bit 1: M0 Timer 0 Mode bits

M1 M0

0     0 : Timer 0 mode 0 – 13 bit timer

0     1 : Timer 0 mode 1 – 16 bit timer

1      0 : Timer 0 mode 2 – 8 bit auto reload

1     1 : Timer 0 mode 3 – Spilt timer mode

Bit 0: M1

Serial Control Register (SCON) – SCON register is used for serial communication.

(MSB) SCON.7 SCON.6 SCON.5 SCON.4 SCON.3 SCON.2 SCON.1 (LSB) SCON.0
Direct Address 98H SM0 SM1 SM2 REN TB8 RB8 TI RI
TMOD is not bit Address 9F 9E 9D 9C 9B 9A 99 98
Bit 7: SM0 Serial mode select bits

SM0  SM1

0        0 : mode 0 – Half duplex with fixed baud rate

0        1 : mode 1 – full duplex with variable baud rate (1 start bit, 8 data bits, 1 stop bit)

1        0 : mode 2 – full duplex 11 bit serial communication

1        1 : Mode 3 – Dull duplex with variable baud rate

Bit 6: SM1
Bit 5: SM2  Set to 0 in mode 0.

Used to store stop bit in mode 1.

Used for multiprocessor communication in mode 2 and 3.

Bit 4: REN 0: Disable serial communication

1: Enable serial communication

Bit 3: TB8 Used in mode 2 and 3
Bit 2: RB8 Used in mode 2 and 3
Bit 1: TI Transmit interrupt flap set by microcontroller when one character transmission is complete.
Bit 0: RI RI is Receive Interrupt flag, When 8051 receive data via RxD pin

Serial Buffer (SBUF) – This register is used for transmitting or receiving data serially. We put data in it which we want to transmit, it also contains the data which is transmitted from other peripherals like personal computers (PC) to 8051 micro controller. It is not bit addressable.

Find economical 8051 development boards here

Interrupt Handling in 8051

Most instructions in 8051 take 1 machine cycle to complete. Some instructions take 2 or 3 machine cycles. One machine cycle consists of 6 states S1 to S6 and every state has 2 pulses P1 and P2. So a machine cycle takes 12 pulses of clock to execute.

The interrupt flags are sampled at P2 of S5 of every instruction cycle. The samples are polled during next instruction cycle. If one of the flags was set at S5P2 of the preceding machine cycle, the polling detects it and the microcontroller generates interrupt by generating a long call (LCALL) to the appropriate vector address. When an equal or a higher priority interrupt is already being serviced then the microcontroller does not generate LCALL. While the instruction in progress is RETI or any write to IE or IP registers then the microcontroller does not generate LCALL. If interrupt is blocked because of above mentioned reasons then the interrupt will be serviced after removal of blocking conditions only if interrupt flap is still active.

When an interrupt occurs and the program is directed to the interrupt vector address, the Program Counter (PC) value of the interrupted program is stored (pushed) on the stack. The required Interrupt Service Routine (ISR) is executed. At the end of the ISR, the instruction RETI returns the value of the PC from the stack and the originally interrupted program is resumed.

Steps in executing interrupts:

  1. Microcontroller finishes the instruction it is executing and saves the address of the next instruction (PC) on the stack.
  2. Jump to a fixed location in memory called the interrupt vector table that holds the address of the interrupt service routine.
  3. Microcontroller gets the address of the ISR from the interrupt vector table and jumps to it. It starts to execute the interrupt service subroutine until it reaches the last instruction of the subroutine, that is RETI (return from interrupt).
  4. Upon executing the RETI instruction, the microcontroller returns to the place where it was interrupted. First, it gets the program counter (PC) address from the stack by popping the top two bytes of the stack into the PC. Then it starts to execute from that address.

Programmers must be careful while manipulating data on stack during ISR execution. In ISR number of PUSH and POP must be same.

How to write ISR

ISR is like any other subroutine in program, except that it must end with RETI instruction and not with RET instruction. First line of ISR must begin from corresponding vector address. In some cases ISR will be very long and it may not be practical to write all code starting from vector address. So ISR is kept at some other location in the program memory and an unconditional jump to the starting address of ISR must be provided from corresponding vector address.

Whenever a triggered interrupt is acknowledged and the processor branches to its corresponding vector address, it automatically disables the interrupt in IE register. This disabled interrupt would only be re-enabled upon executing the RETI instruction placed inside the ISR.

Example: ISR for INT0

        ORG     0H      ; Power on ROM reset location 
        LJMP    MAIN    ; bypass all the interrupt vector locations 

        ORG     0003H    ; ISR for INT0 beginning from its vector address 
        LJMP    ISR_INT0 ;unconditional jump from 0003H to the starting 
                          address of ISR 
        ORG     30H 
MAIN:   SETB    IT0      ; configure interrupt 0 for falling edge on INT0 
        SETB    EX0      ; enable external interrupt INT0 
        SETB    EA       ; enable global interrupt flag 
        ---------- 
HERE:   SJMP    HERE 

; ISR for INT0 
ISR_INT0: 
       SETB     P0.0     ; turn on some output 
       SETB     P0.1     ; turn on some output 
       --------- 
       --------- 
       RETI 
       END

Below is the alternate C code for same ISR. The compiler itself handles the address mapping. You only have to write the ISR function with the corresponding “interrupt number”.

void main() 
{ 
    IT0 =  1; // configure interrupt 0 for falling edge on INT0 
    EX0 = 1;   // enable external interrupt INT0 
    EA = 1;    // enable global interrupt flag 
    ------- 
    while(1); 
}   

// ISR for INT0 beginning from its vector address 
void ISR_INT0(void) interrupt 0 
{ 
    P0.0 = 1;   // turn on some output 
    P0.1 = 1;   // turn on some output 
    -------- 
}

Software Interrupts in 8051

Software interrupts are generated by program itself inside the controller. Generating software interrupt in 8051 microcontroller is tricky. When external interrupt received at INT0 pin TCON.0 bit (IT0) would be set automatically and processor generates interrupt. If the TCON.0 bit is set in program, microcontroller immediately acknowledges it as interrupt and branch to corresponding ISR of INT0. As a result, 8051 Microcontroller executes software interrupt exactly same as normal ISR.

Read more about interrupts

Interrupts

Mohan is working in embedded system design since 11 years. In his career Mohan worked in different fields like research and development, consumer electronics, process automation, device driver development and automotive software development. He has hands on experience in hardware design, board bring up and production, software architecture and design. He is passionate about robotics, automation, automotive software development and sensors. He loves talking about control systems, predictive control, embedded software optimization.

January 6, 2017

Code Optimization – Embedded Flakes

maximios ⋅ IT

Memory is a costly comodity in the world of embedded software development. Software programmers often need to optimize the code to reduce memory utilization or to increase speed of execution. It is the last step in software development, but this is not always in the case of embedded system development. To save the cost of the product, hardware designers design the system having barely enough memory and processing power to get the job done. The goal of code optimization is to make the working program run on the lower cost production version of the hardware.

If you are struggling with low memory size and slow processing speed, these are some code optimization techniques you can implement into your project to increase the code efficiency and to save some amount of memory.

Increasing Code Efficiency:

Modern compilers provide some degree of code optimization. However, most of the optimization techniques of the compiler involve a trade-off between execution speed and code size. An improvement in one area can have negative impact on another. Your program can be either faster or smaller, but not both. It is programmer’s choice to decide which of these improvements is most important.

As execution speed is usually important only in certain time critical or frequently executed sections of the code, it is recommended to reduce the size of the program, and improve the efficiency of those time critical or frequently executed sections by hand. However, code size is a difficult thing to influence manually, and compiler optimization is better option to make this change across all software modules.

After compiler’s optimization process, you can identify the sections/routines that require greater code efficiency. You can use the following techniques to reduce execution time of such sections/routines.

Inline functions

“inline” keyword makes a request to the compiler to replace all calls to the indicated function with copies of the code that is inside. This eliminates the runtime overhead associated with the actual function call. This is most effective when the inline function is called frequently but contains only a few lines of code. Though inline function improves execution speed, it increases the code size.

Table lookups

A “switch” statement is one of the common decision making technique used in programming. It needs to be used with care, because each test and jump in switch statement uses valuable processor time simply deciding what work should be done next. By putting the most likely cases first and the least likely cases last we can reduce the average execution time.

If there is a lot of work to be done within each case, it might be more efficient to replace the entire switch statement with a table of pointers to functions. For example,

int completeAction1 (void);

int completeAction2 (void);

int completeAction3 (void);

int ActionIndex;

ActionIndex = getActionIndex();

switch (ActionIndex)

{

     case ACTION1:

          completeAction1 ();

     break;

     case ACTION2:

          completeAction2 ();

     break;

     case ACTION3:

          completeAction3 ();

     break;

     default:
}

This code can be optimized by using function pointers as below.

void completeAction1 (void);

void completeAction2 (void);

void completeAction3 (void);

/* define function pointer array */

void (*ActionFunctions[ ]) () = {completeAction1, completeAction2, completeAction3};

/* The switch statement can be replaced by*/

int ActionIndex;

ActionIndex = getActionIndex ();

ActionFunctions (ActionIndex);

Hand coded assembly

Hand coded assembly gives programmer an opportunity to make software modules as efficient as possible. Good programmer can write better machine code than average compiler for a given function.

Register variables

For frequently accessed variables, you can use the keyword “register”. This tells the compiler to store the variable into a general purpose register, rather than on the stack. This enhances the performance of the function.

Global variables

Global variables eliminate the need to push the parameter onto the stack before the function call and pop it back off once the function is completed. Therefore, it is more efficient to use a global variable than to pass a parameter to a function.  

Though the global variables save some ROM size, they take up permanent place in RAM, so they increase RAM consumption. Also global variables are visible to all modules and can be easily modified by any other module so the global variables must be used with more care.

Decreasing Code Size:

When it comes to reducing code size, your compiler’s optimization is the best option. However, if the resulting program is still too large for your available ROM, there are many techniques you can use to further reduce the size of your program.

Natural word size

ANSI C and C++ standards state that data type int must always map to processor’s native word size. It requires the use of additional machine language instructions to perform manipulation of smaller and larger data types. So it’s a good practice to use int whenever possible in your program.

Goto statement

Using goto statement, you can remove the complicated control structures or to share a block of repeated code. goto statement generally disrupts code structure, flow and readability. If used inappropriately, goto statement can even break your code. So, my advice is to use goto when it is absolute necessary.

Avoid standard library routines

Large standard library routines are expensive only because they try to handle all possible cases. It might be possible to implement a subset of the functionality yourself with significantly less code. This is why it is good to avoid standard library routines.

Techniques described in the previous section specifically table lookups, hand coded assembly, register variables and global variables are also helpful in reducing code size. Of these, the use of hand coded assembly yields the largest reduction in code size.

Reducing Memory Usage:

In some applications, RAM is limiting factor rather than ROM. In such cases, you need to reduce your dependence on global data, the stack and the heap. Programmer can make these optimizations better than compiler.

“const” keyword

Using const keyword before your constant data, you can instruct the compiler to store that data into the ROM. Most compilers place all constant global data into a special data segment that is recognizable to the locator as ROM-able. This is most valuable when you have lots of strings or table oriented data that does not change at runtime.

Stack size reduction

RAM requirement of your program can be lowered by reducing stack size. In case of real time operating systems, you need to be conscious of stack space. Most of the operating systems create a separate stack for each task. You can determine the amount of stack required for each task. You might also try to reduce the number of tasks that has a separate “interrupt stack” for execution of all interrupt service routines.

Using one or more of these optimization techniques you can improve code quality and efficiency of your program.

­Note: Never make the mistake of assuming that the optimized program will behave the same as the unoptimized one. You must completely retest your program at each new optimization level to be sure its behaviour has not changed.
«‹ 7 8 9 10

Recent Posts

  • 8051 Oscillator Circuits: The Heartbeat of Your Microcontroller – Embedded Flakes
  • Easily Make Plots in MATLAB in 5 Minutes – Embedded Flakes
  • TOP 5 OPEN SOURCE SOLUTIONS FOR VERSION CONTROL – Embedded Flakes
  • 8051 LCD Interfacing Secrets: Display Like a Champion – Embedded Flakes
  • About – Embedded Flakes

Recent Comments

No comments to show.

Archives

  • December 2025
  • September 2025
  • August 2025
  • July 2025
  • December 2024
  • September 2024
  • August 2024
  • June 2024
  • February 2024
  • December 2023
  • September 2023
  • January 2023
  • July 2022
  • August 2018
  • January 2018
  • January 2017

Categories

  • IT