18-348 Lab #8
Spring 2015
NOTE: The oscilloscopes in the lab do not have an "autostore" feature. Instead they have an "infinite persistence" display feature that has the same functionality, so be sure to turn on infinite persistence when the lab asks for autostore.
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:
- To learn about hardware interrupts on the APS12C128.
- To learn about task scheduling techniques for embedded systems.
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:
- Period - this is the maximum amount of
time between the beginning of one execution of a task and the beginning of the
next execution of that same task.
- Execution time - this is the amount of
time required for one iteration of the task to execute.
- Blocking task - a task during which
interrupts are disabled.
- Margin - expressed in terms of
percentage, this means that the worst-case execution time is that many percent of the period. E.g. a loop whose worst-case execution time is 90 ms and whose period is 100 ms has a 10% margin:
(1 - (90/100))=0.10
or alternately: 10 ms spare time out of 100ms is a 10% margin.
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:
- is enabled
- operates at 0.5 MHz
- interrupts the chip whenever TCNT overflows (i.e., changes from 0xFFFF to
0x0000).
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:
- the UART transmitter is enabled
- the UART receiver is enabled
- the UART operates at 9600
- the UART interrupts the chip whenever it receives a byte of data.
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, if anything, must the main loop task periods be changed to in order to be schedulable with at least 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
- (5 points) Fill in Table 1.1 above.
- (5 points) What is the vector address for the Timer Overflow?
- (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
- (5 points) Fill in Table 2.1 above.
- (5 points) What is the vector address for the SCI?
- (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)
- 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)
- 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:
- Assume that the main tasks are run using a prioritized preemptive operating
system with zero task switch overhead and an infinitely fast timer tick. (This
means that if a high priority task becomes ready to run, it runs immediately
subject only to blocking time and ISR effects.)
- ISRs are prioritized in the usual way and run to completion (interrupts
remain masked during the entirety of an ISR).
- Lower task and ISR number mean higher priority.
- All times are in msec.
- State any other reasonable assumptions you need to make to get a solution.
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
- (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:
- To implement a foreground and background task using interrupts and the SCI.
- Observe and record the program timing related to interrupts and interrupt
service routines.
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:
- Execute a cyclic executive (main loop) in C
which shall:
- Display time and current serial data on the LCD.
- Display the wiper controller output (from Lab
#3) on the bar-graph LED.
- Use the timer overflow interrupt to keep track
of time and format the current time in human readable format.
- Use the SCI interrupts to received and store
data from the UART.
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 is executing, 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 Agilent Technologies DSO6012A. The manual is available
here: Agilent 5000/6000/7000 Series Oscilloscopes User 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:
- Wire the board for the wiper controller according to Lab #3 Part B.
- 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.
- 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.
- Complete the assembly function called wiper_init( ). This function
shall execute any initializations required for the wiper controller.
- Complete the assembly function called wiper_main( ). This function
shall implement one
iteration of the state loop of your wiper controller.
- 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)
- Additionally, your main cyclic executive shall:
- Update the LCD display with the 8 most recent values received by the UART
on the first line of the LCD.
- Update the LCD display with the timer string on the second line of the
LCD.
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
- The UART shall operate at 38400 baud, with no parity enabled, one stop bit,
and 8 bit data format.
- The UART receiver shall be enabled.
- An interrupt shall be generated when a character is received by the UART.
- 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:
- Upon activation, the ISR shall store the byte value received from the UART
in the buffer sciRxBuf.
- The buffer shall store the 8 most recent values received from the UART with
the oldest value in the [0] byte.
- The ISR shall acknowledge the interrupt by clearing the interrupt flag.
- 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 UART to the buffer.
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:
- The timer shall operate at 0.5 MHz and enable TOI interrupt.
- The timer shall stop in freeze and wait modes.
- The global timer counter shall be initialized to zero.
- 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:
- The timer ISR shall increment the global timer counter by the appropriate
number of fractional seconds.
- The timer ISR shall acknowledge the interrupt.
- The timer ISR shall update the timer string with the hours, minutes and
seconds in the format "HH:MM:SS".
- 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
- Load the code into module using the USB debugger and run.
- Set the wiper controller to slow speed.
- Connect channel 1 of the oscilloscope to the TIMER_INDICATOR pin.
- 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.
- Use the Autostore feature of the oscilloscope to simultaneously record
multiple pulses to the screen.
- 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.
- Adjust the timebase so that you can see the triggering TIMER_INDICATOR
pulse and next pulse after.
- Measure the time from between the pulses. Record this value and
answer question 6 below.
- Download RateSender.exe.
- Connect the module to the PC with a serial cable.
- Run RateSender with the message "Hello World" and a send rate of
10 ms.
- 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.
- Run RateSender on the PC with the message
"Hello World" and a send rate of 100 ms.
- Connect channel 1 of the oscilloscope to the
MAIN_LOOP_INDICATOR pin on Port B.
- Connect channel 2 of the oscilloscope to the
RDRF_INDICATOR pin on Port B.
- Configure the oscilloscope as follows:
- Set the timebase to 200ms/div.
- Set the trigger to trigger on channel 1.
Set the trigger level so the waveform is stable.
- Set the vertical setting for channel 1 and 2 so
you can see both waveforms clearly (unless RateSender is running, you will not
observe anything on channel 2).
- If the waveform is not stable (or the main loop
period is changing too quickly), you may need to use a single trigger (rather
than letting the oscilloscope run).
- Stop RateSender.
- 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.
- 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.
- 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.
- Connect channel 1 of the oscilloscope to RXD0
pin on the J1 connector. This is the raw serial data coming from the PC.
- Connect channel 2 of the oscilloscope to
RDRF_INDICATOR pin of Port B.
- Run RateSender with any message you wish and a
send rate of 100 ms.
- 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.
- 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.
- 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.
- 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.
- 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.
- Compile and load the modified program.
- Run RateSender with any message you wish at a
rate of 50 ms.
- Adjust the timebase to 5 ms/div. Turn on
the Autostore feature. Allow the program to run for 3 minutes.
- 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:
- Version 1 of the code shall have a shared value that you demonstrate to
work incorrectly due to lack of a mutex.
- Version 2 of the code shall be identical to version 1 except for use of a
mutex, and shall work correctly.
- An automated test program shall be used to demonstrate that version 1 works
incorrectly and version 2 works correctly.
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)
- (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).
- (30 points) Demo one measurement selected by the TA.
- 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.
- (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.
- (50 points) Submit your lab_8_gXX project folder. The
coding style sheet must be followed to
receive full credit.
- (60 points) Answer the questions Q1-12.
- Bonus: (3 points) Optional. Answer question Q13.
- 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:
- The MC9S12 datasheet has a typo. The register diagram for TSCR1 is
incorrectly labelled as TSCR2.
- Don't forget to initialize the SCI interrupt vector -- that
"TODO" is near the end of the program file
FILES for this lab:
Relevant reading:
Also, see the course materials
repository page.
Change notes for 2015: