OS is a simple round-robbin time slice operating system. OS has a fixed number of tasks, eight.
Contents:
File Versions
Files With Links to Source Code
Tar File (http://www.speakeasy.net/~tomdean/c-source/os.tgz)
Makefile Makefile,v 1.6 2002/07/30 22:36:45 tomdean adc.c adc.c,v 1.5 2002/07/31 05:52:16 tomdean cli.c cli.c,v 1.5 2002/07/31 17:29:47 tomdean display.c display.c,v 1.5 2002/07/31 16:50:57 tomdean lcd.h lcd.h,v 1.3 2002/07/31 05:52:16 tomdean main.c main.c,v 1.9 2002/07/31 05:52:16 tomdean os.c os.c,v 1.10 2002/07/31 17:29:47 tomdean os.h os.h,v 1.12 2002/07/31 17:29:47 tomdean rti.c rti.c,v 1.6 2002/07/31 17:29:47 tomdean sci.c sci.c,v 1.7 2002/07/31 17:29:47 tomdean swi.c swi.c,v 1.9 2002/07/31 16:50:57 tomdean task1.c task1.c,v 1.6 2002/07/30 22:36:45 tomdean task2.c task2.c,v 1.6 2002/07/31 05:52:16 tomdean task4.c task4.c,v 1.5 2002/07/31 05:52:16 tomdean task5.c task5.c,v 1.7 2002/07/31 17:29:47 tomdean task7.c task7.c,v 1.5 2002/07/31 05:52:16 tomdean
os.h - System Definitions <Source Code>
- Function Prototypes
- Structures
- Defines
os.c - system things. <Source Code>
- Task init sets up task initial stack.
- Add handler adds an interrupt handler.
- Clear handler sets the specified interrupt handler to dismiss, by setting the opcode to 'rti' and the task to zero.
os.h - system things. <Source Code>
main.c - The main routine. <Source Code>
- Everything starts here.
- Contains the null task.
- Rti is enabled, but, at this time, interrupts are disabled.
- All interrupts are set to dismiss.
- The respective task contexts are connected to the context array.
- Each of the eight tasks are added.
- Interrupt handlers for the sci, rti, and, swi are installed.
- The current task is set to zero, the null task.
- All the timers are set to 0xff for testing.
- Tocks is set to TICKS_PER_TOCK.
- Interrupts are enabled.
- Then, we enter the null task. The null task loops, setting porta, bit 0x20 and clearing it. Makes a good scope point. Some debug/testing things are in between. A null task counter should be added for calculating system time availability.
- A __premain() function is defined at the bottom. This is a work-around for m6811-elf-gcc 3.0.4's __premain() enabling interrupts before we are ready! When linking, __premain() is already defined, so, the library is not searched.
rti.c - rti interrupt handler. <Source Code>
- Context switches and clock.
THIS FUNCTION REQUIRES A SPECIFIC STACK CONFIGURATION. WHEN MAKING CHANGES TO RTI.C, LOOK AT THE .s OR USE 'm6811-elf-objdump -d' TO CHECK FOR STACK PUSH OR SOFT REGISTER USAGE BEFORE THE SOFT REGISTERS ARE SAVED. VIOLATION OF THE STACK CONTENTS WILL CAUSE STRANGE THINGS TO HAPPEN. MOST LIKELY A COMPLETE FAILURE OF OS.- See rti.c for a description of the clockalgorithm.
- Porta, bit 0x80 is set.
- Tocks is decremented, and if zero, it is set to TICKS_PER_TOCK and a context switch is begun.
- The top half of a context switch consists of making the stack have the proper format. See rti.c or swi.c for the stack format.
- An interrupt may occur in the middle of a 'C' statement, at 68hc11 instruction bounaries. Therefore, the rti() function preamble saves some of the context.
- Then, the clock is adjusted. This takes 300 to 320 usec.
- If we are doing a context switch, the sp is pointed to the next task. The stack is unwound and the following rti changes to the next task.
- The context switch takes about 80 usec.
swi.c - syscall. <Source Code>
- May perform a task switch.
THIS FUNCTION REQUIRES A SPECIFIC STACK CONFIGURATION. WHEN MAKING CHANGES TO SWI.C, LOOK AT THE .s OR USE 'm6811-elf-objdump -d' TO CHECK FOR STACK PUSH OR SOFT REGISTER USAGE BEFORE THE SOFT REGISTERS ARE SAVED. VIOLATION OF THE STACK CONTENTS WILL CAUSE STRANGE THINGS TO HAPPEN. MOST LIKELY A COMPLETE FAILURE OF OS.- Syscall() performs an swi, starting the swi() function. Return from the swi() function is by an rti. So, the swi is a synchronous interrupt. Synchronous to the previous code stream. An swi() is a full 'C' statement, so it is not in the midst of a statement. Less of the context is saved than for an interrupt. Therefore, swi() must manipulate the stack, somewhat do it is identical to the interrupt stack.
- Arguments may be passed.
- System operations for the first implementation of swi() will be
- SYS_WAIT_TIMER(n). Wait timer (tocks). A tock is 4.1 msec.
- SYS_STOP(t). Mark task (n) as not ready to run.
- SYS_START(t). Mark task (n) as ready to run.
- SYS_DONE(). This iteration of current task is finished, do a context switch to the next ready task.
- Near future implementations may include
- SYS_SEND(t, m). Send message to task (n).
- SYS_RECV(m). Recveive message.
- (Not Needed) SYS_QUEUE(t, m). Queue mesage to task (n).
- (Not Needed) SYS_DEQUEUE(m). Dequeue message.
sci.c - serial line handler <Source Code>
The SCI handler does both receive and transmit functions for the serial line. The handler is entirely interrupt driven.
When an interrupt happens, the handler first checks for character received and handles that. Then, the transmit buffer is checked. If the buffer is not empty, the next character is sent.
When a character is received, it is put in the receive buffer queue. Some character translations occur. 0x0d is translated to 0x00 and put in the buffer. 0x0a is translated to ox00 and put in the buffer, and, eol is handled.
To transmit the first character is sent and interrupts are enabled.
The sci handler has three routines.
sci().
The sci handler interrupt routine. Handle receive characters first to possibly avoid overrun.
- If not a character received interrupt, goto 7
- get the character from the device. Note: #1 and #2 ack the interrupt
- if 0x0d translate to 0x00, put in the buffer and goto 6
- if 0x0a, translate to 0x00, put in the buffer
- send signal to the cli task
- rti
- get the next tx buffer
- if the char is 0x00, goto 11
- send tha char
- goto 14
- read the scdr to make sure interrupts are ack'ed
- mark the tx buffer as empty
- disable transmitter and related interrupts
- rti
Send().
Called by the os print function, the transmitter is enabled, along with the transmit related interrupts.
- put the buffer in the tx queue
- enable transmitter and transmit related interrupts
- send first char
Sci_init().
Called to initialize the sci device and the sci buffers.
- initialize the sci buffers
- enable receiver and receive related interrupts.
task1.c - task one. <Source Code>
- For now, just send the task number up the sci.
task2.c - task two. <Source Code>
- For now, just send the task number up the sci.
adc.c - task three. <Source Code>
Read each of the adc's and put on row 1 of the lcd. Position of each adc is conteolled by defines in os.h.
gps.c - task four. <Source Code>
- Recognize and count gps messages.
gps.h - defines for gps.c<Source Code>
task5.c - task five. <Source Code>
- For now, just send the task number up the sci.
cli.c - task 6. Command line interpreter. <Source Code>
Parse incomming buffers and pass to the proper handler.
task7.c - task seven. <Source Code>
- For now, just send the task number up the sci.
display.c - task eight. Display task. <Source Code>
Display task. Copy the lcd display buffer to the lcd. There is one buffer for each lcd row. Each task is responsible for formatting its data into the correct lcd buffer at the correct location. Locations are defined in lcd.h
lcd_init() - initialize the lcd display. This takes a very long time, asround 5 msec, so, it is called before interrupts are enabled. Do not call this routine during normal os operation.
_lcd_read_ctlr1
- write 0x30, delay 4.1 msec
- write 0x30, delay 100 usec
- write 0x30, delay 37 usec
- write 0x3c, delay 37 usec
- write 0x08, delay 37 usec
- write 0x01, delay 37 usec
- write 0x06, delay 4.1 msec <-- determined by trial and error, this may be too long.
- write 0x0c, delay 37 usec
_lcd_read_ctlr2
_lcd_write_both
_lcd_write_ctlr1
_lcd_write_ctlr2
_lcd_write_row_1
_lcd_write_row_2
_lcd_write_row_3
_lcd_write_row_4
lcd.h - defines related to the lcd.<Source Code>
Makefile. Build OS. <Source Code>
BE VERY CAREFUL IN CHANGING rti() or swi(). SOME CODE WILL FORCE SAVING SOFT REGISTERS OR MAKING ROOM VOR VARIABLES ON THE STACK. IF THIS HAPPENS, THE CONTEXT STRUCTURE WILL BE VIOLATED AND STRANGE THINGS WILL HAPPEN.
PC |
Pushed by interrupt |
Y |
Pushed by interrupt |
X |
Pushed by interrupt |
D |
Pushed by interrupt |
CCR |
Pushed by interrupt |
_.tmp |
Pushed by rti() Preamble or swi() Code |
_.z |
Pushed by rti() Preamble or swi() Code |
_.xy |
Pushed by rti() Preamble or swi() Code |
_.frame |
Pushed by rti()or swi() Preamble. Moved by swi()
Code |
_.d1 |
Pushed by rti() Preamble or swi() Code |
_.d2 |
Pushed by rti() or swi() Code |
_.d3 |
Pushed by rti() or swi() Code |
_.d4 |
Pushed by rti() or swi() Code |
_.d5 |
Pushed by rti() or swi() Code |
_.d6 |
Pushed by rti() or swi() Code |
_.d7 |
Pushed by rti() or swi() Code |
_.d8 |
Pushed by rti() or swi() Code |
|
|
<-- sp |
BE VERY CAREFUL IN CHANGING rti() or swi(). SOME CODE WILL FORCE SAVING SOFT REGISTERS OR MAKING ROOM VOR VARIABLES ON THE STACK. IF THIS HAPPENS, THE CONTEXT STRUCTURE WILL BE VIOLATED AND STRANGE THINGS WILL HAPPEN.
With all tasks defined as,
while(1) {
port bit = 1
serial send task number
port bit = 0
}
The tasks cycle 1..8 continuously when all tasks remain ready to run. task n runs for 12.2 msec and then a context switch occurs. Control is passed back to task n every 98 msec. The rti task uses about 500 usec for each context switch, and, around 260 usec for each non-context switch interrupt.
Row 1 3.5 msec
Row 2 3.5 msec
Row 3 3.5 msec
Row 4 3.5 msec
Port Signal adapt-11_Pin lcd_Pin portb[7] RS 14 11 portb[6] RW 15 10 portb[5] E1 16 9 portb[4] E2 17 15 portb[3] - 18 - portb[2] - 19 - portb[1] - 20 - portb[0] - 21 -
portc[7] db[7] 42 1 portc[6] db[6] 41 2 portc[5] db[5] 40 3 portc[4] db[4] 39 4 portc[3] db[3] 38 5 portc[2] db[2] 37 6 portc[1] db[1] 36 7 portc[0] db[0] 35 8
This section describes what data is extracted from the GPS NMEA data stream. The GPS sends messages that are not discussed here. Those messages are discarded. The messages discussed contain information that is ignored.
$GPBOD - Bearing, Origin to Destination
$GPGGA - GPS Fix Data
$GPGLL - Geographical
$GPRMB - Generic Navigation Information
$GPRMC - GPS and Transit Specific
$GPRTE - Routes
$GPWPL - Waypoint Location
bearing (t)
bearing (m)
origin need to xref this to a lat/lon
destination need to xref this to a lat/lon
UTC time of position What is the difference from the other UTC, below?
Latitude of fix
latitude direction (N=north, S=south) Use + for N, - for S
Longitude of fix
Longitude direction (W=west, E=east) Use + for W, - for E
Present latitude (degrees and minutes)
Present latitude direction (N=north, S=south) Use + for N, - for S
Present longitude (degrees and minutes)
Present longitude direction (E=east, W=west) Use + for W, - for E
Position valid (A=valid, V=invalid)
Cross Track error (nautical miles)
Direction to steer (L=left, R=right)
Origin waypoint identifier
Destination waypoint identifier
Destination latitude (degrees and minutes)
Destination latitude direction (N=north, S=south) Use + for N, - for S
Destination longitude (degrees and minutes)
Destination longitude direction (E=east, W=-west) Use + for W, - for E
Range from present position to destination waypoint (nautical miles)
Bearing form present position to destination wypoint (degrees, true)
Closing velocity to destination waypoint (knots)
Time (UTC)
Position valid (A=valid, V=invalid)
Latitude at UTC time (degrees and minutes)
latitude direction (N=north, S=south) Use + for N, - for S
Longitude at UTC time (degrees and minutes)
Longitude direction (E=east, W=west) Use + for W, - for E
Speed over ground (knots)
Course over ground or track (degrees, true)
Date (day, month, year)
Magnetic variation (degrees)
Magnetic variation direction ( E=east, W=west) Use - for W, + for E
--------------------
NOTE DIFFERENT CONVENTION --------------------------------^
Total number of messages transmitted
Message number
Message mode
Route identifier
Waypoint identifier
Waypoint identifier
Waypoint Latitude (degrees and minutes)
Waypoint Latitude direction (N=north, S=south) Use + for N, - for S
Waypoint Longitude (degrees and minutes)
Waypoint longitude direction (E=east, W=west) Use + for W, - for E
Waypoint identifier