任務堆棧:存儲任務中的調用的函數、局部變量、中斷服務程序和CPU寄存器的值。
全局變量的保護:
1.如果只在一個任務中寫(或只有一個數據),而在其他任務中只是讀取,則可以不用互斥型信號量,最多會造成讀取的數據未被完全寫完。
2.如果全局變量在多個任務中寫,則需要用互斥型信號量保護,這樣當有任務申請到互斥型信號量(保護不可重入的程序段)寫數據時,其他任務的同一個互斥型信號量必須等待上一個任務的釋放才可進行寫。
3.如果全局變量在中斷中寫,則在其他任務中的全局變量的寫操作要用臨界段(禁止中斷和禁止調度:保護不可被分割的程序段)保護。(因為如果不關中斷相當于中斷的優先級最高,而且不能被像其他任務那樣掛起。)
OS_CFG_ISR_POST_DEFERRED_EN為1臨界段使用鎖調度器方式;
為0臨界段使用禁中斷方式(CPU_SR_ALLOC();
OS_CRITICAL_ENTER();OS_CRITICAL_EXIT();
OS_CRITICAL_EXIT_NO_SCHED();
OSSchedLockNestingCtr記錄調度器被鎖的次數)。
檢測任務堆棧的使用情況:
OS_CFG_STAT_TASK_STK_CHK_EN使能 OS_ERRerr; CPU_STK_SIZE stk_free; CPU_STK_SIZE stk_used; OSTaskStkChk(&TaskBStkTCB,&stk_free,&stk_used,&err); 中斷中使用OSIntEnter(); 和OSIntExit();是為了退出中斷后執行中斷調度操作,如果中斷中并未用到OSSemPost();等系統函數,則退出中斷服務程序后不需要進行任務調度,就可以不在中斷服務程序中使用OSIntEnter(); 和OSIntExit();。
(有時候用:CPU_CRITICAL_ENTER();OSIntNestingCtr++; CPU_CRITICAL_EXIT();替代OSIntEnter();) 一、 變量類型 在cpu.h中是有關cpu變量的重新定義,還包括CPU_STK(CPU堆棧類型), 和CPU_STK_SIZE(CPU堆棧類型的大。┑亩x,CPU_SR(CPU狀態寄存 器的定義)。 在os.h中是有關os類型的定義如OS_TCB(任務控制塊)、OS_SEM(信號量)、OS_MUTEX(互斥型信號量)、OS_MSG(消息)、OS_Q(消息隊列)、OS_ERR(系統錯誤)等。 在cpu_core.h中是有關cpu的定義,如CPU_ERR、CPU_TS、CPU_TS_TMR等。 CPU_STK:typedef unsigned int堆棧的類型定義
OS_TCB:struct os_tcb任務控制塊的類型定義
OS_ERR:enum os_err錯誤信息定義
CPU_TS:typedef unsigned int時間戳變量
CPU_TS_TMR:typedef unsigned int定時器變量
二、 全局變量 (OS_CFG_STAT_TASK_EN使能且調用了OSStatTaskCPUUsageInit(&err); 則開啟了統計任務的功能:可以統計CPU使用率等。) OSStatTaskCPUUsage:CPU的使用率(0—10000= 0.00-100.00%)
OSStatTaskCPUUsageMax:CPU的使用率最大值(0—10000= 0.00-100.00%)
OSTaskCtxSwCtr:任務切換次數的記錄變量
OSStatTaskCtr:已經建立了的任務數
三、常用函數
一、OS_CORE.C (1)void OSInit() //系統初始化 (2)void OSIntEnter() //發生了一次中斷(中斷嵌套的逐層進入) (3)void OSIntExit() //退出了一次中斷(中斷嵌套的逐層退出) (4)void OSSched() //系統進行調度 (5)void OSSchedLock() //給調度器上鎖 (6)void OSSchedUnlock() //給調度器解鎖,成對使用 (7)void OSStart() //啟動多任務過程,在啟動之前必須調用OSInit(),并已建立一個任務。其中OSStartHighRdy()必須調用OSTaskSwHook(),并令OSRunning = TRUE. (8)void OS_Pend() //掛起任務 (9)void OS_Post() //解掛任務 (10)void OS_PendAbort() //取消掛起任務 (11)INT16UOSVersion () //返回uc/os的版本號*10000 (12)void OS_IdleTaskInit() //空閑任務初始化 (13)void OS_IdleTask() //空閑任務 二、OS_TASK.C (1)void OSTaskCreate(OS_TCB *p_tcb,//任務控制塊 CPU_CHAR *p_name,//任務名 OS_TASK_PTR p_task,//任務函數指針 void *p_arg,//任務函數參數 OS_PRIO prio,//任務優先級 CPU_STK *p_stk_base,//堆棧指針 CPU_STK_SIZE stk_limit,//任務的堆棧剩余警戒線 CPU_STK_SIZE stk_size,//任務的空間大小 OS_MSG_QTY q_size, //能接收的信息隊列最大值 OS_TICK time_quanta,//時間片輪轉時間 void *p_ext,// 任務控制塊的擴展信息 OS_OPT opt, //任務的選項 OS_ERR *p_err) //任務的錯誤信息 (2)void OSTaskChangePrio() //任務優先級別的改變 (3)void OSTaskDel() //任務的刪除 (4)void OSTaskSuspend() //任務的暫停 (5)void OSTaskResume() //任務的恢復 (6)void OSTaskStkChk() //校核空余內存的數量 (7)OS_MSG_QTY OSTaskQFlush() //清空任務級消息隊列中的消息 (8)void *OSTaskQPend() //掛起任務級消息隊列 (9)CPU_BOOLEAN OSTaskQPendAbort()//取消任務級消息隊列的掛起狀態 (10)void OSTaskQPost() //向任務級消息隊列中發送消息 (11)OS_REG OSTaskRegGet() //獲取任務寄存器的當前值 (12)void OSTaskRegSet() //設置任務寄存器的當前值 (13)OS_SEM_CTR OSTaskSemPend() //任務信號量等待信號 (14)CPU_BOOLEAN OSTaskSemPendAbort()//任務信號量取消掛起狀態 (15)OS_SEM_CTR OSTaskSemPost() //任務信號量發送消息 (16)OS_SEM_CTR OSTaskSemSet() //設置任務信號量的計數值 (17)void OSTaskTimeQuantaSet() //改變任務的時間片
voidTaskMain(void *pdata); //任務聲明 static OS_TCB TaskMainTCB; //任務控制塊 #define TASK_MAIN_PRIO 3 //任務優先級 #define TASK_MAIN_STK_SIZE 256 //任務堆棧大小256*4=1024B static CPU_STK TaskMainStk[TASK_MAIN_STK_SIZE];//任務堆棧定義 OSTaskCreate((OS_TCB *)&TaskMainTCB, //任務的控制塊 (CPU_CHAR *)"Task Main Start", //任務的名稱 (OS_TASK_PTR )TaskMain, //任務的函數指針 (void *)0, //任務的函數初值 (OS_PRIO )TASK_MAIN_PRIO, //任務的優先級 (CPU_STK *)&TaskMainStk[0], //任務的堆棧 (CPU_STK_SIZE)TASK_MAIN_STK_SIZE/10,//任務的堆棧剩余警戒線 (CPU_STK_SIZE)TASK_MAIN_STK_SIZE,//任務的空間大小 (OS_MSG_QTY )0, //所能接收的信息隊列最大值 (OS_TICK )0, //任務的時間片輪轉時間 (void *)0, //任務的任務控制塊的擴展信息 (OS_OPT )(OS_OPT_TASK_STK_CHK| OS_OPT_TASK_STK_CLR), //任務的選項 (OS_ERR *)&err); //任務的錯誤信息 三、OS_TIME.C (1)void OSTimeDly() //以時鐘節拍數為單位延時 (2)void OSTimeDlyHMSM() //用時、分、秒、毫秒為單位延時 (3)void OSTimeDlyResume() //取消任務中的延時,引發一次調度 (4)OS_TICKOSTimeGet() //獲取OSTime 值 (5)void OSTimeSet() //設置 OSTime 值 四、OS_SEM.C (1)void OSSemCreate() //創建信號量 (2)OS_OBJ_QTY OSSemDel() //刪除信號量 (3)OS_SEM_CTR OSSemPend() //請求信號量 (4)OS_SEM_CTR OSSemPost() //發送(釋放)信號量 (5)void OSSemSet() //設置信號量的計數值 (6)OS_OBJ_QTYOSSemPendAbort() //取消信號量
static OS_SEM AppSem; //定義一個信號量變量 CPU_TS ts=0;//存放發送消息時的時間戳OS_TS_GET();(獲取當前時間戳) OS_ERR err; //返回的錯誤信息 OSSemCreate(&AppSem,"Test Sem", 0, &err);//要在使用之前創建(如果在兩個任務中都用到,則最好在兩個任務創建前建立,也可在優先級高的任務中建立) OSSemPend(&AppSem,0,OS_OPT_PEND_BLOCKING,&ts,&err);//等待信號量(ts為發送信號量的時間戳) OSSemPost(&AppSem, OS_OPT_POST_1,&err);//發送信號量 五、OS_FLAG.C (1)void OSFlagCreate() //信號標志組的創建函數 (2)OS_OBJ_QTY OSFlagDel() //刪除信號標志組 (3)OS_FLAGS OSFlagPend() //掛起信號標志組 (4)OS_FLAGS OSFlagPost() //向信號標志組發送信號 (5)OS_OBJ_QTYOSFlagPendAbort() //取消掛起信號標志組
staticOS_FLAG_GRP AppFlag; //定義一個信號標志組變量 CPU_TSts=0; //存放發送消息時的時間戳OS_TS_GET();(獲取當前時間戳) OS_ERRerr; //返回的錯誤信息 OSFlagCreate(&AppFlag,"TestFlag",0x00,&err);//創建信號標志組且設置初值為0x00 OSFlagPend(&AppFlag,0x03,0,OS_OPT_PEND_FLAG_SET_ALL,&ts,&err); //等待信號標志組的bit0和bit1都為1 OSFlagPost(&AppFlag,0x01,OS_OPT_POST_FLAG_SET,&err); //把信號標志組的bit0設置為1 六、OS_MUTEX.C (1)void OSMutexCreate() //創建互斥型信號量 (2)OS_OBJ_QTY OSMutexDel() //刪除互斥型信號量 (3)void OSMutexPend() //請求互斥型信號量 (4)void OSMutexPost() //發送(釋放)互斥型信號量 (5)OS_OBJ_QTYOSMutexPendAbort() //取消互斥型信號量 static OS_MUTEX AppMutex; //定義一個互斥型信號量變量 CPU_TS ts=0;//存放發送消息時的時間戳OS_TS_GET();(獲取當前時間戳) OS_ERR err; //返回的錯誤信息 OSMutexCreate(&AppMutex,"Test Mutex", &err);//創建互斥型信號量 OSMutexPend(&AppMutex, 0, OS_OPT_PEND_BLOCKING,&ts,&err); //互斥型信號量申請(阻塞方式) OSMutexPost(&AppMutex, OS_OPT_POST_NONE,&err); //互斥型信號量釋放 七、OS_Q.C (1)void OSQCreate() //創建一個消息隊列 (2)OS_OBJ_QTY OSQDel() //刪除消息隊列 (3)OS_MSG_QTY OSQFlush() //清空消息隊列 (4)void *OSQPend() //請求一個消息隊列 (6)void OSQPost() //向消息隊列發送消息 (6)OS_OBJ_QTYOSQPendAbort() //取消消息隊列的等待狀態 以指針和長度的形式向其他任務發送消息,如果是阻塞方式則接收到的數據的次數等于發送的次數才會被阻塞。 static OS_Q AppQ; //定義一個消息隊列變量 u8sendq_a[2]={1,2}; //要發送的數據 OSQCreate(&AppQ,"Test Q", 13, &err);//創建消息隊列包含存放消息的條數 OSQPost(&AppQ,sendq_a,2, OS_OPT_POST_FIFO,&err);//發送數據 OS_MSG_SIZEmsg_size=0; //接收到的數據的大小 CPU_TS ts=0; //發送數據時的時間戳 OS_ERRerr; u8 *req; //接收到的數據的地址 req=(u8*)OSQPend (&AppQ, 0, OS_OPT_PEND_BLOCKING, &msg_size,&ts,&err); //接收數據(阻塞方式,非阻塞方式是給中斷用的) 八、OS_MEM.C (1) void OSMemCreate() //創建一個固定大小的內存分區 (2)void *OSMemGet() //從分區中獲取一個內存塊 (3)void OSMemPut() //返還一個內存塊到分區 九、OS_TMR.C (1)void OSTmrCreate() //創建一個定時器,定時調用函數 (2)CPU_BOOLEAN OSTmrDel() //刪除定時器 (3)OS_TICK OSTmrRemainGet() //定時器的剩余時間 (4)CPU_BOOLEAN OSTmrStart() //定時器開始計時 (5)OS_STATE OSTmrStateGet() //獲取定時器的當前狀態
(6)CPU_BOOLEAN OSTmrStop() //定時器停止計時 |