?? 消息隊列.c
字號:
/**********************************************************************************************************
*
* 電子科技大學嵌入式軟件工程中心 版權所有
*
* Copyright (C) 2007 UESTC ESEC
*
**********************************************************************************************************/
/**********************************************************************************************************
* 目的:
* 這個程序演示基本的消息隊列。程序啟動設計了6個普通應用任務以及一個控制任務TAC,等待消息的任務總是按照優先級的高低來決定獲得
* 消息的順序,實現消息隊列的使用。
**********************************************************************************************************/
#include "../ucos/includes.h"
#include "../bsp/Uart.h"
extern T_UART_PORT uartPort0;
extern void ucBsp_Init(void);
extern void Timer_Start(void);
extern void CPSR_Init(void);
/*
*********************************************************************************************************
* CONSTANTS
*********************************************************************************************************
*/
#define TASK_STK_SIZE 512 /* Size of each task's stacks (# of WORDs) */
#define N_TASKS 3 /* Number of tasks which wait for queue1 */
/*
*********************************************************************************************************
* VARIABLES
*********************************************************************************************************
*/
OS_STK TaskStk1[N_TASKS][TASK_STK_SIZE]; /* Tasks stacks */
OS_STK TaskStk2[N_TASKS][TASK_STK_SIZE];
OS_STK TaskStartStk[TASK_STK_SIZE]; /* Startup task stack */
OS_STK TaskConStk[TASK_STK_SIZE];
//OS_STK TaskQueryStk[TASK_STK_SIZE];
INT8U TaskData1[N_TASKS]; /* Parameters to pass to each task */
INT8U TaskData2[N_TASKS];
OS_EVENT *q1; /* 2 queue */
OS_EVENT *q2;
void *Msg1[6]; /* 2 arry for msg */
void *Msg2[6];
/*
*********************************************************************************************************
* FUNCTION PROTOTYPES
*********************************************************************************************************
*/
void Taskq1(void *pdata); /* Function prototypes of taskq1s */
void Taskq2(void *pdata); /* Function prototypes of taskq2s */
void TaskStart(void *pdata); /* Function prototypes of Startup task */
void TaskCon(void *pdata); /* Function prototypes of Control task */
void TaskQuery();
static void TaskStartCreateTasks(void);
void TaskQuery(void);
/*
*********************************************************************************************************
* MAIN
*********************************************************************************************************
*/
int main (void)
{
//板級初始化
ucBsp_Init();
//open the interrupt bit 'I'
CPSR_Init();
//Initialize uC/OS-II
OSInit();
Uart_PutString(uartPort0,"\t本程序演示uC/OS-II消息隊列管理的基本思想和策略: ");
Uart_PutLine(uartPort0,"程序啟動設計了6個普通應用任\n\r務以及一個控制任務TAC,等待消息的任務總是按照優先級的高低來決定獲得消息的順序,實現消息\n\r隊列的使用");
Uart_PutString(uartPort0,"請按任意鍵繼續......");
Uart_GetChar(uartPort0);
Uart_PutLine(uartPort0,"");
//建立消息隊列
q1 = OSQCreate(&Msg1[0],6);
q2 = OSQCreate(&Msg2[0],6);
OSTaskCreate(TaskStart, (void *)0, &TaskStartStk[TASK_STK_SIZE - 1], 0);
//Start multitasking
OSStart();
return 1;
}
/*
*********************************************************************************************************
* STARTUP TASK
*********************************************************************************************************
*/
void TaskStart (void *pdata)
{
pdata = pdata;
Timer_Start();
TaskStartCreateTasks();
OSTaskSuspend(OS_PRIO_SELF);
}
/*
***************************************************************************************************************
* CREATE TASKS
***************************************************************************************************************
*/
void TaskStartCreateTasks (void)
{
INT8U i;
//Create N_TASKS+N_TASKS identical tasks
for (i = 0; i <N_TASKS; i++)
{
TaskData1[i] = i;
OSTaskCreate(Taskq1, (void *)&TaskData1[i], &TaskStk1[i][TASK_STK_SIZE - 1], i+1);
}
for (i = 0; i <N_TASKS; i++)
{
TaskData2[i] = i;
OSTaskCreate(Taskq2, (void *)&TaskData2[i], &TaskStk2[i][TASK_STK_SIZE - 1], i+4);
}
//Create control tasks
OSTaskCreate(TaskCon, (void *)0, &TaskConStk[TASK_STK_SIZE - 1],i+4);
}
/*
*********************************************************************************************************
* TASKq1
*********************************************************************************************************
*/
void Taskq1 (void *pdata)
{
INT8U err;
INT8U id;
void *mg;
id=*(int *)pdata;
for (;;)
{
//等待消息隊列中的消息
//OSQPend()函數用于任務等待消息。
//消息通過中斷或另外的任務發送給需要的任務。
//消息是一個以指針定義的變量,在不同的程序中消息的使用也可能不同。
//如果調用OSQPend()函數時隊列中已經存在需要的消息,那么該消息被返回給OSQPend()函數的調用者,隊列中清除該消息。
//如果調用OSQPend()函數時隊列中沒有需要的消息,OSQPend()函數掛起當前任務直到得到需要的消息或超出定義的超時時間。
//如果同時有多個任務等待同一個消息,μC/OS-Ⅱ默認最高優先級的任務取得消息并且任務恢復執行。
// 一個由OSTaskSuspend()函數掛起的任務也可以接受消息,但這個任務將一直保持掛起狀態直到通過調用OSTaskResume()函數恢復任務的運行。
mg=OSQPend(q1,0,&err);
Uart_PutLine(uartPort0,"Task__%d got a Message:\t %s",id,(char *)mg);
//Wait 2 second
//按照時、分、秒、毫秒進行延時的函數
OSTimeDlyHMSM(0, 0, 2, 0);
}
}
/*
*********************************************************************************************************
* TASKq2
*********************************************************************************************************
*/
void Taskq2 (void *pdata)
{
INT8U err;
INT8U id;
void *mg;
id=*(int *)pdata;
for (;;)
{
OSTimeDlyHMSM(0, 0, 2, 0);
mg=OSQPend(q2,0,&err);
switch(err)
{
case OS_NO_ERR:
Uart_PutLine(uartPort0,"\tTask__%d got:\t%s.", id+3, (char *)mg);
OSTimeDlyHMSM(0, 0, 0, 200*(4-id));
break;
default :
Uart_PutLine(uartPort0, "Queue__2 is EMPTY!,Task__%d cannot get message!",id+3);
OSTimeDlyHMSM(0, 0, 0, 200*(4-id));
break;
}
}
}
/*
*********************************************************************************************************
* TASKcon
*********************************************************************************************************
*/
void TaskCon (void *pdata)
{
INT8U i,j;
INT8U err;
INT8U note=1; /* for flush the queue */
//queue1's message
static char *s[]={
"message___0",
"message___1",
"message___2",
"message___3",
"message___4",
"message___5"
};
//queue2's message
static char *t[]={
"message___A",
"message___B",
"message___C",
"message___D",
"message___E",
"message___F"
};
pdata=pdata;
for (;;)
{
Uart_PutLine(uartPort0,"");
Uart_PutLine(uartPort0,"-------------Add message to queue1-------------");
Uart_PutLine(uartPort0,"");
for( i = 0 ; i < 6 ; i++ )
{
//向消息隊列發送一則消息,插在前面(LIFO)
err = OSQPostFront(q1,(void*)s[i]);
switch(err)
{
case OS_NO_ERR:
Uart_PutLine(uartPort0,"\tQueue1___%d add:\t%s",i,s[i]);
OSTimeDlyHMSM(0, 0, 0, 150);
break;
case OS_Q_FULL:
Uart_PutLine(uartPort0,"Queue1 is full, cannot added!");
OSTimeDlyHMSM(0, 0, 0, 150);
break;
default :break;
}
}
Uart_PutLine(uartPort0,"");
Uart_PutLine(uartPort0,"-------------Add message to queue2-------------");
Uart_PutLine(uartPort0,"");
for( j = 0 ; j < 6 ; j++ )
{
//OSQPost()函數通過消息隊列向任務發送消息。
//消息是一個指針長度的變量,在不同的程序中消息的使用也可能不同。
//如果隊列中已經存滿消息,返回錯誤碼。
//OSQPost()函數立即返回調用者,消息也沒有能夠發到隊列。
//如果有任何任務在等待隊列中的消息,最高優先級的任務將得到這個消息。
//如果等待消息的任務優先級比發送消息的任務優先級高,那么高優先級的任務將得到消息而恢復執行,也就是說,發生了一次任務切換。
//消息隊列是先入先出(FIFO)機制的,先進入隊列的消息先被傳遞給任務。
err = OSQPost(q2,(void*)t[j]);
switch(err)
{
case OS_NO_ERR:
//消息已經放入消息隊列
Uart_PutLine(uartPort0,"\tQueue2__%d add:\t%s",j,t[j]);
OSTimeDlyHMSM(0, 0, 0, 150);
break;
case OS_Q_FULL:
//消息隊列已滿
Uart_PutLine(uartPort0,"Queue2 FULL!cannot add.");
OSTimeDlyHMSM(0, 0, 0, 150);
break;
default :
break;
}
}
if(note==1)
{
//OSQFlush()函數清空消息隊列并且忽略發送往隊列的所有消息。
//不管隊列中是否有消息,這個函數的執行時間都是相同的。
OSQFlush(q1);
Uart_PutLine(uartPort0,"\n\r--------------Queue1 Cleared Up--------------\n\r");
note=0;
}
else
{
OSQFlush(q2);
Uart_PutLine(uartPort0,"\n\r--------------Queue2 Cleared Up--------------\n\r");
note=1;
}
TaskQuery();
}
}
void TaskQuery()
{
INT8U err;
OS_Q_DATA data;
//取得消息隊列本身的消息
//OSQQuery()函數用來取得消息隊列的信息。
//用戶程序必須建立一個OS_Q_DATA的數據結構,該結構用來保存從消息隊列的事件控制塊得到的數據。
//通過調用OSQQuery()函數可以知道任務是否在等待消息、有多少個任務在等待消息、隊列中有多少消息以及消息隊列可以容納的消息數。
//OSQQuery()函數還可以得到即將被傳遞給任務的消息的信息。
err=OSQQuery(q1,&data);
if(err==OS_NO_ERR)
{
Uart_PutLine(uartPort0,"\n\r------------Queue1's Information------------");
Uart_PutLine(uartPort0,"\tNextMsg:\t%s\n\r",(char *)data.OSMsg);
Uart_PutLine(uartPort0,"\tNumMsg:\t%d",data.OSNMsgs);
Uart_PutLine(uartPort0,"\tQSize:\t%d",data.OSQSize);
Uart_PutLine(uartPort0,"----------------------------------------------");
}
OSTimeDlyHMSM(0, 0, 3, 500);
err=OSQQuery(q2,&data);
if(err==OS_NO_ERR)
{
Uart_PutLine(uartPort0,"\n\r------------Queue2's Information------------");
Uart_PutLine(uartPort0,"\tNextMsg:\t%s\n\r",(char *)data.OSMsg);
Uart_PutLine(uartPort0,"\tNumMsg:\t%d",data.OSNMsgs);
Uart_PutLine(uartPort0,"\tQSize:\t%d",data.OSQSize);
Uart_PutLine(uartPort0,"----------------------------------------------");
}
OSTimeDlyHMSM(0, 0, 3, 500);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -