18-348 Lab #8

Fall 2009

Links to all files referenced in the lab and prelab can be found in the Files section at the end of this document.


Pre-Lab 8:

Goal:

Discussion:

Interrupts

There are typically two methods by which a microcontroller can gather data from a device connected to it - polling and interrupts. Polling is the process of periodically reading the device to see if it has any information or if an event has occurred.  Using interrupts is slightly more complicated. Whenever new data is collected or an event occurs at the device, the device can generate a signal to notify the microcontroller that it should read from the device. When the microcontroller receives an interrupt, it suspends its current processing and passes control to a special subroutine called an interrupt service routine (ISR). The ISR is responsible for acknowledging the interrupt (e.g. clearing a flag) and doing some processing (i.e. reading and storing some new data, incrementing a counter, etc.) based on the interrupt before it returns control to the code that was executing when the interrupt occurred.

For the microcontroller used in the lab, there are on-chip peripherals which are interfaced to the CPU through various control registers.  Many of these devices (timers, A/D converters, UARTs, etc) can generate interrupts.  It is also possible to allow external devices to generate interrupts via some of the I/O pins, but this goes beyond the scope of this lab.

When an interrupt occurs, the microcontroller stores the current value of the PC to the stack and transfers control to the ISR.  The location of the ISR code is stored in a table called the interrupt vector table.  The vector table is located at a fixed location in the system.  The actual ISR code can reside anywhere in addressable program memory.  The processor references this vector table to find the starting address of the ISR.  The ISR should always terminate with an RTI instruction, which properly restores the stack and any other register values to the original value before the interrupt occurred. 

For any further information on interrupts, please refer to the lecture notes or Chapter 5 of the MC9S12 data sheet.

Task Scheduling

In this pre-lab, you will answer questions regarding a given schedule.  The following terminology is used in this lab:

Procedure:

In previous labs, you have used the APS12C128 to communicate with hardware devices such as the timer and the serial communications interface (SCI) through polling. In this lab, you will learn how to set-up the chip and these devices so that they can communicate using interrupts.  For parts 1 and 2, determine the correct control register settings.  For part 3, analyze task response times.

Part 1:    Timer Interrupts

Use the interrupt vector table in Section 1.6.1 of the MC9S12 data sheet and the Timer register information in section 15.3.2 of the MC9S12 data sheet.

Complete the following table so that the Timer peripheral:

Register bits
Value
TSCR1: 7
TSCR2: 7
TSCR2: 2:0

Table 1.1:  Timer control register values


Part 2:    UART Interrupts


Use the interrupt vector table in Section 1.6.1 of the data sheet and the SCI register information in section 13.3.2 of the data sheet. Complete the following table so that:

Register Bits
Value
SCIBDH: [4:0]

SCIBDL: [7:0]

SCICR2: 7

SCICR2: 6
SCICR2: 5
SCICR2: 4
SCICR2: 3
SCICR2: 2

Table 2.1:  SCI control register values


Part 3:    Task Scheduling

Complete the following tables and answer the corresponding questions.  In the tables below,  an empty row or column with a "..." symbol indicates you should add as many rows/columns as are appropriate to complete the calculation.

Review lectures 14 and 15 for more details on scheduling theory.

Part 3.1:    Main Loop Schedule

Task # Type Priority Period (ms) Execution Time (ms)
1 main loop n/a n/a 100 ms
2 main loop n/a n/a 150 ms
3 ISR 1 50 ms 3 ms
4 ISR 2 50 ms 3 ms
5 ISR 3 50 ms 6 ms
6 ISR 4 50 ms 6 ms

Table 3.1:  Task Schedule Data

Q1. Compute the worst-case latency for the main loop using the data from Table 3.1.   Fill the iterative values into a table like Table 3.2 below.   Complete enough iterations for the value of the main loop latency to converge.

Iteration 0 1 2 ...
Main loop contribution        
ISR1 latency contribution        
ISR2 latency contribution        
...        
Total latency        

Table 3.2:  Template for main loop latency calculation.

Q2:  The system requirements for a system with the workload in Table 3.1 dictate that tasks 1 and 2 must be executed at least every 500 ms.  Can this requirement be met given your calculations from Table 2?

Q3:  What must the main loop task periods be changed to in order to be schedulable with 10% margin?


Part 3.2:  Non-preemptive ISR

Task # ISR Priority Period (ms) Execution Time (ms)
1 1 50 ms 3 ms
2 2 50 ms 3 ms
3 3 50 ms 6 ms
4 4 50 ms 6 ms
5 5 100 ms 30 ms
6 6 100 ms 30 ms
7 7 100 ms 45 ms
8 8 130 ms 45 ms

Table 3.3:  ISR Task Data for Part 3.2

Q4: Suppose a system has the ISR tasks shown in Table 3.3.  Assume that interrupts are never disabled in the main program and that all ISRs run to completion (e.g. no preemption).
Complete Table 3.4 to show the iterative calculation for the worst-case latency for ISR 6.

Iteration 0 1 2 ...
Worst case lower priority task        
ISR1 latency contribution        
ISR2 latency contribution        
....        
Total latency        

Table 3.4:  Template for ISR6 latency calculation

Q5:  What is the worst-case latency for ISR6?

Q6:  Does the result in question 5 depend on whether or not there is a main-loop (non-ISR code)?  Assume that no part of the (hypothetical) main loop disables interrupts.


Part 3.3:  Non-preemptive ISR with Blocking Tasks

Now assume that there are blocking tasks in the main loop that DO disable interrupts, according to the values given Table 3.5:

Main Loop Task # Blocking Time (ms)
1 45 ms
2 15 ms
3 77 ms

Table 3.5:  Main-loop tasks

Q7: Repeat the computation for worst case latency of ISR6.  Complete Table 3.6 with the iterative values for your solution

Iteration 0 1 2 ...
Worst case lower priority task        
ISR1 latency contribution        
ISR2 latency contribution        
....        
Total latency        

Table 3.6:  Template for ISR6 latency calculation

Q8:  What is the worst-case latency of ISR6 given the blocking tasks in Table 6?

Part 3.4:  Preemptive ISR

For this part, assume that the hardware is capable of preempting an ISR when a higher priority interrupt occurs.  For this part, assume there are no blocking tasks.

Q9: Using the data in Table 3.3 above, compute the worst case latency for ISR6.  Complete Table 3.9 with the iterative values for the computation.

Iteration 0 1 2 ...
Worst case lower priority task        
ISR1 latency contribution        
ISR2 latency contribution        
....        
Total latency        

Table 3.9:  Template for ISR6 latency calculation

Q10:  What is the worst-case latency for ISR6 under this system, assuming preemption.


Hand-in Checklist (90 + 9):

All non-code submissions shall be in a single PDF document.

Part 1:  Timer Interrupts

  1. (5 points) Fill in Table 1.1 above.
  2. (5 points) What is the vector address for the Timer Overflow?
  3. (5 points) What is the name of the register that holds the TOF flag? What action must be performed in the ISR to clear the flag bit?
Part 2:  UART Interrupts
  1. (5 points) Fill in Table 2.1 above.
  2. (5 points) What is the vector address for the SCI?
  3. (5 points) If both transmit and receive interrupts are enabled for the SCI, how do you know which one caused the SCI interrupt?  What action do you perform (and what register is it performed on) to acknowledge a receiver interrupt? (100 words maximum)
  4. BONUS: (3 points) List 2 advantages of interrupts over polling.  This can be two advantages in the general case, not necessarily specific to the SCI or timer interrupts. (100 words maximum)
  5. BONUS: (6 points) Real systems are often a mix of preemptive and non-preemptive tasks. Figure out the worst case latency for the following task mix. We recommend a spreadsheet-type approach or timeline approach rather than an analytic (equation-based) approach, because the math gets complicated. Give the worst case completion time for every task under the following assumptions, and compare each task's completion time to its period. Show all work to receive credit. (So, to receive credit you will give worst case completion times for all five tasks, showing your work.)
    Assumptions:
