- μC/OS-III內核實現與應用開發實戰指南:基于STM32
- 劉火良 楊森編著
- 1092字
- 2019-08-01 11:35:57
3.6 main()函數
main()函數在文件app.c中編寫,app.c文件的完整代碼參見代碼清單3-29。
代碼清單3-29 app.c文件
1 /* 2 ******************************************************************* 3 * 包含的頭文件 4 ******************************************************************* 5 */ 6 #include "os.h" 7 #include "ARMCM3.h" 8 9 /* 10 ******************************************************************* 11 * 宏定義 12 ******************************************************************* 13 */ 14 15 16 /* 17 ******************************************************************* 18 * 全局變量 19 ******************************************************************* 20 */ 21 22 uint32_t flag1; 23 uint32_t flag2; 24 25 /* 26 ******************************************************************* 27 * TCB & STACK &任務聲明 28 ******************************************************************* 29 */ 30 #define TASK1_STK_SIZE 20 31 #define TASK2_STK_SIZE 20 32 33 static CPU_STK Task1Stk[TASK1_STK_SIZE]; 34 static CPU_STK Task2Stk[TASK2_STK_SIZE]; 35 36 static OS_TCB Task1TCB; 37 static OS_TCB Task2TCB; 38 39 void Task1( void *p_arg ); 40 void Task2( void *p_arg ); 41 42 /* 43 ******************************************************************* 44 * 函數聲明 45 ******************************************************************* 46 */ 47 void delay(uint32_t count); 48 49 /* 50 ******************************************************************* 51 * main()函數 52 ******************************************************************* 53 */ 54 /* 55 * 注意事項:1)該工程使用軟件仿真,debug需要選擇為Ude Simulator 56 * 2)在Target選項卡中把晶振Xtal(MHz)的值改為25,默認是12, 57 * 改成25是為了與system_ARMCM3.c中定義的__SYSTEM_CLOCK相同, 58 * 3)確保仿真時時鐘一致 59 */ 60 int main(void) 61 { 62 OS_ERR err; 63 64 65 66 /* 初始化相關的全局變量 */ 67 OSInit(&err); 68 69 /* 創建任務 */ 70 OSTaskCreate ((OS_TCB*) &Task1TCB, 71 (OS_TASK_PTR ) Task1, 72 (void *) 0, 73 (CPU_STK*) &Task1Stk[0], 74 (CPU_STK_SIZE) TASK1_STK_SIZE, 75 (OS_ERR *) &err); 76 77 OSTaskCreate ((OS_TCB*) &Task2TCB, 78 (OS_TASK_PTR ) Task2, 79 (void *) 0, 80 (CPU_STK*) &Task2Stk[0], 81 (CPU_STK_SIZE) TASK2_STK_SIZE, 82 (OS_ERR *) &err); 83 84 /* 將任務加入就緒列表 */ 85 OSRdyList[0].HeadPtr = &Task1TCB; 86 OSRdyList[1].HeadPtr = &Task2TCB; 87 88 /* 啟動操作系統,將不再返回 */ 89 OSStart(&err); 90 } 91 92 /* 93 ******************************************************************* 94 * 函數實現 95 ******************************************************************* 96 */ 97 /* 軟件延時 */ 98 void delay (uint32_t count) 99 { 100 for (; count!=0; count--); 101 } 102 103 104 105 /* 任務1 */ 106 void Task1( void *p_arg ) 107 { 108 for ( ;; ) { 109 flag1 = 1; 110 delay( 100 ); 111 flag1 = 0; 112 delay( 100 ); 113 114 /* 任務切換,這里是手動切換 */ 115 OSSched(); 116 } 117 } 118 119 /* 任務2 */ 120 void Task2( void *p_arg ) 121 { 122 for ( ;; ) { 123 flag2 = 1; 124 delay( 100 ); 125 flag2 = 0; 126 delay( 100 ); 127 128 /* 任務切換,這里是手動切換 */ 129 OSSched(); 130 } 131 }
代碼清單3-29中的所有代碼在本小節之前都有循序漸進的講解,這里只是融合在一起放在main()函數中。Task1和Task2并不會真正自動切換,而是在各自的函數體中加入了OSSched()函數來實現手動切換。OSSched()函數的實現具體參見代碼清單3-30。
代碼清單3-30 OSSched()函數
1 /* 任務切換,實際就是觸發PendSV異常,然后在PendSV異常中進行上下文切換 */ 2 void OSSched (void) 3 { 4 if ( OSTCBCurPtr == OSRdyList[0].HeadPtr ) { 5 OSTCBHighRdyPtr = OSRdyList[1].HeadPtr; 6 } else { 7 OSTCBHighRdyPtr = OSRdyList[0].HeadPtr; 8 } 9 10 OS_TASK_SW(); 11 }
OSSched()函數的調度算法很簡單,即如果當前任務是任務1,那么下一個任務就是任務2,如果當前任務是任務2,那么下一個任務就是任務1,然后調用OS_TASK_SW()函數觸發PendSV異常,再在PendSV異常中實現任務的切換。在此后的章節中,我們將繼續完善,加入SysTick中斷,從而實現系統調度的自動切換。OS_TASK_SW()函數其實是一個宏定義,具體是往中斷及狀態控制寄存器SCB_ICSR的位28(PendSV異常啟用位)寫入1,從而觸發PendSV異常。OS_TASK_SW()函數在os_cpu.h文件中實現(第一次使用os_cpu.h時需要自行在文件夾C-CPU中新建并添加到工程的C/CPU組),文件的內容具體參見代碼清單3-31。
代碼清單3-31 os_cpu.h文件
1 #ifndef OS_CPU_H 2 #define OS_CPU_H 3 4 /* 5 ******************************************************************* 6 * 宏定義 7 ******************************************************************* 8 */ 9 10 #ifndef NVIC_INT_CTRL 11 /* 中斷控制及狀態寄存器 SCB_ICSR */ 12 #define NVIC_INT_CTRL *((CPU_REG32 *)0xE000ED04) 13 #endif 14 15 #ifndef NVIC_PENDSVSET 16 /* 觸發PendSV異常的值 Bit28:PENDSVSET */ 17 #define NVIC_PENDSVSET 0x10000000 18 #endif 19 20 /* 觸發PendSV異常 */ 21 #define OS_TASK_SW() NVIC_INT_CTRL = NVIC_PENDSVSET 22 /* 觸發PendSV異常 */ 23 #define OSIntCtxSw() NVIC_INT_CTRL = NVIC_PENDSVSET 24 /* 25 ******************************************************************* 26 * 函數聲明 27 ******************************************************************* 28 */ 29 void OSStartHighRdy(void);/* 在os_cpu_a.s中實現 */ 30 void PendSV_Handler(void);/* 在os_cpu_a.s中實現 */ 31 32 33 #endif/* OS_CPU_H */
推薦閱讀
- Linux內核完全注釋(20周年版·第2版)
- 嵌入式Linux系統開發:基于Yocto Project
- 精通Linux內核開發
- 移動應用UI設計模式(第2版)
- Application Development in iOS 7
- 一學就會:Windows Vista應用完全自學手冊
- Social Data Visualization with HTML5 and JavaScript
- 鴻蒙操作系統設計原理與架構
- bash shell腳本編程經典實例(第2版)
- 完美應用Ubuntu(第2版)
- Learn OpenShift
- Mastering Azure Serverless Computing
- 鴻蒙HarmonyOS應用開發從入門到精通
- Python機器學習系統構建(原書第3版)
- Azure Serverless Computing Cookbook