/*
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel
*
* ROUTINE #6
*********************************************************************************************************
*/
#define _CRT_SECURE_NO_WARNINGS
#include "includes.h"
#include "app_linked_list.h"
#include <time.h> // 时间处理头文件
/*
*********************************************************************************************************
* CONSTANTS
*********************************************************************************************************
*/
#define TASK_STK_SIZE 512 /* Size of each task's stacks (# of WORDs) */
/* 任务优先级 */
#define TASK_START_PRIO 0 //起始任务具有最高优先级
#define TASK_1_PRIO 10 //5个用户任务
#define TASK_2_PRIO 11
#define TASK_3_PRIO 12
#define TASK_4_PRIO 13
#define TASK_5_PRIO 14
#define TASK_DISP_PRIO 25 //负责显示用户任务信息
#define TASK_CLK_PRIO 30 //负责显示系统时间 任务数 CPU利用率
//保存被查询任务的相关信息
typedef struct {
INT32U MyTCBDly;
INT8U MyTCBStat;
INT8U MyTCBPrio;
INT32U MyTCBCtxSwCtr;
INT32U MyTCBCycles;
} TASK_USER_DATA;
/*
*********************************************************************************************************
* VARIABLES
*********************************************************************************************************
*/
OS_STK TaskStartStk[TASK_STK_SIZE]; /* Startup task stack */
OS_STK Task1Stk[TASK_STK_SIZE]; /* MyTask1 task stack */
OS_STK Task2Stk[TASK_STK_SIZE]; /* MyTask2 task stack */
OS_STK Task3Stk[TASK_STK_SIZE]; /* MyTask3 task stack */
OS_STK Task4Stk[TASK_STK_SIZE]; /* MyTask4 task stack */
OS_STK Task5Stk[TASK_STK_SIZE]; /* MyTask5 task stack */
OS_STK TaskClkStk[TASK_STK_SIZE]; /* Clock task stack */
OS_STK TaskDispStk[TASK_STK_SIZE]; /* Display task stack */
FP32 AppCPUUsage; //第2种CPU利用率
INT32U time_idle; //用来计算第2种CPU利用率
OS_TCB tcb_copy; //用来复制被查询任务的TCB
TASK_USER_DATA TaskUserData[5]; //存放5个用户任务的查询信息
APP_TCB AppTCBTbl[128]; //全局APP_TCB数组 含128个块 仿真OSTCBTbl
APP_TCB *AppTCBFreeList; //空闲APP_TCB链头
APP_TCB *AppTCBPrioTbl[64]; //对应64个优先级的指针数组 用来连接APP_TCB双向链表 区别于OSTCBPrioTbl
OS_EVENT *SempFull; // 块跌落通知信号量
OS_EVENT *MsgQ; // 消息队列事件
void *MsgQTbl[20]; // 消息队列存储区
OS_MEM *pMem; // 内存控制块指针
INT8U myMem[10][32]; // 内存分区(10块,每块32字节)
OS_MEM_DATA mem_data; // 内存分区查询数据
/*
*********************************************************************************************************
* FUNCTION PROTOTYPES
*********************************************************************************************************
*/
void TaskStart(void *data);
void MyTask1(void *data);
void MyTask2(void *data);
void MyTask3(void *data);
void MyTask4(void *data);
void MyTask5(void *data);
void TaskClock(void *data);
void TaskDisp(void *data);
void UpdateTaskData(INT8U id);
void DispTaskData(INT8U id);
void InitAppTCBList (void);
int AppTCBInit (INT8U prio, INT32U slice);
void AppSchedRR (INT8U prio);
void AppSchedRR2 (INT8U prio);
/*$PAGE*/
/*
*********************************************************************************************************
* MAIN
*********************************************************************************************************
*/
int main (void)
{
INT8U err;
PC_DispClrScr(DISP_BGND_BLACK); /* 清屏 */
OSInit(); /* 初始化uC/OS-II */
InitAppTCBList(); // 初始化APP_TCB空闲链
time_idle = 0;
PC_ElapsedInit();
// 创建信号量和消息队列
SempFull = OSSemCreate(0);
MsgQ = OSQCreate(&MsgQTbl[0], 20);
// 创建内存分区(10块,每块32字节)
pMem = OSMemCreate((void *)&myMem[0], 10, 32, &err);
if (pMem == NULL) {
PC_DispStr(0, 25, "内存分区创建失败!", DISP_FGND_RED + DISP_BGND_BLACK);
}
OSTaskCreate(TaskStart, (void *)0, &TaskStartStk[TASK_STK_SIZE - 1], TASK_START_PRIO); /* 创建起始任务 */
OSStart(); /* 启动多任务 */
return 0;
}
/*$PAGE*/
/*
*********************************************************************************************************
* STARTUP TASK
*********************************************************************************************************
*/
void TaskStart (void *pdata)
{
char s[40];
INT16S key;
INT8U err;
pdata = pdata; /* 防止编译器警告 */
/* 设置屏幕固定显示区域 */
PC_DispStr( 0, 0, " 实时多任务操作系统uC/OS-II ", DISP_FGND_WHITE + DISP_BGND_RED);
PC_DispStr( 0, 1, " 版权声明: ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 2, " 1.内核源码由Jean J. Labrosse提供 ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 3, " 2.x86-Win32平台移植由Werner Zimmermann提供 ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 4, " ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 5, " ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 6, " CH6 动态内存分配 ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 7, " APP_TCB OS_MEM_DATA ", DISP_FGND_CYAN + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 8, " UserTask 上台次数 Status 上台间隔 TOT Cur_ID addr 总块数 每块大小", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 9, "--------- -------- -------- -------- ----------- --------------------------", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 10, " MyTask1 ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 11, " MyTask2 ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 12, " MyTask3 ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 13, " MyTask4 ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 14, " MyTask5 ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 15, " ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 16, " ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 17, " ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 18, " ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 19, " ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 20, " ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 21, " ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 22, " 总任务数 : 每秒任务切换: CPU利用率1: % 2: % ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 23, " 内核版本 : ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
PC_DispStr( 0, 24, " 当前时间 : <--按‘ESC’键退出--> ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
/* 初始化统计功能 */
OSStatInit();
/* 查询内存分区信息并显示 */
if (pMem != NULL) {
OSMemQuery(pMem, &mem_data);
sprintf(s, "0x%08X", (unsigned int)mem_data.mem_addr); // 显示起始地址
PC_DispStr(62, 8, s, DISP_FGND_BLUE + DISP_BGND_LIGHT_GRAY);
sprintf(s, "%2d", mem_data.nblks); // 显示总块数
PC_DispStr(72, 8, s, DISP_FGND_BLUE + DISP_BGND_LIGHT_GRAY);
sprintf(s, "%2d", mem_data.blksize); // 显示每块大小
PC_DispStr(76, 8, s, DISP_FGND_BLUE + DISP_BGND_LIGHT_GRAY);
} else {
PC_DispStr(62, 8, "未创建内存分区", DISP_FGND_RED + DISP_BGND_LIGHT_GRAY);
}
/* 创建其他任务 */
OSTaskCreate(TaskClock, (void *)0, &TaskClkStk[TASK_STK_SIZE - 1], TASK_CLK_PRIO);
OSTaskCreate(TaskDisp, (void *)0, &TaskDispStk[TASK_STK_SIZE - 1], TASK_DISP_PRIO);
OSTaskCreate(MyTask1, (void *)0, &Task1Stk[TASK_STK_SIZE - 1], TASK_1_PRIO);
OSTaskCreate(MyTask2, (void *)0, &Task2Stk[TASK_STK_SIZE - 1], TASK_2_PRIO);
OSTaskCreate(MyTask3, (void *)0, &Task3Stk[TASK_STK_SIZE - 1], TASK_3_PRIO);
OSTaskCreate(MyTask4, (void *)0, &Task4Stk[TASK_STK_SIZE - 1], TASK_4_PRIO);
OSTaskCreate(MyTask5, (void *)0, &Task5Stk[TASK_STK_SIZE - 1], TASK_5_PRIO);
/* 显示内核版本 */
sprintf(s, "uC/OS-II V%1d.%02d", OSVersion() / 100, OSVersion() % 100);
PC_DispStr(18, 23, s, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
for (;;) {
if (PC_GetKey(&key)) { /* 检测按键 */
if (key == 0x1B) { /* ESC键退出 */
exit(0);
}
}
OSTimeDly(400);
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* TASK #1
*********************************************************************************************************
*/
void MyTask1(void *pdata)
{
INT8U i;
char s[20];
INT32U time1;
pdata = pdata; /* 防止编译器警告 */
for (i = 0; i < 2; i++) { //初始化2个APP_TCB块 依次插入链表AppTCBPrioTbl[10]
AppTCBInit(TASK_1_PRIO, 1); //设置1个时间片
}
while (1) {
time1 = PC_ElapsedStop(1);
PC_ElapsedStart(1);
sprintf(s, "%5.2f", time1/ (FP32)1000000);
PC_DispStr(32, 10, s, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY); //显示上台时间间隔
AppSchedRR2(TASK_1_PRIO); //三级反馈队列
i = APPGetListLen(&AppTCBPrioTbl[TASK_1_PRIO]);
sprintf(s, "%2d", i);
PC_DispStr(42, 10, s, DISP_FGND_YELLOW + DISP_BGND_BLUE);
if (i>0) {
sprintf(s, "%4u", AppTCBPrioTbl[TASK_1_PRIO]->Id);
PC_DispStr(47, 10, s, DISP_FGND_YELLOW + DISP_BGND_BLUE);
} else {
PC_DispStr(47, 10, " ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
}
OSTimeDly(150); /* Wait 150 ticks */
}
}
/*
*********************************************************************************************************
* TASK #2
*********************************************************************************************************
*/
void MyTask2(void *pdata)
{
INT8U i;
char s[20];
INT32U time2;
pdata = pdata; /* 防止编译器警告 */
for (i = 0; i < 3; i++) { //初始化3个APP_TCB块 依次插入链表AppTCBPrioTbl[11]
AppTCBInit(TASK_2_PRIO, 2); //设置2个时间片
}
while (1) {
time2 = PC_ElapsedStop(2);
PC_ElapsedStart(2);
sprintf(s, "%5.2f", time2/ (FP32)1000000);
PC_DispStr(32, 11, s, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY); //显示上台时间间隔
AppSchedRR2(TASK_2_PRIO); //三级反馈队列
i = APPGetListLen(&AppTCBPrioTbl[TASK_2_PRIO]);
sprintf(s, "%2d", i);
PC_DispStr(42, 11, s, DISP_FGND_YELLOW + DISP_BGND_BLUE);
if (i>0) {
sprintf(s, "%4u", AppTCBPrioTbl[TASK_2_PRIO]->Id);
PC_DispStr(47, 11, s, DISP_FGND_YELLOW + DISP_BGND_BLUE);
} else {
PC_DispStr(47, 11, " ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
}
OSTimeDly(120); /* Wait 120 ticks */
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* TASK #3
*********************************************************************************************************
*/
void MyTask3(void *pdata)
{
INT8U i;
char s[20];
INT32U time3;
static INT8U prev_len = 0; // 记录上次队列长度
pdata = pdata; /* 防止编译器警告 */
for (i = 0; i < 5; i++) { //初始化5个APP_TCB块 依次插入链表AppTCBPrioTbl[12]
AppTCBInit(TASK_3_PRIO, 4); //设置4个时间片
}
while (1) {
time3 = PC_ElapsedStop(3);
PC_ElapsedStart(3);
sprintf(s, "%5.2f", time3/ (FP32)1000000);
PC_DispStr(32, 12, s, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY); //显示上台时间间隔
AppSchedRR(TASK_3_PRIO); //按时间片轮转 时间片单位 = MyTask3上台间隔
i = APPGetListLen(&AppTCBPrioTbl[TASK_3_PRIO]);
// 检测是否有新块跌落
if (i > prev_len) {
OSSemPost(SempFull); // 发送信号通知MyTask4
}
prev_len = i;
sprintf(s, "%2d", i);
PC_DispStr(42, 12, s, DISP_FGND_YELLOW + DISP_BGND_BLUE);
if (AppTCBPrioTbl[TASK_3_PRIO] != NULL) {
sprintf(s, "%4u", AppTCBPrioTbl[TASK_3_PRIO]->Id);
PC_DispStr(47, 12, s, DISP_FGND_YELLOW + DISP_BGND_BLUE);
} else {
PC_DispStr(47, 12, " ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
}
OSTimeDly(90); /* Wait 90 ticks */
}
}
/*
*********************************************************************************************************
* TASK #4
*********************************************************************************************************
*/
void MyTask4(void *pdata)
{
INT8U err;
char *msg;
time_t now;
struct tm *tm_info;
char time_str[20];
pdata = pdata; /* 防止编译器警告 */
while (1) {
// 等待块跌落通知
OSSemPend(SempFull, 0, &err);
// 申请内存块
msg = (char *)OSMemGet(pMem, &err);
if (msg == NULL) {
continue; // 内存不足,继续等待
}
// 获取当前时间
time(&now);
tm_info = localtime(&now);
strftime(time_str, sizeof(time_str), "%H:%M:%S", tm_info);
// 格式化消息
sprintf(msg, "APP_TCB跌落 @ %s", time_str);
// 发送消息
err = OSQPost(MsgQ, (void *)msg);
if (err != OS_NO_ERR) {
// 发送失败,释放内存
OSMemPut(pMem, msg);
}
OSTimeDly(70); /* Wait 70 ticks */
}
}
/*
*********************************************************************************************************
* TASK #5
*********************************************************************************************************
*/
void MyTask5(void *pdata)
{
INT8U err;
char *msg;
pdata = pdata; /* 防止编译器警告 */
while (1) {
// 请求消息
msg = (char *)OSQPend(MsgQ, 0, &err);
if (msg != NULL) {
PC_DispStr(4, 17, msg, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
// 释放内存块
OSMemPut(pMem, msg);
}
OSTimeDly(30); /* Wait 30 ticks */
}
}
/*
*********************************************************************************************************
* CLOCK TASK
*********************************************************************************************************
*/
void TaskClock (void *pdata)
{
char s[40];
pdata = pdata; /* 防止编译器警告 */
for (;;) {
sprintf(s, "%3d", OSTaskCtr);
PC_DispStr(18, 22, s, DISP_FGND_YELLOW + DISP_BGND_BLUE); /* Total tasks */
sprintf(s, "%3d", OSCtxSwCtr);
PC_DispStr(39, 22, s, DISP_FGND_YELLOW + DISP_BGND_BLUE); /* Context switch counter */
sprintf(s, "%5.2f", OSCPUUsage);
PC_DispStr(60, 22, s, DISP_FGND_YELLOW + DISP_BGND_BLUE); /* CPU usage */
sprintf(s, "%5.2f", AppCPUUsage * 100);
PC_DispStr(72, 22, s, DISP_FGND_YELLOW + DISP_BGND_BLUE); /* CPU usage 2 */
PC_GetDateTime(s);
PC_DispStr(18, 24, s, DISP_FGND_YELLOW + DISP_BGND_BLUE); /* System time */
PC_DispStr(4, 17, " ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY); //每秒清除消息显示
OSCtxSwCtr = 0; //每秒清零总切换次数
OSTimeDly(OS_TICKS_PER_SEC);
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* DISPLAY TASK
*********************************************************************************************************
*/
void TaskDisp(void *pdata)
{
INT8U i;
pdata = pdata; /* 防止编译器警告 */
while (1) {
for (i = 0; i < 5; i++) { //刷新5个用户任务
DispTaskData(i);
}
OSTimeDly(35); //值过小刷新频率太快 过大不易捕捉状态变化
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* 与TASK_USER_DATA有关函数
*********************************************************************************************************
*/
void UpdateTaskData (INT8U id)
{
INT8U err;
err = OSTaskQuery (id + 10, &tcb_copy);
TaskUserData[id].MyTCBDly = tcb_copy.OSTCBDly;
TaskUserData[id].MyTCBStat = tcb_copy.OSTCBStat;
TaskUserData[id].MyTCBPrio = tcb_copy.OSTCBPrio;
TaskUserData[id].MyTCBCtxSwCtr = tcb_copy.OSTCBCtxSwCtr;
}
void DispTaskData (INT8U id)
{
char s[40];
sprintf(s, "%3d", TaskUserData[id].MyTCBCtxSwCtr);
PC_DispStr(14, (INT8U)(id + 10), s, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
if (0 == TaskUserData[id].MyTCBStat) {
if (TaskUserData[id].MyTCBDly <= 5) {
PC_DispStr(20, (INT8U)(id + 10), " Ready", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
} else {
PC_DispStr(20, (INT8U)(id + 10), " Delayed", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
}
} else if (1 == TaskUserData[id].MyTCBStat) { //等待信号量事件
PC_DispStr(20, (INT8U)(id + 10), " Wait_Sem", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
} else if (4 == TaskUserData[id].MyTCBStat) { //等待消息事件
PC_DispStr(20, (INT8U)(id + 10), " Wait_Msg", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
} else if (8 == TaskUserData[id].MyTCBStat) { //被挂起 等待恢复事件
PC_DispStr(20, (INT8U)(id + 10), "Suspended", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
} else if (16 == TaskUserData[id].MyTCBStat) { //等待互斥信号量事件
PC_DispStr(20, (INT8U)(id + 10), " Wait_Mtx", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
} else {
PC_DispStr(20, (INT8U)(id + 10), " Other", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
}
}
/*
*********************************************************************************************************
* 与APP_TCB有关函数
*
* 1. InitAppTCBList() -- Initialize the free list of APP_TCBs
* 2. AppTCBInit() -- 初始化一个APP_TCB块 并将其插入对应的AppTCBPrioTbl[prio]
* 3. AppSchedRR() -- 在双向链表上实现轮转调度
* 4. AppSchedRR2() -- 在轮转调度基础上实现多级反馈队列
*********************************************************************************************************
*/
void InitAppTCBList (void)
{
INT8U ix;
INT8U ix_next;
APP_TCB *ptcb1;
APP_TCB *ptcb2;
OS_MemClr((INT8U *)&AppTCBTbl[0], sizeof(AppTCBTbl)); /* Clear all the APP_TCBs */
OS_MemClr((INT8U *)&AppTCBPrioTbl[0], sizeof(AppTCBPrioTbl)); /* Clear the priority table */
for (ix = 0u; ix < 128; ix++) { //初始化128个APP_TCB块
ix_next = ix + 1u;
ptcb1 = &AppTCBTbl[ix];
ptcb2 = &AppTCBTbl[ix_next];
ptcb1->Next = ptcb2;
ptcb1->Id = ix; //数组下标是组成ID的一部分
}
ptcb1 = &AppTCBTbl[ix];
ptcb1->Next = (APP_TCB *)0; //最后一个块
AppTCBFreeList = &AppTCBTbl[0]; //空闲APP_TCB链头
}
int AppTCBInit (INT8U prio, INT32U time_quanta)
{
APP_TCB *ptcb;
ptcb = AppTCBFreeList; /* Get a free TCB from the free TCB list */
if (ptcb != (APP_TCB *)0 && ptcb->Id < 1000) {
AppTCBFreeList = ptcb->Next; /* Update pointer to free TCB list */
ptcb->TCBPrio = prio;
ptcb->TCBStat = OS_STAT_RDY;
ptcb->TCBDly = 0u;
ptcb->Next = (APP_TCB *)0; //后向指针清空
ptcb->TQ = time_quanta; //设置时间片
ptcb->TQctr = time_quanta; //设置当前剩余时间片
ptcb->Id += 1000u; //每个新划分TCB的标识由四位数字组成
APPInsertListTail(&AppTCBPrioTbl[prio], ptcb); //将新划分的TCB按优先级插入对应链表
return 1;
}
return 0;
}
void AppSchedRR (INT8U prio)
{
APP_TCB *ptcb;
ptcb = AppTCBPrioTbl[prio];
if (ptcb->TQctr > 0u) {
ptcb->TQctr--;
return;
}
if (ptcb->Next != NULL) {
AppTCBPrioTbl[prio] = ptcb->Next;
ptcb->Next = NULL;
ptcb->TQctr = ptcb->TQ;
APPInsertListTail(&AppTCBPrioTbl[prio], ptcb);
} else {
ptcb->TQctr = ptcb->TQ;
}
}
void AppSchedRR2 (INT8U prio)
{
APP_TCB *ptcb;
ptcb = AppTCBPrioTbl[prio];
if (ptcb == NULL) {
return;
}
if (ptcb->TQctr > 0u) {
ptcb->TQctr--;
} else {
if (ptcb->TQctr != 0u)
return;
AppTCBPrioTbl[prio] = ptcb->Next;
ptcb->Next = (APP_TCB *)0; //后向指针清空
ptcb->TQ = (ptcb->TQ) * 2; //下一级队列时间片翻倍
ptcb->TQctr = ptcb->TQ;
APPInsertListTail(&AppTCBPrioTbl[prio + 1], ptcb);
}
return;
}
/*
*********************************************************************************************************
* STATISTIC TASK HOOK
*********************************************************************************************************
*/
void OSTaskStatHook (void)
{
INT8U i;
for (i = 0; i < 5; i++) { //仅更新用户任务数据 不打印
UpdateTaskData(i);
}
}
/*
*********************************************************************************************************
* TASK SWITCH HOOK
*********************************************************************************************************
*/
void OSTaskSwHook (void)
{
INT32U time;
time = PC_ElapsedStop(0); /* This task is done */
PC_ElapsedStart(0); /* Start for next task */
if ((OSTCBCur->OSTCBPrio >= 10) && (OSTCBCur->OSTCBPrio <= 14)) {
TaskUserData[(OSTCBCur->OSTCBPrio) - 10].MyTCBCycles = time;
}
if (OSTCBCur->OSTCBPrio == 30) {
AppCPUUsage = 1.0 - time_idle / (FP32)1000000;
time_idle = 0;
}
if (OSTCBCur->OSTCBPrio == 63) {
time_idle += time;
}
}
/*
*********************************************************************************************************
* DUMMY HOOKS
*********************************************************************************************************
*/
void OSInitHookEnd()
{
}
void OSTimeTickHook()
{
}
void OSTaskCreateHook(OS_TCB *ptcb)
{
}
void OSTaskIdleHook()
{
//OS_SLEEP();
}在Test.c中修改或补充代码,实现如下功能:
1)使用动态内存完善MyTask4与MyTask5中的消息发送过程。动态内存以及内存控制块指针在全局变量中已有定义:
OS_MEM *pMem;
INT8U myMem[10][32];
请于main函数中完成对动态内存分区的创建。并于MyTask4与MyTask5中恰当位置申请/释放内存块(使用OSMemGet()和OSMemPut()),用以处理消息的装填和清除。
此外,为了使消息内容更有实际意义,我们设定发送消息的条件是:每当有新APP_TCB块跌落至三级反馈队列的最低一级(对应MyTask3的队列),应当通知消息发送者MyTask4将跌落消息连同当前时间一并发给接收者MyTask5。
显然,MyTask3知道何时有新的块跌落。你应当在MyTask3中恰当位置补充代码,当检测到有新块后基于某种方式通知MyTask4。具体通知方法可使用普通信号量,而且此处接近生产者-消费者问题中的Full信号量。
2)输出区多了OS_MEM_DATA栏,用来显示当前使用动态分区的起始地址、总块数和每个块的大小。
基于内存分区查询函数OSMemQuery()可实现这一功能。其原型是:
INT8U OSMemQuery (OS_MEM *pmem, OS_MEM_DATA *p_mem_data)
其中pmem为待查询分区的内存控制块指针,p_mem_data指向了查询后的数据。在全局变量处已有定义:
OS_MEM_DATA mem_data;
你应当在起始任务中合适位置调用OSMemQuery(),并根据查询后的mem_data相关成员变量输出OS_MEM_DATA栏内的信息。
最新发布