You must make a reasonable attempt (i.e., be substantially correct) on all five tasks *including the main tasks* to receive any credit for this section. Attempting ONLY the ISR portion of this problem will result in no credit, since that analysis is right out of the course lecture notes.

Blocking time = 4
Task Period (Pi)
Execution Time (Ci)
ISR 1
10
1
ISR 2
15
3
ISR 3
50
8
Main task 4
100
27
Main task 5
200
35

Part 3:  Task Scheduling
  1. (60 points) Complete questions Q1 through Q10

Refer to the LAB FAQ for more information on lab handin procedures and file type requirements.  You MUST follow these procedures or we will not accept your submissions.


Lab 8:

Goals:

Discussion:

In this lab you will build a cyclic executive with two interrupt service routines. The cyclic executive will combine both C code and assembly.  You will implement interrupt functions in both assembly and C.

Interrupts

Interrupts can be used to allow multiple tasks to run concurrently on the chip. The code that executes normally (i.e., once main() has started executing) can be considered a foreground task because it runs continuously. The code in an ISR can be considered a background task because it only executes when an interrupt is received and does not execute again until another interrupt is received. Full-scale operating systems are of course much more complex than this, but for many embedded systems this simple approach to tasking does just fine.

Cyclic Executive and ISRs

In the lab, you will use an oscilloscope to measure the performance of the a system which combines main-loop operations with the interrupt service routines (ISRs).

The program shall perform the following:

You have implemented a majority of this functionality in previous labs.  We encourage you to re-use that code for this lab.

In addition to the behaviors described above, the digital outputs on Port B are used to indicate the activity of the processor.  For example, while the timer overflow ISR, bit 7 of Port B is set high and is set low otherwise.  Refer to the "defines" section of the code to see which bit corresponds to which activity.  The relative brightness and frequency of the LEDs connected to port B gives you a sense of which parts of the code are being executed more often.  In addition to observing them visually, you will use the oscilloscope monitor these outputs with the oscilloscope to make measurements of the program activity.

The oscilloscopes in the lab are HP 54645.  The manual is available here:  HP 54600 Series Oscilloscopes User and Service Guide.

In this lab, you make use of a program called RateSender.  You can get the command-line syntax by running the program with no arguments.  Use Ctrl-C to terminate the program.  Note that the program may consume significant resources on your PC, so you may have to stop it in order to record data or use other programs.

Procedure:

Wiring:

  1. Wire the board for the wiper controller according to Lab #3 Part B.
  2. Wire Port B of the module to the project board LEDs.

Part 1 - Cyclic Executive:

Download the lab 8 skeleton project.  Rename your project folder to lab_8_gXX.  You will modify the C and assembly files to implement the foreground tasks.
  1. Add the wiper controller functionality in assembly code as the main foreground task.  You do not have to modify the main loop.  The main C program calls assembly functions to initialize and execute your wiper controller functionality.  Your foreground task shall have the same requirements as the windshield wiper task from Lab #3 (this means you can re-use code you already have implemented plus changes to meet further requirements).  You may use either the base implementation or the bonus implementation (with intermittent state) as you prefer.
  2. Modify your NOP loop from Lab #3 so that the wiper runs at the specified speed in the requirements.  We have modified the module's bus clock to 8 MHz (this is 4x faster than in Lab #3)
  3. Additionally, your main cyclic executive shall:
Part 2 - Serial Interrupt:

Implement the serial interrupt service routine.  The setup code shall be in C code.  The ISR itself shall be written in assembly. This interrupt will read the most recent byte received by the UART and place it into the byte array sciRxBuf.  This buffer will hold the 8 most recent bytes received by the UART. 

serialSetup( ) is a C function which sets up the UART.  The routine shall meet the following requirements
  1. The UART shall operate at 38400 baud, with no parity enabled, one stop bit, and 8 bit data format.
  2. The UART receiver shall be enabled.
  3. An interrupt shall be generated when a character is received by the UART.
  4. The sciRxBuf array shall be initialized to all spaces.
sci_handle is an assembly interrupt service routine that handles interrupts generated by the UART.  The handler should meet the following requirements:
  1. Upon activation, the ISR shall store the byte value received from the UART in the buffer sciRxBuf. 
  2. The buffer shall store the 8 most recent values received from the UART with the oldest value in the [0] byte.
  3. The ISR shall acknowledge the interrupt by clearing the interrupt flag.
  4. The ISR shall return control to the foreground task after processing of the interrupt has completed.
HINT: Do not forget to add the address of sci_handle to the SCI vector's location.

Note that some manipulation of the data might be required in moving it from the buffer to the UART.

Also note, that the skeleton function has a 5 ms delay at the end of it.  The serial interrupt does not require this delay.  It is used for illustrating timing in Part 4 below.

Once you complete the serial interrupt handler you can test this functionality using the RateSender.exe program.

Part 3 - Timer Interrupt:

Implement the timer interrupt service routine.  Generally, this timer handler will implement much of the same functionality as the stop watch you implemented in Lab #7.  However, note that there are no inputs to the timer.  It is free running and begins as soon as interrupts are enabled.  Additionally, you do not have to actively monitor TCNT as you did in Lab #7.  The timer interrupt automatically executes once TCNT rolls over.

setupTimer( ) is a C function that sets up the timer.  The routine shall meet the following requirements:
  1. The timer shall operate at 0.5 MHz and enable TOI interrupt.
  2. The timer shall stop in freeze and wait modes.
  3. The global timer counter shall be initialized to zero.
  4. Initial LCD output string shall be initialized to "00:00:00"
timerHandler( ) is a C interrupt service routine which executes each time TCNT rolls over. The timer ISR shall meet the following requirements:
  1. The timer ISR shall increment the global timer counter by the appropriate number of fractional seconds.
  2. The timer ISR shall acknowledge the interrupt.
  3. The timer ISR shall update the timer string with the hours, minutes and seconds in the format "HH:MM:SS".
  4. The stopwatch clock shall be accurate within 1 second per 2 minutes elapsed time.
You may re-use any code from Lab #7 you feel to be useful.

Interrupt Questions:
;foreground task
    ...
    ;copy 8 bytes from buf1 to buf 2
    LDX #buf1
    LDY #buf2
    ;INSTR_A
    MOVB 1,X+,1,Y+
    MOVB 1,X+,1,Y+
    MOVB 1,X+,1,Y+
    MOVB 1,X+,1,Y+
;what if an interrupt occurs here?
    MOVB 1,X+,1,Y+
    MOVB 1,X+,1,Y+
    MOVB 1,X+,1,Y+
    MOVB 1,X+,1,Y+
    ;INSTR_B
    ...
;interrupt service routine
ISR_1:
    ...
    LDY #buf1
    LDX #(buf1+1)
    MOVB 1,X+,1,Y+
    MOVB 1,X+,1,Y+
    MOVB 1,X+,1,Y+
    MOVB 1,X+,1,Y+
    MOVB 1,X+,1,Y+
    MOVB 1,X+,1,Y+
    MOVB 1,X+,1,Y+
    LDAA SCIDRL
    STAA 1,Y+
    ...

    RTI

Listing 1.

Listing 1 shows part of a foreground task and part of an ISR.  Consider this code for the following questions:

Q1:  In 30 words or fewer, what is the purpose of the code in ISR_1?
Q2:  If an interrupt occurs where indicated by the comment in the foreground task, will the ISR corrupt the values in the X and Y index registers?  (Assume that the ISR correctly cleans up the stack before calling the RTI).
Q3:  If an interrupt occurs where indicated by the comment in the foreground task, will the copy operation in the foreground task be successful?
Q4:  What instruction would you put in the locations indicated by the comments INSTR_A and INSTR_B to fix any problems identified in questions 2 and 3?

Part 4 - Timing Analysis:

In this section you will perform a timing analysis of your combined cyclic executive and ISR program.  Answer the questions Q5 through Q13 as you perform your analysis.

For all measurements, the wiper controller shall be set to SLOW speed.

Part 4.1
  1. Load the code into module using the USB debugger and run.
  2. Set the wiper controller to slow speed.
  3. Connect channel 1 of the oscilloscope to the TIMER_INDICATOR pin.
  4. Configure the oscilloscope to trigger on the TIMER_INDICATOR pin.  Adjust the settings until you can see the entire positive pulse.  Note that all iterations of the timer ISR are not the same.
  5. Use the Autostore feature of the oscilloscope to simultaneously record multiple pulses to the screen.
  6. Allow the program to run for 3 minutes, then use the cursors to measure the worst case execution time (widest pulse).  Record this as the answer to question 5 below.
  7. Adjust the timebase so that you can see the triggering TIMER_INDICATOR pulse and next pulse after.
  8. Measure the time from between the pulses.  Record this value and answer question 6 below.
  9. Download RateSender.exe.
  10. Connect the module to the PC with a serial cable.
  11. Run RateSender with the message "Hello World" and a send rate of 10 ms.
  12. Use the Autostore feature to record multiple pulses.  Allow the program to run for 3 minutes.  There will now be a small cloud around the second pulse.  Measure the time from the first pulse to the beginning and end of this cloud.  These measurements represent the minimum and maximum times between ISRs.  Record these values and answer question 7 below.

Q5:  What is the worst-case execution time for the timer ISR?

Q6:  How much time elapsed between the two pulses?  Compute the theoretical time that it should take the timer to overflow (based on the timer settings in the code) and compare this to your measured value.

Q7:  What is the minimum time from one timer ISR to the next one?  What is the maximum time?  How do you explain the fact that the maximum time is longer than the timer overflow period.?  How do you explain that the minimum time is shorter than the overflow period?
Hint:  The explanation for the timing of the min/max period compared to the nominal may make more sense in light of your measurement in Question 9 below.


Part 4.2:

In this part, you will observe the effect interrupt task frequency can have on the operation of the main loop.  The procedure for this section assumes you have already loaded the code and connected the serial port as in Part 1.

  1. Run RateSender on the PC with the message "Hello World" and a send rate of 100 ms.
  2. Connect channel 1 of the oscilloscope to the MAIN_LOOP_INDICATOR pin on Port B.
  3. Connect channel 2 of the oscilloscope to the RDRF_INDICATOR pin on Port B.
  4. Configure the oscilloscope as follows:
  5. Stop RateSender.
  6. Use the cursors to measure the amount of time required for several main loop iterations.  Remember that the main loop toggles the indicator bit, so each high / low period represents a single main loop execution.
  7. Compute the average main loop execution time over the number of iterations you measured.  The exact time for your main loop will vary based on your implementation.  Record your measurements and computed results in the appropriate row of Table 4.
  8. Run RateSender.exe on the correct COM port with any message you wish for each of the send rates listed in Table 4 below.  Repeat the measurements from steps 6 fill in Table 4 with the data and appropriate computations.  If the board ceases to function at a certain send rate, put "non-functional" in the main loop time execution time column.

Q8: fill out Table 4 below per above procedure.

Send rate (RateSender argument in ms) Serial receive frequency (Hz) Cursor measurement (s) # of main loops Main loop execution time (s) Apparent effect on the chasing LED.
none (RateSender not running) 0 1.592 5 0.3184 Run normally
1000 1 1.600 5
0.3200 LEDs run more slowly
500          
200          
100          
50          
20          
15          
10          
8          
7          
6          
5          
4          
3          

Table 4 - Main loop execution time measurements.  Some sample values have been filled in to help you understand the meaning of the columns.  Note that the data in the samples is NOT accurate and MUST be replaced with your own data.

Q9: Plot the data for Main loop execution time (col 5) vs the Serial receive frequency (col 2) of the data you recorded in table 4.  Do not plot the rows you marked as non-functional.

Part 4.3:

