CS452 - Real-Time Programming - Spring 2013

Lecture 14 - AwaitEvent, Task Structure

Pubilc Service Annoucements

  1. Due date for kernel 3: 12 June.
  2. No class Friday, 14 June.
  3. Questions about kernel 3?

Serial I/O

See pdf.

FIFO

Why do FIFOs exist in UARTS?

The Big Blunder

To use the FIFO effectively you must be able to turn off the transmitter & receiver independently.

But look at UARTE in UARTxCtrl

The Little Blunder

`It is assumed that various configuration registers for the UART are not written more than once in quick succession, in order to insure proper synchronization of configuration information across the implementation. Such registers include UART1Ctrl and UART1LinCtrlHigh. ... In between the two writes, at least two UARTCLK periods must occur. Under worst case conditions, at least 55 HCLK periods must separate the two writes. The simplest way to due [sic] this is separate the two writes by 55 NOPs.'

Why does this occur?

Why doesn't anybody care?

Interrupts

Five interrupts in the device

These interrupts are separately enabled and disabled.

  1. Transmit
  2. Receive
  3. Modem status
  4. Receive timeout
  5. Combined

Three inputs to the PIC

  1. Transmit
  2. Receive
  3. Combined

Easy way to use interrupts

Enable only combined; read UART registers to decide what to do.

Think of the receive and transmit parts of the UART as separate state machines


Implementation of Serial I/O

FIFO is assumed to be turned off; buffers are assumed to be in the server.

The simplest way to handle the interrupts is to turn on only the combined interrupt and then look at the registers of the device.

To identify the current interrupt

Read UARTxIntIDIntClr at 0x800[bc]001c

Providing I/O for the terminal

Initialization

  1. Enable RcvRdy, XmitRdy interrupts in UART.
  2. Enable combined interrupt in ICU

Receiving

Notifier RCV_BL on RcvRdy event

  1. Interrupt occurs, AwaitEvent returns with byte.
  2. Notifier sends byte to server
  3. Server replies, Notifier returns to initial state
  4. Server checks GetQ
  5. If ( ! GetQ_Empty )
  6. Else insert byte in RcvQ

When server receives Get request from client

  1. Server checks RcvQ
  2. If ( ! RcvQ_Empty )
  3. Else insert client in GetQ

Transmitting

Transmitting is a little more tricky because two conditions must be met.

  1. Byte available to transmit
  2. Transmit holding register empty

Assume we put conjunction detection in the server

When server receives Put request from client

  1. Is Notifier ready?
  2. If ( Ready ) Reply( notifier, byte ); Reply( client, ... )
  3. Else insert byte in XmitQ; Reply( client, ... )

When server receives Ready request from Notifier

  1. Is XmitQ empty?
  2. If ( Empty ) Mark notifier ready
  3. Else Extract byte from XmitQ; Reply( notifier, byte ); Reply( client )

The Notifier

  1. Enable XmitRdy interrupt
  2. byte = AwaitEvt( XmitRdy )
  3. Disable XmitRdy interrupt in UART
  4. Send( server, ready, byte )
  5. Write byte on UART

This procedure assumes that the transmit bit never resets once it is set. Is this true?

Conjunction detection and buffer could just as easily be in the Notifier

Providing I/O for the train controller

Receiving

As Above

Transmitting

For transmitting three conditions must be set

  1. Byte available to transmit
  2. Holding register empty
  3. CTS asserted

Task Structure

We are supposed to support

int Get( int port )

and

int Put( int port, char c )

These are wrappers for sends to one or more serial servers.

You will probably want something more complex in addition to Get and Put.

How many servers and notifiers?

one server two servers four servers
one

notifier

likely queue

congestion in

server

likely queue

congestion

in notifer

two

notifiers

one per channel?

one per direction?

how should they

be paired?

four

notifiers

certain queue

congestion

in server

likely queue

congestion in

server

best performance,

most tasks

How should we handle a terminal?

Issues

  1. Line editing
  2. Echo -- Either

    Or


Debugging Real-time Programs

The most common set of debugging tools used by experienced programmers is the oldest: printf, grep & stack trace.

Debugging real-time programs, at its base, is just the same as any other debugging, and just the same as empirical science.

  1. Gather data.
  2. Create a model that explains the data
  3. Test the model
  4. If the model is not correct, go to 1.
  5. Remember that the model is ALWAYS provisional: data collected later may invalidate it, no matter how much data has confirmed it.

But real-time programs are harder to debug. Very few programs are entirely free of critical races, which are the worst type of bug, lurking for weeks months or years in seemingly correct code, then appearing when innocuous, believed to be independent code changes occur.

Critical Races

There is no known method for eliminating critical races.

It is, in principle, impossible to test away critical races. Why?

RedBoot

The memory contents are not wiped by reset. Some of the most difficult errors can be detected only by using the contents of memory after a reset. Produce useful results by inserting

    str   pc, <magic location>

many places in your code. Then, with the assistance of a load map, you can find out where you were in which code when the problem occurred.

You can often find out this information by looking at the garbage output that often appears at the bottom of the screen. One set of eight characters is the hex address of the instruction that could not be executed. With a load map and assembly listings you can find the instruction on which the program died.

In RedBoot you can, in principle, trace any of the kernel data structures, but it's extremely arduous to do it.

Breakpoint

What does it do?

How do you get it started?

Breakpoint is a special case of a particular sort of tool that is very common.

Getting information closer to real-time.

Stack Trace

In single-threaded programs this is often the most useful tool.

What is the equivalent of a stack trace in a real-time multi-tasking environment?


Return to: