Operating Systems for Embedded Computing (2007) - lab1

Operating Systems for Embedded Computing

Lab Assignment 1 - The Higher Striker Experiment

This lab assignment is about programming the real-time control experiment "Higher-Striker". The experiment consists of a tube of glass surrounded by 7 electromagnets. In the experiment an iron cylinder has to be accelerated by switching the magnets on and off in an adequate order. Position information can be aquired from light barriers among the tube. The experiment relies on a dual-ported FIFO memory to buffer experiment data. Hard deadlines of the control software for buffer refill can be configured by varying the used buffer size from 0 to 255. Because of the sampling frequency of 38,4 KHz the max. deadline of the controlling task is 6 ms. Because of the high speed of the cylinder this control delay caused by the buffer must be reduced.

The experiment hardware is connected to a X86-PC running Windows Ce.NET 4.2 as operating system. The experiment hardware is connected via the parallel port interface. Details about the architecture and programming of the parallel port interface can be found here. The parallel port can be programmed using memory mapped I/O via 3 registers namely data, control, and status register. On the experiment they are configured as follows:

0x03BC data register
0x03BD status register
0x03BE control register

The following picture shows the layout of the experiment's control hardware. On the bottom of the picture you can see the three 8-Bit lines of the parallel port, which are conntected to the control PC. The data lines are directly connected to the data pins of the dual-ported FIFO memory chips.

circuit diagram of HDL hardware

The lines of the status line, shown in the middle of the picture, are connected to (counting the bits from 0 to 7):

bit 3 full flag of light barrier buffer
bit 4 empty flag of light barrier buffer
bit 5 generell hardware error flag
bit 6 half full flag of light barrier buffer
bit 7 empty flag of magnet buffer

As an example the empty flag of the light barrier buffer can be checked like this: if((IO.ReadByte(0x03BD) & 0x10) == 0). Unfortenately some of the FIFO-flags are inverted. The following list explains the coding of the buffer flags (special thanks to M.-P. Schapranow)

MS_EMPTY: 0 => is empty, 1 = is not empty;
LS_HALFFULL: 0 => is not half-full, 1 => is half-full;
HW_ERROR: 0 => there is an error, 1 => there is no error;
LS_EMPTY: 0 => is not empty, 1 => is empty;
LS_FULL: 0 => is not full, 1 => is full;

Because of the restricted number of bits, the control line is connected to a demultiplexer, providing access to the control pins of the FIFO-buffers and the frequency generator (timer). In order to access e.g. the READ_ENABLE-pin of the magnet FIFO buffer, it must be selected via the demultiplexer and the data line conntected to Pin 0 must be programmed in parallel. The following table shows the coding of the multiplexer:

0x02 RESET pin of both FIFO chips
0x0C READ_ENABLE pin of light barrier buffer
0x06 WRITE_ENABLE pin of magnet buffer
0x00 frequency generator (timer) stop
0x0E frequency generator (timer) start

As an example the RESET-pin can be selected by: IO.WriteByte(0x03BE, 0x02 | DATA) . DATA can be 0 or 1 and causes a HIGH or LOW voltage on the pin. All pins can be triggered by generating a rising edge in the voltage signal. 

The experiment data is sampled synchronously with a frequency of 38,4 kHz into the dual-ported FIFO memory. The data can be read/writen asynchronously via the parallel port by sending control signals via the control line and reading/writing the data register. Reading and writing is indicated by raising the voltage of the READ_ENABLE / WRITE_ENABLE-pin of the dual-ported memory chip. The technical specification of the chip can be found here. Please read the specification carefully and understand the functioning of the chip.

In order to control the experiment correct values must be inserted into the magnet buffer, while content of the light barrier buffer must be evaluated. During start-up the two memories must be reset as described in the chip specification. Afterwards initial values must be stored in the magnet buffer. After the start of the timer, data from the magnet buffer is transfered to the magnets, while in parallel information of the light barriers is sampled into the light barrier buffer. The control program must continously read/write new data to/from the memories. The buffers must never run empty. Otherwise the experiment run will fail, while false data is send to the magnets. Depending on the number of initially provided data in the magnet buffer, the memory must be refilled slower or faster. For example an initial buffer size of 10 causes a deadline of 0,26 ms for buffer refill. The higher the initial buffer size is, the higher the deadline, but on the other hand the control delay is higher as well.

The magnets among the tube are numbered and coded as follows (the provided values must be written into the buffers) (only one magnet can be enabled at a time):

0x00 No magnet enabled
0x02 magnet 1 enabled (top of tube)
0x04 magnet 2 enabled
0x06 magnet 3 enabled
0x08 magnet 4 enabled
0x0a magnet 5 enabled
0x0c magnet 6 enabled
0x0e magnet 7 enabled (bottom of tube : should be enabled first)

The light barriers are positioned in the middle of two magnets with a distance of 18 cm and coded as follows:

0x00 no light barrier enabled
0x01 light barrier 1 enabled (top of tube)
0x02 light barrier 2 enabled
0x04 light barrier 3 enabled
0x08 light barrier 4 enabled
0x16 light barrier 5 enabled
0x32 light barrier 6 enabled (bottom of tube)

The experiment can be accessed via the Distributed Control Lab. In the lab a prototype of the Real-Time.Net framework is installed, allowing to implement the control application in C#. In order to develop a control application you should read about the language C# first. Introductions to C# can easily be found in the Internet. C# is quite similar to Java.

In this lab you have to implement a control application that shots the cylinder to the top of the tube. We provide a starting point for the implementation of the controller. In labframe1.cs you can find a frame for a control application. In the code you can find 3 classes, nameley HDLAccess, HDLPerform, HigherStrikerController. HDLAccess provides basic I/O operations such as reading one entry from the light barrier buffer, writing one entry to the magnet buffer, starting/stopping the timer, resetting the memories and reading the status line. The class uses the method ReadByte and WriteByte, which are implemented nativily and are provided in the experiment setup. HDLPerform provides a higher level of abstraction. There are methods for initializing the buffer with an array of entries, and most importent the method Perform. This method write one entry to the magnet and reads one entry from the light barriers, keeping the number of read/written bytes synchronized. Finally the class HigherStrikerController contains the control algorithm. The controller logic uses the methods of the class HDLPerform. You can use this kind of abstraction for implementing the algorithm, but you can also design your own control application.

  1. Implement the neccessary logic to reset the buffers and start/stop the timers.
  2. Start with a simple programm, evaluating the bits of the status register. Write a program that resets the buffers, reads the status byte, starts the timer, waits and finally reads the status byte again. Compare the changed bits of the read status byte and explain the changes.
  3. Implement funcrtions for reading/writing data from/to the buffers. (Implement HDLPerform)
  4. The next step is to implement an algorithm, that enables the first magnet for 900 time units. Initialize the buffers with HDL.MS7 and implement a main-loop that fills the missing entries in the buffer, after the timer has been started. The cylinder should jump about 25 cm. Implement the main-loop of the control algorithm by executing HDLPerform as long as there are entries in the light barrier buffer. Use the status register to check the empty flag of the light barrier buffer. If the buffer is empty recheck the empty flag using sleepy wait:
    while(buffer emtpy)
    // checkStatus
    Make sure that there is no error condition at the other flags (e.g. empty flag of magnet buffer is on). Please write only 0 to the magnet's buffer until you are sure that the main-loop-algorithm is working. For debugging the can use the Console.WriteLine() methods. But be aware that you are using a prototype compiler. Not all versions of Console.WriteLine() are implemented. Remind that the usage of Console.WriteLine causes unpredictable timely behavior. Write debug output at the end of the experiment run.
    Be aware that there is a watch dog running in the experiment-PC that reboots the computer if the watch dog is not signalled for 5 sec. Don't use busy wait anywhere! After a reboot you will not get any debug output.
  5. Evaluate the bits of the read values from the light barriers. At what times does the value change if you shoot the cylinder up as described in step 5. ?
  6. Implement an algorithm that accelerates the cylinder using position information from the light barriers. Please think about the physics of the experiment first. Consider an accelerated movement including gravity.
  7. Have fun! And please ask if you have any problems!

It is also possible to implement the controal algorithm in C/C++. In order to do that select the Higher-Striker experiment in the Web-interface and input your C-code instead of C#-code. You only must include a comment including the string #usec# to configure the usage of the C-compiler. On the experiment-PC Windows Ce.Net 4.2 is installed as operating system. You can use most the provided operating system functions and all functions from the standard C-library. The header file HIO.h is available on the experiment-PC as well. You can use all defined constants in your code by including this header-file. There is also a C frame code provided: HDLFrame.c.
Some hints for the mathematical calculations.

created by Andreas Rasche