In this section, you will measure the response time of the receive interrupt.  The procedure for this section assumes you have already loaded the code and connected the serial port as in Part 1.

  1. Connect channel 1 of the oscilloscope to RXD0 pin on the J1 connector.  This is the raw serial data coming from the PC.
  2. Connect channel 2 of the oscilloscope to RDRF_INDICATOR pin of Port B.
  3. Run RateSender with any message you wish and a send rate of 100 ms.
  4. Change the oscilloscope to trigger on the falling edge of RXD0 (channel 1).  This is the beginning of the start bit.  You may need to increase the holdoff on the trigger to stabilize the waveform.
  5. Set the timebase to 200 us/div.  Adjust the delay so you can see the entire serial frame and the beginning of the RDRF_INDICATOR pulse.
  6. Use the cursors to measure the time between the final rising edge in the serial frame (note that this is the beginning of the stop bit) and the beginning of the RDRF_INDICATOR pulse.  Record this value and answer question 10 below.
  7. Measure the length of time the receive ISR takes to execute (this is the width of the pulse).

Q10:  What is the time between the beginning of the stop bit and the beginning of the RDRF pulse?  How does this compare to the width of one baud (symbol) at the baud rate being used in the code?

Q11:  How long does it take the receive ISR to execute?


Part 4.4:

In this section, you will see the effect of blocking tasks on interrupt latency.

  1. Modify lab_8_main.c by uncommenting the "#define BLOCK_DURING_LCD" compiler directive.  With this modification, interrupts are masked during the LCD write sequence, making it a blocking task.
  2. Compile and load the modified program.
  3. Run RateSender with any message you wish at a rate of 50 ms.
  4. Adjust the timebase to 5 ms/div.  Turn on the Autostore feature.  Allow the program to run for 3 minutes.
  5. After 3 minutes, there will be a cloud that represents the various ISR executions.  Measure the time from the beginning of the cloud to the end.  Use this measurement and the value you measured in step 7 of part 4.3 to compute the maximum latency of the receive ISR.  Record this value and answer the questions 12 and 13 below.

Q12:  What is the maximum latency of the receive ISR?  What can you infer about the length of the blocking task from this information?

Bonus: Q13:  The cloud in the measurements you took for part 4.4 indicates that the ISR latency can be any value from a few microseconds to the maximum value you computed in question 6.  Explain why the latency can be any value in this range (as opposed to only being the maximum value). (100 words maximum)


Bonus Part 5 - Mutex Demonstration - Optional:

For this bonus section you're going to implement a very simple timer-tick scheduler and mutex system to write and test a mutex for correct operation. We leave the details up to you, but the point of this exercise is to write a mutex and demonstrate it really works. You must meet the following requirements:
It is expected that version 1 will only work incorrectly sometimes. We strongly recommend you find a way to make it work incorrectly on average once every 30 seconds or so for the sake of a practical demo (faster is better). It is reasonable to run version 2 for 10 times the version 1 problem inter-arrival time to demonstrate that version 2 is operating problem-free under the same circumstances. It is OK to have two separate programs for version 1 and version 2, but a combined program to test both versions is also acceptable.

Bonus: Q14. Describe the general strategy used to create the test system for version 1 and version 2 of the code above (100 words or fewer).

Demo Checklist: (60 + 5 points)

  1. (30 points) Demo your program to the TA with RateSender running at a rate of 100 ms. You must show that both your windshield wiper functionality and UART functionality and timer functionality work correctly (i.e. both will properly process their input if you simultaneously give both types of input).
  2. (30 points) Demo one measurement selected by the TA.
  3. Bonus: (5 points) Optional.  Demo your mutex test program from Part 5.

Hand-in Checklist: (115 + 13 points)

All non-code submissions shall be in a single PDF document.

  1. (5 points) List any problems you encountered in the lab and pre-lab, and suggestions for future improvement of this lab. If none, then state so to get these points.
  2. (50 points) Submit your lab_8_gXX project folder. The coding style sheet must be followed to receive full credit.
  3. (60 points) Answer the questions Q1-12.
  4. Bonus: (3 points) Optional. Answer question Q13.
  5. Bonus: (10 points) Optional. Answer question Q14 and submit your project folder for Part 5. Name the folder lab_8_mutex_gXX.  The coding style sheet must be followed to receive full credit.

Refer to the LAB FAQ for more information on lab handin procedures and file type requirements.  You MUST follow these procedures or we will not accept your submissions.


Hints and Suggestions:

FILES for this lab:

Relevant reading:

Also, see the course materials repository page.