An Embedded Software Primer - PowerPoint PPT Presentation

1 / 20
About This Presentation
Title:

An Embedded Software Primer

Description:

An assembly language is a more easily readable form of the instructions that a ... Labels are followed by colons. ADD R2, R3. NOT R2. JUMP NO_ADD. ADD: ... – PowerPoint PPT presentation

Number of Views:2580
Avg rating:3.0/5.0
Slides: 21
Provided by: ideaEn
Category:

less

Transcript and Presenter's Notes

Title: An Embedded Software Primer


1
An Embedded Software Primer
  • David E. Simon

2
Chapter 4 Interrupts
  • Microprocessor Architecture
  • Interrupt Basics
  • The Shared-Data Problem
  • Interrupt Latency

3
Microprocessor Architecture
  • Most microprocessors and their assembly languages
    are generally similar to one another.
  • An assembly language is a more easily readable
    form of the instructions that a microprocessor
    actually works with.
  • The assembly language is translated into binary
    numbers by a program called an assembler before
    execution.
  • When translating C, most of the statements are
    converted into multiple assembly instructions by
    the compiler.
  • Each microprocessor family will have a different
    assembly language (e.g. the Intel 8085, 8051
    etc.) however the individual microprocessors in
    the same family generally have the same assembly
    language.
  • Microprocessors typically have a set of
    (general-purpose) registers that can store data
    values.

4
Microprocessor Architecture (contd.)
  • The registers are used before performing any data
    operations like arithmetic. For the following
    sections assume the microprocessor has the
    registers R1, R2, R3 .etc.
  • Apart from the above registers, microprocessors
    normally contain special registers like
  • Program Counter Contains the address of the next
    instruction to be executed.
  • Stack Pointer Contains address of the top of the
    processor stack.
  • Accumulator Used by the microprocessor to do
    arithmetic operations.

5
Microprocessor Architecture (contd.)
  • Some assembly language conventions
  • The variables in the instruction are normally
    read from right to left.
  • e.g. MOVE R1, R2
  • will move the contents of register R2 to register
    R1
  • A variable-name in an instruction refers to its
    address.
  • MOVE R5, Temperature
  • is read move the address of Temperature to
    register R5
  • A variable in parentheses refers to the value of
    the variable.
  • MOVE R5, (Temperature)
  • will place the value of Temperature in register
    R5.
  • Anything following a semicolon is a comment.

6
Microprocessor Architecture (contd.)
  • Some important instructions include
  • Arithmetic ADD R2, R3
  • add contents of R3 to R2
  • Bit-oriented NOT R5
  • invert all the bits of R5
  • Jump (unconditional) Will unconditionally jump
    to an instruction specified by a label. Labels
    are followed by colons.
  • ADD R2, R3
  • NOT R2
  • JUMP NO_ADD
  • ADD
  • ADD R2, R5 Comments come here
  • NO_ADD
  • MOVE R7, R2 R7 contains the final result
  • The instruction adds contents of R3 to R2,
    inverts the result in R2, jumps unconditionally
    to the NO_ADD label (the instruction ADD R2, R5
    never gets executed) and stores the result in R7.

7
Microprocessor Architecture (contd.)
  • Conditional Jump Executes a jump if a certain
    condition is true.
  • SUBTRACT R2, R3
  • JCOND ZERO,NEXT
  • .
  • .
  • NEXT
  • .
  • .
  • Here jump is executed if result of the
    subtraction is zero.
  • PUSH and POP These are stack instructions. PUSH
    adjusts the stack pointer and adds data to the
    stack while POP retrieves the data and adjusts
    the pointer.
  • CALL Used to execute functions and subroutines.
    Followed by a RETURN instruction for getting
    back.
  • CALL SUBTRACT_THESE
  • MOVE R7,R2
  • .
  • .
  • SUBTRACT_THESE
  • SUB R2,R3
  • RETURN

8
Interrupt Basics
  • Interrupts are triggered when certain events
    occur in the hardware.
  • e.g. when a serial chip has sent data to a
    microprocessor and wants it to read it from its
    pin, it sends an interrupt to the processor,
    usually by sending a signal to one of the
    processors IRQ (interrupt request) pins.
  • On receiving an interrupt, the microprocessor
    stops its current execution, saves the address of
    the next instruction on the stack and jumps to an
    interrupt service routine (ISR) or interrupt
    handler.
  • The ISR is basically a subroutine written by the
    user to perform certain operations to handle the
    interrupt with a RETURN instruction at the end.
    It is a good practice to save register state and
    reset the interrupt in ISRs.
  • ISRs are similar to a CALL except that the call
    to the ISR is automatically made.

9
Interrupt Basics (contd.)
  • The following shows an e.g. of an ISR
  • Task Code ISR
  • ...
  • MOVE R1, R7
  • MUL R1, 5 PUSH R1
  • ADD R1, R2 PUSH R2
  • DIV R1, 2 ...
  • JCOND ZERO, END ISR code comes here
  • SUBTRACT R1, R3 ...
  • ... POP R2
  • ... POP R1
  • END MOVE R7, R1 RETURN
  • ...
  • ...

10
Interrupt Basics (contd.)
  • Saving and Restoring the Context
  • As the above code demonstrated, the task code has
    no idea of the changes taking place in registers
    like R1 or R2 in the ISR.
  • Hence if R1 is modified by the ISR, we might get
    an incorrect final result.
  • Due to limited number of registers, the ISRs and
    task codes usually have to work with same
    registers.
  • To solve this problem it is common practice to
    save the register contents onto the stack (saving
    the context) and restoring them at the end of the
    ISR (restoring the context).
  • This is mandatory to prevent any bugs from
    appearing due to interrupts

11
Interrupt Basics (contd.)
  • Disabling Interrupts
  • Most microprocessors allow programs to disable
    interrupts.
  • In most cases the program can select which
    interrupts to disable during critical operations
    and which to keep enabled by writing
    corresponding values into a special register.
  • Nonmaskable interrupts however cannot be disabled
    and are normally used to indicate power failures
    or other serious event.
  • Certain processors assign priorities to
    interrupts, allowing programs to specify a
    threshold priority so that only interrupts having
    higher priorities than the threshold are enabled
    and the ones below it are disabled.

12
The Shared-Data Problem
  • In many cases the ISRs need to communicate with
    the task codes through shared variables.
  • Fig. 4.4 from Simon shows the classic shared-data
    problem.
  • The code continuously monitors two temperatures
    and sets off an alarm if they are different.
  • An ISR reads the temperatures from the hardware.
  • The interrupt might be invoked through a timer or
    through the temperature sensing hardware itself.
  • Now, consider that the temperatures are 70
    degrees and an interrupt occurs after iTemp0
    iTemperatures0 is executed.
  • The temperatures now become 75 degrees. Hence on
    returning from ISR, iTemp1 will be assigned 75
    and an alarm will be set off even though the
    temperatures were the same.
  • Fig. 4.5 compares the values iTemperatures0 and
    iTemperatures1 directly without making a local
    copy. However as the assembly code for this code
    in Fig. 4.6 shows if an interrupt occurs between
    the two MOVES, this translates into the same
    problem as Fig. 4.4 and the alarm goes off when
    it shouldnt have.

13
The Shared-Data Problem (contd.)
14
The Shared-Data Problem (contd.)
  • Characteristics of the Shared-Data Bug
  • The problem in both the above figures (4.4 and
    4.5) is due to the shared array iTemperatures.
  • These bugs are very difficult to find as they
    occur only when the interrupt occurs in between
    the first 2 MOVE instructions, other than which
    code works perfectly.
  • Solving the Shared-Data problem
  • The problem can be solved by disabling the
    interrupts during the instructions that use the
    shared variable and re-enabling them later.
  • The following modification to Fig. 4.4 (or 4.5)
    solves the problem.
  • while (TRUE)
  • disable() Disable interrupts
  • iTemp0 iTemperatures0
  • iTemp1 iTemperatures1
  • enable() Re-enable interrupts
  • ...
  • Remaining code same as in Fig. 4.4
  • ...
  • In assembly DI and EI are used to disable and
    enable interrupts respectively.

