官术网_书友最值得收藏!

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 */
主站蜘蛛池模板: 镇平县| 衢州市| 丽水市| 南通市| 本溪市| 长阳| 牙克石市| 江西省| 开鲁县| 若尔盖县| 绥德县| 望谟县| 区。| 正安县| 江西省| 乌鲁木齐县| 杭锦旗| 凤阳县| 南郑县| 六安市| 高清| 寿光市| 长葛市| 华池县| 天气| 固安县| 宁夏| 青海省| 聂荣县| 永城市| 通道| 弥渡县| 惠州市| 荔波县| 确山县| 咸阳市| 文山县| 景德镇市| 桦南县| 凤冈县| 江油市|