typedef struct {OS_STK:
INT8U OSEventType; /* Type of event control block (see OS_EVENT_TYPE_???) */
INT8U OSEventGrp; /* Group corresponding to tasks waiting for event to occur */
INT16U OSEventCnt; /* Semaphore Count (not used if other EVENT type) */
void *OSEventPtr; /* Pointer to message or queue structure */
INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */
char OSEventName[OS_EVENT_NAME_SIZE]; /* Compile time directive currently has OS_EVENT_NAME_SIZE = 32 */
} OS_EVENT;
#define OS_EVENT_TYPE_UNUSED 0 /* All possible values for OSEventType in OS_EVENT struct */
#define OS_EVENT_TYPE_MBOX 1
#define OS_EVENT_TYPE_Q 2
#define OS_EVENT_TYPE_SEM 3
#define OS_EVENT_TYPE_MUTEX 4
#define OS_EVENT_TYPE_FLAG 5
typedef unsigned short OS_STK; /* Each stack entry is 16-bit wide */
OS_TCB:
typedef struct {
INT32U OSFree; /* Number of free bytes on the stack for a specific task */
INT32U OSUsed; /* Number of bytes used on the stack for a specific task*/
} OS_STK_DATA;
typedef struct os_tcb{
OS_STK *OSTCBStkPtr; //Stack Pointer void *OSTCBExtPtr; //TCB extension pointer OS_STK *OSTCBStkBottom; //Ptr to bottom of stack INT32U OSTCBStkSize; //Size of task stack (#elements) INT16U OSTCPOpt; //Task options struct os_tcb *OSTCBNext; //Pointer to next TCB struct os_tcb *OSTCBPrev; //Pointer to previous TCB OS_EVENT *OSTCBEventPtr; //Pointer to ECB void *OSTCBMsg; //Message received OS_FLAG_NODE *OSTCBFlagNode; //Pointer to event flag node OS_FLAGS OSTCBFlagsRdy //Event flags that made task ready INT16U OSTCBDly; //Nbr ticks to delay task or, timeout INT8U OSTCBStat; //Task Status INT8U OSTCBPrio; //Task Priority (0 = highest) INT8U OSTCBX; INT8U OSTCBY; INT8U OSTCBBitX; INT8U OSTCBBitY; BOOLEAN OSTCBDelReq; //Flag to tell task to delete itself }OS_TCB;
OS_EXT INT8S OSCPUUsage; /* Percentage of CPU used */
*((int *)0x80) = (int)OSCtxSw; /* set up vector to Context Switch (TRAP #0) */
Function Prototype |
Arguments |
Returns |
Notes |
void OSInit(void); Location: src/uC/os_core.c |
none |
nothing |
Call this function first inside your begin()
function. Initializes uC/OS-II and must be called before calling OSStart() |
begin (void) /* SYSTEM ENTRY POINT */
{*((int *)0x80) = (int)OSCtxSw; /* set up vector to Context Switch (TRAP #0) */
OSInit();
.
.
OSStart(); /* away we go ! */
}
Function Prototype |
Arguments |
Returns |
Notes |
void OSStart(void); Location: src/uC/os_core.c |
none |
nothing |
OSStart begins the multitasking. Call this as
a part of your initialization function but make sure that you have called
OSInit() first. |
begin (void) /* SYSTEM ENTRY POINT */
{*((int *)0x80) = (int)OSCtxSw; /* set up vector to Context Switch (TRAP #0) */
OSInit();
.
.
OSStart(); /* away we go ! */
}
Function Prototype |
Arguments |
Returns |
Notes |
void OSStatInit(void); Location: src/uC/os_core.c |
none |
nothing |
If CPU stats are required, this function
must be called. It must be called from the first and only task created.
This first and only task may,in turn, create other tasks once OSStatInit has
been called. |
begin (void) /* SYSTEM ENTRY POINT */
{
*((int *)0x80) = (int)OSCtxSw; /* set up vector to Context Switch (TRAP #0) */
OSInit();
TaskCreate("StartTask",StartTask,StartTask_ID);
OSStart(); /* away we go ! */
}
void StartTask(void *data)
{
ScopeInit(); /* Initialize oscilloscope triggering routine */
TickInit(); /* Start OS ticker, see os/os_cpu_a.s */
OSStatInit(); /* Initialize statistics task */
OSTaskCreateExt(...); /* all clear to call tasks now */
OSTaskCreateExt(...);
.
.
.
OSTaskDel(OS_PRIO_SELF); /* This task only runs once */
}
Function Prototype |
Arguments |
Returns |
Notes |
INT8U OSTaskCreateExt (void(*task)(void*pd), void *pdata, OS_STK *ptos, INT8U prio, INT16U id, OS_STK *pbos, INT32U stk_size, void *pext, INT16U opt ) ; Location: src/uC/os_task.c |
task Pointer to task's code that must be declared as void Task (void *) pdata Pointer to data that is passed to task when it is created ptos Pointer to the top of the task's stack. For stacks that grow down in memory ptos needs to point to the highest valid memory location on the stack. prio Unique priority to assign to this task. The lower the number the higher the priority. id Task's ID number which is not currently used. Set this to the priority of the task. pbos Pointer to the bottom of the task's stack. For stacks that grow downward in memory pbos must point to the lowest valid stack location. stk_size Number of 16 bit entries available on the stack. See typedef of OS_STK in src/uC/os_cpu.h and above. pext Pointer to a user supplied memory location used as TCP extension. User defined location or data structure. opt Options for the task created. Lower 8 bits are reserved for uC/OS-II but applications may use the upper 8 bits for application specific options. Possible uC/OS-II predefined options are: OS_TASK_OPT_STK_CHK Specifies whether stack checking is allowed for the task OS_TASK_OPT_STK_CLR Specifies whether the stack need to be cleared OS_TASK_OPT_SAVE_FP N/A we have no floating point registers on our CPU32 |
One of the following error codes: OS_NO_ERR Function was successful in creating the task OS_PRIO_EXIST A task already exists with that priority. In uC each task must have a unique priority OS_PRIO_INVALID prio is higher than OS_LOWEST_PRIO, currently set to 63 OS_NO_MORE_TCB uC has run out of OS_TCBs to assign |
Stack must be declared as type OS_STK At some point during the execution of the task one of the services offered by uC/OS-II must be called to wait for time to expire, suspend the task or wait for an event like a mailbox or semaphore. Otherwise the task may never cede the processeor and other tasks with lower priorities may never get a time slice. uC/OS-II is not a round robin OS. Consequently, all task must eventually cede for all task to get servicing. Don't assign user tasks priorities 0, 1, 2, 3, OS_LOWEST_PRIO-3, OS_LOWEST_PRIO-2, OS_LOWEST_PRIO-1, or OS_LOWEST_PRIO. These are reserved by uC/OS-II. The other 56 application tasks are therefore available. |
#define TASK_OPT OS_TASK_OPT_STK_CHK + OS_TASK_OPT_STK_CLR
void TaskCreate(char *TaskDesc, void *TaskFunc, INT8U TaskID)
{
INT8U err;
err=OSTaskCreateExt(TaskFunc,
(void *)0,
&TaskStack[TaskID][TASK_STACK_SIZE-1],
TaskID+5,
TaskID,
&TaskStack[TaskID][0],
TASK_STACK_SIZE,
&TaskData[TaskID],
TASK_OPT);
if (!err)
strcpy(TaskData[TaskID].TaskName, TaskDesc);
else
disp_err(err);
}
Function Prototype |
Arguments |
Returns |
Notes |
INT8U OSTaskDel (INT8U prio) ; Location: src/uC/os_task.c |
prio priority number of the task to be deleted. |
OS_NO_ERR Call was successful OS_TASK_DEL_IDLE This value is returned if you attempt to delete the idle task, this is not permitted OS_TASK_DEL_ERR Task to be deleted does not exist. OS_PRIO_INVALID prio is higher than OS_LOWEST_PRIO. OS_TASK_DEL_ISR This value is returned if you attempt to delete a task from an ISR. |
Specify the priority of the task to be
deleted or pass in OS_PRIO_SELF if priority of task is unknown. This task's
code is not actually removed but the task is placed in the dormant state
and can be recreated and made active by calling OSTaskCreate or OSTaskCreateExt.
Be careful when deleting a task that owns associated resources. If a task owns resources like mailboxes, semaphores etc. call OSTaskDelReq() instead to deal with those issues safely. |
void StartTask(void *data)
{
ScopeInit(); /* Initialize oscilloscope triggering routine */
TickInit(); /* Start OS ticker, see src/uC/os_cpu_a.s */
OSStatInit(); /* Initialize statistics task */
LEDQueue = OSQCreate (LEDQueueTbl, 10);
.
.
.
OSTaskDel(OS_PRIO_SELF); /* We don't want the Start ask to run more than once */
}
Function Prototype |
Arguments |
Returns |
Notes |
INT8U OSTaskStkChk (INT8U prio, OS_STK_DATA *pdata); Location: src/uC/os_task.c |
prio priority number of the task about which you want stack information. If the value OS_PRIO_SELF is passed then the stack of the calling task is checked. pdata pointer to a variable of type OS_STK_DATA that is used by the function |
OS_NO_ERR Call was successful OS_PRIO_INVALID prio is higher than OS_LOWEST_PRIO or not equal to OS_PRIO_SELF OS_TASK_NOT_EXIST Specified task does not exist OS_TASK_OPT_ERR this value is returned if the task was created by OSTaskCreate or if OS_TASK_OPT_STK_CHK was not specified when the OSTaskCreateExt call was used. |
Execution time for this task depends on the
size of the stack for each task and is, therefore, nondeterministic. To calculate the total stack size used add .OSFree and .OSUsed together. Currently, all of the stacks in the labs are the same size (= 512 bytes). Don't call this function inside an ISR due to its nondeterministic nature and possible length of time for completion. |
OS_STK_DATA StackData;
INT8U err;
err = OSTaskStkChk(OS_PRIO_SELF,&StackData);
Function Prototype |
Arguments |
Returns |
Notes |
INT8U OSTaskQuery (INT8U prio, OS_TCB *pdata); Location: src/uC/os_q.c |
prio priority number of the task about which you want task information. If the value OS_PRIO_SELF is passed then the stack of the calling task is checked. pdata pointer to a structure of type OS_TCB, which contains a copy of the task's control block |
OS_NO_ERR Call was successful OS_PRIO_ERR Attempt to obtain information from an invalid task OS_PRIO_INVALID prio is higher than OS_LOWEST_PRIO or not equal to OS_PRIO_SELF |
You must allocate an OS_TCB structure before calling this function, and
passing the pointer in as a parameter. Your copy obtains a snapshot of the desired task's control
block. DO NOT modify any of the fields in the OS_TCB control blocks. Reading them is sufficient for the labs in CMPE401. |
OS_TCB task_data;
INT8U err;
err = OSTaskQuery(OS_PRIO_SELF,&task_data);
Function Prototype |
Arguments |
Returns |
Notes |
OS_EVENT * OSQCreate (void **start, INT16U size); Location: src/uC/os_q.c |
start base address of storage area size number of elements in the storage area |
A pointer to the event control block allocated
to the queue is returned if the call succeeds. If it fails a NULL pointer
is returned. |
Always create queues before using them. Generally, queues are created for intertask communication. One task posts a message and another task retrieves it. Otherwise race conditions could result and cause many potential problems if tasks attempt to simultaneously access common resources. |
begin (void)
{
*((int *)0x80) = (int)OSCtxSw; /* set up vector to Context Switch (TRAP #0) */
OSInit();
TaskCreate("StartTask",StartTask,StartTask_ID);
OSStart();
}
void StartTask(void *data)
{
ScopeInit();
TickInit();
.
.
TxQueueA = OSQCreate (TxQueueTblA, FIFO_SIZE);
TxQueueB = OSQCreate (TxQueueTblB, FIFO_SIZE);
.
.
OSTaskDel(OS_PRIO_SELF); /* This task only runs once */
}
Function Prototype |
Arguments | Returns | Notes |
void * OSQPend (OS_EVENT *pevent, INT16U timeout, INT8U * err) ; Location: src/uC/os_q.c |
pevent Pointer to queue from which the message is to be recieved. This is the same pointer that was returned when the queue was created using OSQCreate() timeout Pass in 0 if you want to wait forever for a message. Pass a value in ticks (0 - 65535) to give up on receiving the message after the period has lapsed. The function will return and the task will resume once the number of ticks has expired. err OS_NO_ERR Message was received OS_TIMEOUT Message was not received withing the specified timeout. OS_ERR_EVENT_TYPE pevent is not pointing to a message queue OS_ERR_PEVENT_NULL pevent is a NULL pointer OS_ERR_PEND_ISR This function was called from an ISR and uC/OS-II must suspend the task. To avoid this don't call this function from an ISR. |
If successful OSQPend returns a message sent
by a task and *err contains OS_NO_ERR. If unsuccessful a NULL pointer is
returned and *err contains one of the error codes as specified in the arguments
field. |
Always create queues before using them and don't
call this function from inside an ISR Messages are placed in the queue by one task and retreived by another. Call this function to retrieve possible messages. If multiple tasks are waiting for a message the highest priority task is resumed. |
LedQueueData = *(LED_DATA *)OSQPend(LEDQueue, 0, &err); /* this will block until a queue entry is available */
if (err)
disp_err(err);
Function Prototype |
Arguments |
Returns |
Notes |
INT8U OSQPost (OS_EVENT *pevent, void *msg) ; Location: src/uC/os_q.c |
pevent Pointer to the queue into which the message is deposited. Use the pointer that was returned when the queue was created using OSQCreate() msg Pointer- sized variable that is user defined. Don't post a NULL pointer. |
OS_NO_ERR Message was deposited in the queue. OS_Q_FULL No room in the queue. OS_ERR_EVENT_TYPE pevent is not pointing to a message queue. OS_ERR_PEVENT_NULL pevent is a NULL pointer. OS_ERR_POST_NULL_PTR msg is a NULL pointer. |
Always create Queues before using them and never
pass in NULL pointers as arguments. Use this function to send a message to another task via a previously created queue. If multiple tasks are waiting for a message the highest priority task is resumed. |
void LedBufferPost(char num, char state)
{
INT8U err;
if (LedBufferIndex >=10)
LedBufferIndex=0;
LedBuffer[LedBufferIndex].LedNum = num;
LedBuffer[LedBufferIndex].State = state;
err = OSQPost(LEDQueue, (void *)&LedBuffer[LedBufferIndex++]);
}
Function Prototype |
Arguments | Returns | Notes |
OS_EVENT* OSSemCreate (INT16U value); Location: src/uC/os_sem.c |
value Initial value of the semaphore that can be from 0 - 65536. Pass in 0 to indicate that the resource is not available. |
OSSemCreate returns the created event control
block if the function succeeds. If it fails OSSemCreate returns a NULL
pointer |
Always create semaphores before using them. When creating semaphores the value indicates how many tasks can obtain the semaphore concurrently. Pass in 1 if the semaphore is protecting a single resource (ie. a memory location). If there is more than one resource available (ie. a block of structures that can be assigned) then pass in that number. |
OS_EVENT *TxSemA, *TxSemB, *TxBufferLock;
void StartTask(void *data)
{
ScopeInit();
TickInit();
TxSemA = OSSemCreate(0);
TxSemB = OSSemCreate(0);
TxBufferLock = OSSemCreate(1);
.
.
DuartInit();
OSTaskDel(OS_PRIO_SELF); /* This task only runs once */
}
Function Prototype |
Arguments | Returns | Notes |
void OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *err) Location: src/uC/os_sem.c |
pevent Pointer to the semaphore. This was returned when the semaphore was created with OSSemCreate() timeout Pass in 0 if you want to wait forever for a message. Pass a value in ticks (0 - 65535) to give up on receiving the message after the period has lapsed. The function will return and the task will resume once the number of ticks has expired. err OS_NO_ERR Semaphore is available OS_TIMEOUT Semaphore was not obtained withing the specified timeout. OS_ERR_EVENT_TYPE pevent is not pointing to a semaphore OS_ERR_PEVENT_NULL pevent is a NULL pointer OS_ERR_PEND_ISR This function was called from an ISR and uC/OS-II must suspend the task. To avoid this don't call this function from an ISR. |
nothing |
Always create semaphores before using them. Call this function when a task needs to use a shared resource safely, is waiting for an event,or needs to synchronize its activities with an ISR or a task. Note that this call blocks while waiting for the semaphore to be free. Don't use this function from an ISR use the non-blocking OSSemAccept instead() |
void TxTask1 (void *data) /* send the uppercase alphabet to TxA */
{
char byte;
char err;
while(1)
{
byte=0x41;
OSSemPend(TxBufferLock, 0, &err);
while (byte <= 0x5A)
TxBufferPost(0, byte++);
TxBufferPost(0, CR);
TxBufferPost(0, LF);
OSSemPost(TxBufferLock);
OSTimeDly(64);
}
}
Function Prototype |
Arguments |
Returns |
Notes |
INT8U OSSemPost (OS_EVENT *pevent); Location: src/uC/os_sem.c |
pevent Pointer to the semaphore. This was returned when the semaphore was created with OSSemCreate() |
OS_NO_ERR Semaphore has been signalled or released. OS_SEM_OVF Semaphore counts has overflowed (> 65535). OS_ERR_EVENT_TYPE pevent is not pointing to a semaphore OS_ERR_PEVENT_NULL pevent is a NULL pointer |
Always create semaphores before using them. Calling this function will signal, or release the semaphore so that another task can obtain it. If the value is 0 or greater the value is incremented and the function returns to the caller. |
void TxTask1 (void *data) /* send the uppercase alphabet to TxA */
{
char byte;
char err;
while(1)
{
byte=0x41;
OSSemPend(TxBufferLock, 0, &err);
while (byte <= 0x5A)
TxBufferPost(0, byte++);
TxBufferPost(0, CR);
TxBufferPost(0, LF);
OSSemPost(TxBufferLock);
OSTimeDly(64);
}
}
Function Prototype | Arguments | Returns |
Notes |
void OSTimeDly (INT16U ticks) ; Location: src/uC/os_time.c |
ticks Number of clock ticks to delay the current task. (0 - 65,535) (see OS_TICKS_PER_SEC in configuration file src/uC/os_cfg.h) |
nothing |
Use this function to reschedule a task for a
later time. Calling the function with all parameters set to zero simply returns
to the caller immediately. |
while(1)
{
/* One second = 64 ticks*/
OSTimeDly(64);
}
Function Prototype | Arguments | Returns |
Notes |
void OSTimeDlyHMSM (INT8U hours, INT8U minutes, INT8U seconds, INT8U milli) ; Location: src/uC/os_time.c |
hours Number of hours of delay (0 - 255) minutes Number of minutes of delay (0 - 59) seconds Number of seconds of delay (0 - 59) milli Number of milliseconds of delay (0 - 999). milliseconds are rounded to nearest number of ticks so be careful. Be aware of tick rate when only using milliseconds. If the number of milliseconds passed in is smaller that one tick the delay may not occur at all. |
OS_NO_ERR Call was successful OS_TIME_INVALID_MINUTES Minutes argument is greater than 59 OS_TIME_INVALID_SECONDS Seconds argument is greater than 59 OS_TIME_INVALID_MILLI Milliseconds argument is greater than 999 OS_TIME_ZERO_DLY All arguments are given as zero |
Use this function to reschedule the task for
a later time. Calling the function with all parameters set to zero simply
returns to the caller immediately. |
while(1)
{
LEDValue = *(char *)OSQPend(LEDQueue, 0, &err);
if (err)
disp_err(err);
led_current |= LEDValue;
*LED = led_current;
OSTimeDlyHMSM(0,0,0,50);
led_current &= ~LEDValue;
*LED = led_current;
}