15
  • Atomic and Critical Section
  • A part of a program is atomic if it cannot be
    interrupted. Hence the code between disable() and
    enable() above is atomic.
  • Atomic might also be used for codes that only
    disable interrupts working with the same data.
    Hence if interrupts not working with the
    temperature variable (like pressure, time etc.)
    are left enabled code is still considered atomic
    and free of bugs.
  • Few Examples
  • Consider an ISR that updates iHours, iMinutes and
    iSeconds every second through a hardware timer
    interrupt. The function to calculate the time can
    be written as follows
  • long iSecondsSinceMidnight (void)
  • long lReturnVal
  • disable()
  • lReturnVal
  • (((iHours60) iMinutes) 60) iSeconds
  • enable()
  • return (lReturnVal)
  • A problem in the above code arises when the
    function is called from a critical section that
    has disabled interrupts. The function will
    incorrectly enable interrupts on return. Fig.
    4.10 solves this problem.

16
The Shared-Data Problem (contd.)
  • The volatile Keyword
  • Fig. 4.12 from Simon fixes the shared-data
    problem without disabling interrupts by reading
    the seconds twice.

17
The Shared-Data Problem (contd.)
  • However certain compilers will optimize the code.
    It will read lSecondsToday in one or more
    registers and instead of updating the value
    before saving it to lReturn it will read the
    value from the register every time instead of
    from memory.
  • Some compilers might also remove the while-loop
    during optimization causing the same bug as in
    Figs 4.4 and 4.5.
  • This is prevented by declaring lSecondsToday as
    volatile. This warns the C compiler that the
    variable might change due to interrupts or other
    routines and not to optimize code pertaining to
    it.
  • static volatile long int lSecondsToday

18
Interrupt Latency
  • Interrupt latency is the amount of time taken to
    respond to an interrupt.
  • This depends on several factors-
  • Longest period during which the interrupt is
    disabled
  • Time taken to execute ISRs of higher priority
    interrupts
  • Time taken for the microprocessor to stop the
    current execution, do the necessary bookkeeping
    and start executing the ISR
  • Time taken for the ISR to save context and start
    executing instructions that count as a response
  • The third factor is measured by knowing the
    instruction execution times from the processor
    manual, when instructions are not cached.
  • Make ISRs short
  • Factors 4 and 2 are controlled by writing
    efficient code that are not too long.
  • Factor 3 depends on hardware and is not under
    software control.

19
Interrupt Latency (contd.)
  • Disabling Interrupts
  • Disabling interrupts increases interrupt latency
    so this period should be kept as short as
    possible.
  • Consider the scenario in which two different task
    codes disable interrupts for 125 and 250 µs resp.
  • In this case the max. time taken to start
    executing an ISR will be 250 µs and not 125250
    µs because ISR is started as soon as the
    interrupts are re-enabled in either one of the
    atomic sections.
  • Alternatives to Disabling Interrupts
  • As disabling interrupts increases latency, some
    alternatives might be required in certain
    situations.
  • Fig. 4.15 (Simon) uses two array sets
    iTemperaturesA and iTemperaturesB and a variable
    (fTaskCodeUsingTempB) to ensure that the ISR
    always works with the array not being used by the
    task code.
  • However the while-loop might have to run twice if
    the task checks the wrong array the first time.

20
Interrupt Latency (contd.)
  • Fig. 4.16 uses a queue. The ISR writes data at
    the head of the queue and increments iHead by 2
    while the task code starts reading from the tail
    of the queue.
  • These alternatives are not robust and even minor
    changes might introduce bugs and hence should
    only be used as the last option.
Write a Comment
User Comments (0)
About PowerShow.com