The assembly version, the region of memory is located in the address range 0x60-0x6f. In C, it is placed where the compiler finds it convenient. It is partitioned as follows:
Offset (Assembly) | Type (C) | Field |
0x00 | unsigned char | OSStatus |
0x01 | unsigned char | OSNumTasks |
0x02 | unsigned char | OSCurrentTask |
0x03 | unsigned char | OSReturnVal |
0x04 | unsigned int | OSTimeout(High Byte) |
0x05 | OSTimeout(Low Byte) | |
0x06 | unsigned int | OSMaxTimeout(High Byte) |
0x07 | OSMaxTimeout(Low Byte) | |
0x08 | unsigned long | OSGlobalTime(Byte 3-High) |
0x09 | OSGlobalTime(Byte 2) | |
0x0a | OSGlobalTime(Byte 1) | |
0x0b | OSGlobalTime(Byte 0-Low) | |
0x0c | N/A | OSCurrPCB(High Byte) |
0x0d | OSCurrPCB(Low Byte) | |
0x0e | unsigned char | OSUARTCharCnt |
0x0f | unsigned char | OSUARTTemp |
This register contains two bit fields which are used during the regular operation of the OS.
These fields store the number of tasks which have been created by OSCreateTask and the number of the current task running, respectively. The maximum number of tasks allowed is 8!
OSReturnVal:When returning from a task, a return code must be specified. In the assembly version, tasks return using the OSReturn call. In the C version, the ordinary return
command is used. The system will halt and print the return code used to the UART if any value other than 0 is returned. This feature is useful for debugging purposes.
OSMaxTimeout, which is set by OSInit, specifies the length of time a task is allowed to run before the system assumes that it has crashed. When a task is scheduled, the value stored in OSMaxTimout is copied into OSTimeout. At each clock tick, OSTimeout is decremented by the timer 0 ISR. When OSTimeout reaches 0x0000, the system is halted. Valid values of OSMaxTimeout are in the range 1ms-65535ms
OSGlobalTime:At each clock tick, the timer 0 ISR increments this 4 byte value. It will overflow approximately every 49 days.
OSCurrPCB:This field is used internally by many OS calls in the assembly version. It stores a pointer to the Process Control Block of the task that is currently running. It is updated by the scheduler when a task is run. This field is normally accessed via the OSPCBZ call, which transfers OSCurrPCB to the Z register.
OSUARTCharCnt:In the assembly version, before using the UART for string output, this field must be set with the number of characters to be transfered. It is decremented by the UART TX empty ISR after each character is sent.
OSUARTTemp:This field is scratch space used by the assembly version of the UART TX empty ISR and should not be modified by the user.
The OS memory contains 8 process control blocks, one for each task. These regions store vital information about the status of a task. In the assembly version, their base address, controlled by the PCBBase constant, is 0x70 by default. In the C version, they are formed by structures defined in comatos8515.h, and the compiler selects the best location in memory for them. The blocks are stored in order by process number (e.g. process 1's block is located in memory after process 0's and before process 2's.) Each block is 16 bytes long and is defined as follows:
Offset | C type | Field |
0x00 | Function pointer | PCBEntryPtr (High byte) |
0x01 | PCBEntryPtr (Low byte) | |
0x02 | unsigned char | PCBTimeoutVal |
0x03 | unsigned char | PCBCurrentTime |
0x04 | unsigned char | PCBMessMask |
0x05 | unsigned char | PCBMessSrc |
0x06 | unsigned char | PCBAck |
0x07 | unsigned char | PCBState |
0x08- 0x0f | unsigned char[8] | Mailboxes |
Stores the address at which the scheduler should begin running this task. This field is set by OSCreateTask. when a task is created. In the assembly version, a task can change it's own entry pointer using OSSetEntryPt.
PCBTimeoutVal and PCBCurrentTime:One way to schedule a task is to specify a timeout value using OSCreateTask or OSSetTimeout. When a task is run, it's timeout value (PCBTimeoutVal) is copied into PCBCurrentTime. At each clock tick, the timer 0 ISR decrements the PCBCurrentTime value for every task that has been created by OSCreateTask. When the value reaches 0x00, a task using the timeout feature is eligible to run. To turn off this feature for a given task, set its timeout value to 0x00.
This feature is used to cause tasks to run periodically. To cause a task to be run approximately every N milliseconds, set the value to N.
PCBMessMask and PCBMessSrc:Another way in which to schedule a task is through messaging. Tasks can send one byte messages to one another using OSSendMess. ISRs can send messages using ISRSendMess. When a task receives a message, the bit corresponding to the sender's task number is set in the recipient's PCBMessSrc byte. For example, if process 3 sends process 1 a message, bit 3 is set in process 1's PCBMessSrc byte. When a task reads its message using OSGetMess, the sender's bit in PCBMessSrc is cleared. As an example, if process 1 reads the message send by process 3, bit 3 is cleared in process 1's PCBMessSrc byte. Calling OSGetMessageSrc places the PCBMessSrc byte in a register and clears it in memory. Note that clearing bits in the PCBMessSrc byte is not done automatically when a task is run and must be done using OSGetMess or OSGetMessageSrc.
By setting bits in the PCBMessMask byte, using OSCreateTask or OSSetMessMask, one can specify which tasks are being waited on. For example, by setting the message mask of task 1 to 00000101, this task must wait on messages from tasks 0 and 2. Upon receiving messages from the specified tasks, a process is eligible to be run by the scheduler. Set PCBMessMask to 0xff for any task which is not using this feature.
PCBAck:A task receiving a message can acknowledge that message using this field. The receiving task may call OSSendAck to acknowledge a message. This call sets the bit corresponding to the message recipient's task number in the sender's PCBAck byte. For example, upon receiving a message from task 3, task 1 can send an acknowledgement which sets bit 1 in task 3's PCBAck byte.
PCBState:Many tasks will need to store some sort of state information between successive runs. For example, a debouncing task for the keyboard will need to specify whether a new key was pressed on the last run of the debouncer. Because registers are not guaranteed to be preserved between runs of a task, the PCBState byte is available to the user. The state value can be set using OSSetState and read using OSGetState.
Mailboxes:Each task has 8 mailboxes, corresponding to the 8 tasks allowed in the system. A message is placed in the recipient task's mailbox in the location corresponding to the sender's task number. For example, if task 3 sends a message to task 1, the message is placed in byte 3 of task 1's PCB. The contents of the mailboxes can be retrieved using OSGetMess.