📄 test_cl.c
字号:
/*
*********************************************************************************************************
* uC/OS
* The Real-Time Kernel
*
* TEST FILE
*
* Philips Semiconductors, Inc.
* XA (Large Model)
*
*
* File : TEST_CL.C
*
* Notes: The tick rate is set at 100 Hz. The CPU usage will be high because the tick rate is generally
* between 10 and 100 Hz. If you need a slower tick rate, you will need to modify the code because
* the timer initialization function currently only allows you to have a faster tick rate, not a
* slower one! You can change the tick rate (see OS_TICKS_PER_SEC below) without affecting the
* code (except that the XA Usage % and the number of context switches per second will be different).
*
* This code assumes it is running on the Future Design, Inc. XTEND board.
*
* Once started, uC/OS will be running a total of 14 tasks:
*
* 8 identical tasks. Each task will toggle a bit on the XTEND board's OUTPUT port
*
* 1 task that will blink the XTEND's LED 10 times per second.
*
* 1 task that sends a message to another task though a message queue.
*
* 1 task that waits for messages from the other task (see above).
*
* 1 task that updates a clock every second (MM:SS) that counts up to 99 minutes and 59 seconds.
* The clock then rolls over to 00:00 after 100 minutes.
*
* 1 task that displays information to a 'dumb' terminal. You should thus see the following message
* appear on serial port #0 of the XA:
*
* Philips Semiconductors, Inc.
* XA (Large Model)
* uC/OS, The Real-Time Kernel
*
* XA Usage: PP% #CtxSw: CCCC MM:SS Q: $ BBBB BBBB
*
* PP is the percentage of CPU time used. You should see about 6 to 7% of CPU usage.
* CCCC is the number of context switches that uC/OS performs every second. You should see
* between 494 and 498 context switches per second.
* MM:SS is the clock where 'MM' are the minutes and 'SS' are the seconds.
* $ is the message sent/received. The sender of the message actually cycles through all
* 26 letters of the alphabet ('A' through 'Z').
* BBBB BBBB is the binary state of the XTEND's 8-bit input port. The first bit to the left is the
* most significant bit (i.e. Bit #7). When all headers (in JP4) are in place, the value
* will be '0000 0000'.
*
* 1 task (the last task) is actually executed when no other task is ready to run. In this case,
* uC/OS will keep track of how much of the CPU is being used.
*********************************************************************************************************
*/
/*$PAGE*/
#include "INCLUDES.H"
/*
*********************************************************************************************************
* CONSTANTS
*********************************************************************************************************
*/
#define XA_CRYSTAL_FREQ (ULONG)(24000000L)
#define OS_TICKS_PER_SEC 100
#define TIME_10mS (OS_TICKS_PER_SEC / 100)
#define TIME_50mS (OS_TICKS_PER_SEC / 20)
#define TIME_100mS (OS_TICKS_PER_SEC / 10)
#define TIME_200mS (OS_TICKS_PER_SEC / 5)
#define TIME_500mS (OS_TICKS_PER_SEC / 2)
#define TIME_1S (OS_TICKS_PER_SEC)
#define TIME_2S (OS_TICKS_PER_SEC * 2)
#define TIME_3S (OS_TICKS_PER_SEC * 3)
#define TIME_4S (OS_TICKS_PER_SEC * 4)
#define TIME_5S (OS_TICKS_PER_SEC * 5)
#define TASK_STK_SIZE 128 /* Size of each task's stacks (# of UWORDs) */
#define N_TASKS 20 /* Maximum number of tasks */
#define N_IDENTICAL 8
/*$PAGE*/
/*
*********************************************************************************************************
* VARIABLES
*
* Notes : The size of all task stacks are the same for convenience. uC/OS, however, allow you have
* different stack sizes.
*********************************************************************************************************
*/
far OS_STK_TYPE StartTaskStk[TASK_STK_SIZE];
far OS_STK_TYPE TaskStk[N_IDENTICAL][TASK_STK_SIZE]; /* Stacks for identical tasks */
far UBYTE TaskData[N_TASKS]; /* Argument to pass to each task */
far OS_STK_TYPE LEDTaskStk[TASK_STK_SIZE];
far OS_STK_TYPE QTxTaskStk[TASK_STK_SIZE];
far OS_STK_TYPE QRxTaskStk[TASK_STK_SIZE];
far OS_STK_TYPE ClkTaskStk[TASK_STK_SIZE];
far OS_STK_TYPE DispTaskStk[TASK_STK_SIZE];
far ULONG OSIdleCtrMax; /* Maximum value taken by OSIdleCtr in 1 second */
far UWORD OSCtxSwCtrMax; /* Number of context switches in the past second */
far UBYTE OutPortImage; /* RAM image of output port defined below */
far UBYTE *OutPort; /* 8-bit Output port */
far UBYTE *InPort; /* 8-bit Input port */
far UBYTE CPUUsage; /* CPU usage in % */
far char StatStr[80];
far UBYTE Min; /* Clock (MM:SS), up to 99 minutes and 59 seconds*/
far UBYTE Sec;
far OS_EVENT *QPtr; /* Pointer to a queue */
far void *QTbl[10]; /* Message queue storage area */
far UBYTE QMsg;
/*$PAGE*/
/*
*********************************************************************************************************
* MESSAGE STRINGS
*********************************************************************************************************
*/
code char PhilipsMsg[] = {"\n\n Philips Semiconductors, Inc.\n\r"};
code char XAMsg[] = {" XA (Large Model)\n\r"};
code char uCOSMsg[] = {" uC/OS, The Real-Time Kernel\n\n\r"};
code char StatMsg[] = {"XA Usage: xx% #CtxSw: xxxx xx:xx Q: x xxxx xxxx\r"};
/*
*********************************************************************************************************
* FUNCTION PROTOTYPES
*********************************************************************************************************
*/
void StartTask(far void *data); /* Startup Task */
void Task(far void *data); /* 8 Identical Tasks */
void LEDTask(far void *data); /* LED blinking task */
void MsgPostTaskQ(far void *data); /* Message queue posting task */
void MsgPendTaskQ(far void *data); /* Message queue pending task */
void ClkTask(far void *data); /* Clock Task */
void DispTask(far void *data); /* Display Task */
static void XATmrInit(UBYTE tmr, UWORD freq, UBYTE prio);
static void XAComm0Init(UWORD baud);
static void XAComm0TxStr(far char *s);
static void XAStrCpy(far char *s1, code char *s2);
/*$PAGE*/
/*
*********************************************************************************************************
* MAIN
*
* Description : C main entry point. This function initializes the XA, uC/OS, the 8-bit output port on
* the XTEND board, creates a single task and starts multitasking. Note that the 'ticker'
* is neither initialized nor running at this point. The ticker needs to be initialized by
* the first running task.
*********************************************************************************************************
*/
void main(void)
{
/* -------------------- XA CONFIGURATION ------------------*/
WDCON = 0xF0; /* Disable watchdog ... */
WFEED1 = 0xA5; /* ... Feed watchdog so new config. takes effect */
WFEED2 = 0x5A;
/* Initialize the XA's buses ... */
P0CFGA = 0xFF; /* ... Port 0 configured for PUSH-PULL */
P0CFGB = 0xFF;
P1CFGA = 0xFF; /* ... Port 1 configured for Quasi-bidirectional except */
P1CFGB = 0x0F; /* A3..A0 are PUSH-PULL */
P2CFGA = 0xFF; /* ... Port 2 configured for PUSH-PULL */
P2CFGB = 0xFF;
P3CFGA = 0xFF; /* ... Port 3 configured for Quasi-bidirectional except */
P3CFGB = 0xC0; /* Rd and Wr are PUSH-PULL */
BCR = 0x16; /* WAIT disabled, 16-bit data bus, 20 address lines */
OSInit(); /* Initialize uC/OS, The Real-Time Kernel */
OutPortImage = 0x00; /* Initialize the RAM based port image */
OSTaskCreate(StartTask, (far void *)0, (far void *)&StartTaskStk[TASK_STK_SIZE], 62);
OSStart(); /* Start multitasking */
}
/*$PAGE*/
/*
*********************************************************************************************************
* STARTUP TASK
*
* Description : This function is the first task that executes under uC/OS. The task starts off by
* initializing the 'ticker' which happens to be TIMER #0 of the XA. The task then
* synchronizes itself to the ticker in order to determine how high 'OSIdleCtr' will
* count up to during a one second period. 'OSIdleCtr' is a 32-bit variable that is
* incremented whenever uC/OS is not running any task. The maximum count is saved in
* 'OSIdleCtrMax'.
*
* Next, the startup task will create 9 identical tasks (see description of the
* next function (i.e. 'Task()'). The startup task will then enter an infinite loop that
* basically calculate the CPU usage (in %) once per second and some other stats.
*
* Notes : It is assumed that TIMER #0 is used as the system ticker. Because of this, TIMER #0's
* interrupt should vector to 'OSTickISR()'.
*********************************************************************************************************
*/
void StartTask(far void *data)
{
UBYTE i;
ULONG idle;
data = data; /* Prevent compiler warning */
XATmrInit(0, OS_TICKS_PER_SEC, 3); /* Configure TIMER#0 for tick rate */
XAComm0Init(4800); /* Configure SERIAL#0 for 4800 baud */
OSTimeDly(1); /* Synchronize to ticker */
OSIdleCtr = 0L; /* Clear the idle counter */
OSTimeDly(TIME_1S); /* Wait one second (no other task will run for 1 sec.)*/
OSIdleCtrMax = OSIdleCtr; /* Save maximum idle counter count */
QPtr = OSQCreate((far void **)&QTbl[0], 10); /* Create a message queue with 10 entries */
/* ------------------- TASK CREATIONS ----------------*/
for (i = 0; i < N_IDENTICAL; i++) { /* Create identical tasks */
TaskData[i] = i;
OSTaskCreate(Task, (far void *)&TaskData[i], (far void *)&TaskStk[i][TASK_STK_SIZE], i);
}
OSTaskCreate(DispTask, (far void *)0, (far void *)&DispTaskStk[TASK_STK_SIZE], 20);
OSTaskCreate(LEDTask, (far void *)0, (far void *)&LEDTaskStk[TASK_STK_SIZE], 21);
OSTaskCreate(ClkTask, (far void *)0, (far void *)&ClkTaskStk[TASK_STK_SIZE], 22);
OSTaskCreate(MsgPostTaskQ, (far void *)0, (far void *)&QTxTaskStk[TASK_STK_SIZE], 23);
OSTaskCreate(MsgPendTaskQ, (far void *)0, (far void *)&QRxTaskStk[TASK_STK_SIZE], 24);
OSCtxSwCtr = 0; /* Clear the context switch counter */
OSIdleCtr = 0L;
while (1) {
OS_ENTER_CRITICAL();
OSCtxSwCtrMax = OSCtxSwCtr; /* Get number of context switches in past second */
OSCtxSwCtr = 0; /* Reset statistics counters */
idle = OSIdleCtr;
OSIdleCtr = 0L;
OS_EXIT_CRITICAL();
CPUUsage = 100 - (UBYTE)((idle * 100L) / OSIdleCtrMax); /* Compute % CPU usage */
OSTimeDly(TIME_1S); /* Wait one second until next update of CPU usage */
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* TASKS
*
* Description : Generic task of which there are N_TASKS instances. When the task is first executed, it
* is passed an argument. The argument actually represents the task#.
*
* These tasks will each toggle a bit on the XTEND output port located at 0xB0000.
* The bit being toggled is based on the task#. Task#0 will toggle bit 0 of the output port
* every tick, Task#1 will toggle bit 1 of the output port every 2 ticks, Task #3 will toggle
* bit 2 of the output port every 3 ticks, etc. A RAM image of the port is maintained
* because the port is WRITE only and can thus not be modified through a read-modify-write
* operation. Instead, the port image in RAM is modified and written to the output port.
* The toggle rate is also dependant on the task#. The lower the number, the higher the
* rate.
*********************************************************************************************************
*/
void Task(far void *data)
{
UBYTE taskid;
UBYTE msk;
data = data;
taskid = *(far UBYTE *)data;
msk = 1 << taskid; /* Setup mask to toggle bit based on task# */
OutPort = (far UBYTE *)0xB0000; /* Point to output port (XTEND board) */
while (1) {
OSTimeDly(taskid + 1); /* Delay based on task I.D. */
OS_ENTER_CRITICAL();
OutPortImage ^= msk; /* Change memory port image */
*OutPort = OutPortImage; /* Output changed bit to output port */
OS_EXIT_CRITICAL();
}
}
/*
*********************************************************************************************************
* LED BLINKING TASK
*********************************************************************************************************
*/
void LEDTask(far void *data)
{
data = data;
while (1) {
OSTimeDly(TIME_50mS); /* Delay 50 mS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -