CS452 - Real-Time Programming - Fall 2011

Lecture 17 - Debugging, Anthropomorphic Programming

Public Service Annoucements

  1. Due date of kernel 4 (Friday, 28 October)
  2. Saturday November 5, 11.00 to 13.00. Open house for high school students.
  3. Signatures of Getc( ) and Putc( )

Serial I/O

The implementations that follow are samples to show how bytes flow from task to task. They are not the only, and probably not the best possible implementations. They have been chosen because it is easy to see the byte flow in them, or so I hope.

Implementation without FIFO, without Flow Control

Receive

There must be a FIFO receive buffer (probably circular) in the server, and a queue for clients blocked on Getc( )

Interrupt

Kernel

  1. Check for EVENT_BLOCKED Notifier
  2. Read byte from UART
  3. Ready Notifier, returning byte

Notifier

  1. Send byte to server

Server

  1. Receive byte from Notifier
  2. Reply to Notifier
  3. If client queued

    else

Client Getc

Server

  1. If receive buffer not empty

    else

Transmit

There is a FIFO transmit buffer (probably circular) in the server

Interrupt

Kernel

  1. Check for EVENT_BLOCKED Notifier
  2. Ready Notifier

Notifier

  1. Send to server for byte
  2. Write byte to UART

Server

  1. If no byte available, then
  2. Reply byte

Client Putc

Server

  1. If Notifier waiting

    else

  2. Reply `done' to Client

Implementation without FIFO, with Flow Control

Receive

Same as above.

Transmit

There is a FIFO transmit buffer and a CTS state variable

Transmit Interrupt

Kernel

  1. Check for EVENT_BLOCKED Notifier
  2. Disable interrupt in ICU
  3. Ready Notifier

Notifier

  1. Send to server for byte
  2. Write byte to UART
  3. Enable interrupt in ICU

Server

  1. If buffer empty
  2. If !CTS

    else

Client Putc

Server

  1. If Notifier waiting && CTS

    else

CTS Interrupt

Kernel

  1. Check for EVENT_BLOCKED CTSNotifier
  2. Turn off interrupt in UART
  3. Ready CTSNotifier

CTSNotifier

  1. Send CTS toggle message to Server

Server

  1. Reply to CTSNotifier
  2. Toggle CTS
  3. Read UART modem status
  4. while( CTS != UART modem status CTS ) Read UART modem status
  5. If CTS &&Notifier waiting && buffer not empty

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, the appearing when innocuous, unconnected changes occur.

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.

On some types of exceptions RedBoot will attempt to connect with gdb. In such cases it writes a bunch of gibberish on the bottom of the monitor screen. Among that gibberish is the address of the instruction that caused the exception. Using the load map generated by the linker you can find

It is usually pretty easy to figure out which line of C source was responsible for the instruction.

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?

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.

We need methods of getting information closer to real-time.


Anthropomorphic Programming

We all, even most programmers (!), have effective intuitions about human relations

Tasks are independent entities


Return to: