COrnell Miniature ATmel Operating System (COMATOS)

Memory Map

COMATOS uses 144 bytes of data memory, leaving the remaining 368 bytes for user programs. The OS memory is divided into two sections: the general OS memory and the process control blocks. The fields within these memory regions are defined within the file and can be modified if necessary. In addition, the USRBase constant, set to 0xf0, indicates the base address of user memory.

General OS Memory

This region of memory is located in the address range 0x60-0x6f. It is partitioned as follows:

0x04OSTimeout(High Byte)
0x05OSTimeout(Low Byte)
0x06OSMaxTimeout(High Byte)
0x07OSMaxTimeout(Low Byte)
0x08OSGlobalTime(Byte 3-High)
0x09OSGlobalTime(Byte 2)
0x0aOSGlobalTime(Byte 1)
0x0bOSGlobalTime(Byte 0-Low)
0x0cOSCurrPCB(High Byte)
0x0dOSCurrPCB(Low Byte)


This register contains two bit fields which are used during the regular operation of the OS.

OSNumTasks and OSCurrentTask:

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!


When returning from a task using OSReturn, a return code must be specified. 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.

OSTimeout and OSMaxTimeout:

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


At each clock tick, the timer 0 ISR increments this 4 byte value. It will overflow approximately every 49 days.


This field is used internally by many OS calls. 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.


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.


This field is scratch space used by the UART TX empty ISR and should not be modified by the user.

Process Control Blocks

The OS memory contains 8 process control blocks, one for each task. These regions store vital information about the status of a task. Their base address, controlled by the PCBBase constant, is 0x70 by default. 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:

0x00PCBEntryPtr (High byte)
0x01PCBEntryPtr (Low byte)


Stores the address at which the scheduler should begin running this task. This field is set by OSCreateTask. when a task is created. 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.


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.


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.


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.

Questions? Contact Ben Greenblatt