ucosii在stm32上的移植詳解4


    詳解3中有一個問題還沒解釋,就是stm32f10x_it.c中已經有SysTick中斷函數的定義SysTick_Handler(),爲什麼官方版非要弄個OS_CPU_SysTickHandler()。答案就在啓動文件上,一般我們自己開發基於stm32芯片的軟件,都會使用標準外設庫CMSIS中提供的啓動文件,而官方移植的啓動文件卻是自己寫的,在兩個文件init.s,vectors.s中(Micrium\Software\EvalBoards\ST\STM3210B-EVAL\RVMDK)。init.s負責進入main(),vectors.s設置中斷向量。OS_CPU_SysTickHandler和OS_CPU_PendSVHandler就是在vectors.s中被設置的。
    我的移植是使用標準外設庫CMSIS中startup_stm32f10x_hd.s作爲啓動文件的,那該怎麼在這個文件
中設置OS_CPU_SysTickHandler呢,事實上在startup_stm32f10x_hd.s文件中,PendSV中斷向量名爲PendSV_Handler,所以只需用OS_CPU_PendSVHandler把所有出現PendSV_Handler的地方替換掉就可以了。
    那麼爲什麼OS_CPU_SysTickHandler不用這種方式處理呢,這樣也就不用註釋os_cpu.c中的
OS_CPU_SysTickHandler(),這主要是基於兩個原因:
    1. startup_stm32f10x_hd.s儘量少該,能不改就不改。
    2. 如果保留OS_CPU_SysTickHandler(),在以後開發過程中,改動OS_CPU_SysTickHandler()中的內
容可能性是非常大的,如果一不小把該文件其他部分改了造成了問題,這個bug就非常難查了,所以我一般移植好後就把ucosii的這些文件設置爲只讀。
    對於上面的原因1,一開始移植時,我曾做過在PendSV_Handler()中調用OS_CPU_PendSVHandler(),
後來發現這樣不行,這是爲什麼呢?問題出在LR寄存器上。
PendSV_Handler()
{
        OS_CPU_PendSVHandler();
}

匯編出來的代碼會是這樣:
PendSV_Handler PROC
   PUSH     {r4,lr}
   BL       OS_CPU_PendSVHandler
   POP      {r4,pc}
ENDP

    這樣在進入OS_CPU_PendSVHandler之後,LR寄存器中存放的是指令POP {r4,pc}的地址+1。在OS_CPU_PendSVHandler中的ORR LR, LR, #0x04就不會起作用,也就無法使用PSP,移植因此失敗。其實在AN-1018.pdf的3.04.06中也有強調OS_CPU_PendSVHandler必須被放置在中斷向量表中。一開始我也沒注意
    到這裏移植的大部分工作都做完了,下面剩下的就是把工程配置好,SysTick中斷處理好。
    在工程中建立ucosii組,把ucosii下的文件都加進該組。這裏別忘了把os_cpu_a.asm加入。
    在工程的Options中,c/c++選項卡的Include Paths中添加.\src\ucosii\src;.\src\ucosii\port。
    編譯工程,會發現缺少app_cfg.h和os_cfg.h文件,app_cfg.h是用來配置應用軟件的,主要是任務的
優先級和堆棧大小,中斷優先級等信息。目前還沒有基於ucosii開發應用軟件,所以只需在include文件夾中創建一個空的app_cfg.h文件即可。os_cfg.h是用來配置ucosii系統的。拷貝Micrium\Software\EvalBoards\ST\STM3210B-EVAL\RVMDK\OS-Probe\os_cfg.h到template\include,對其做如下修改:

#define OS_APP_HOOKS_EN           0
#define OS_DEBUG_EN               0
#define OS_EVENT_MULTI_EN         0
#define OS_SCHED_LOCK_EN          0
#define OS_TICK_STEP_EN           0
#define OS_TASK_CHANGE_PRIO_EN    0 
#define OS_TASK_QUERY_EN          0 
#define OS_TASK_STAT_EN           0
#define OS_TASK_STAT_STK_CHK_EN   0
#define OS_TASK_SUSPEND_EN        0 
#define OS_FLAG_EN                0
#define OS_MBOX_EN                0 
#define OS_TIME_DLY_HMSM_EN       0 
#define OS_TIME_DLY_RESUME_EN     0
#define OS_TIME_GET_SET_EN        0
#define OS_TIME_TICK_HOOK_EN      0

    所做的修改主要是把一些功能給去掉,減少內核大小,也利於調試。等移植完成後,如果需要該功能,再做開啓。
    接下來就剩下處理好SysTick中斷和啓動任務了。SysTick是系統的“心跳”,本質上來說就是一個定時
器。先把原來main.c中的內容刪除,添加如下代碼:

#include "ucos_ii.h"
#include "stm32f10x.h"

static OS_STK startup_task_stk[STARTUP_TASK_STK_SIZE];

static void systick_init(void)
{
        RCC_ClocksTypeDef rcc_clocks;
        RCC_GetClocksFreq(&rcc_clocks);
        SysTick_Config(rcc_clocks.HCLK_Frequency / OS_TICKS_PER_SEC);
}

static void startup_task(void *p_arg)
{
        systick_init();     /* Initialize the SysTick. */

#if (OS_TASK_STAT_EN > 0)
        OSStatInit();      /* Determine CPU capacity. */
#endif
 /* TODO: create application tasks here */

       

        OSTaskDel(OS_PRIO_SELF);
}


int main(void)
{
        OSInit();
        OSTaskCreate(startup_task, (void *)0,
              &startup_task_stk[STARTUP_TASK_STK_SIZE - 1],
              STARTUP_TASK_PRIO);
         OSStart();
         return 0;
}

systick_init()用來初始化並啓動SysTick定時器。
     RCC_GetClocksFreq()用來獲取系統時鐘。
     SysTick_Config()初始化並使能SysTick定時器。
     這裏要注意的是OS_TICKS_PER_SEC,它是每秒鐘的ticks數,如果爲1000,就是1s中1000個ticks,也
就是說1ms就會產生一個SysTick中斷。系統的時間片爲1ms。
    在邵老師的書中3.11節已有明確說明,必須在調用OSStart()之後,才能開啓時鐘節拍器(SysTick)
。一般會把它放在第一個任務(啓動任務)中。

    startup_task()用來創建其他應用任務,創建完其他任務後,就會自己刪除自己。

    文件中的STARTUP_TASK_STK_SIZE,STARTUP_TASK_PRIO需要在app_cfg.h中定義。代碼如下:
/* task priority */
#define STARTUP_TASK_PRIO                          4

/* task stack size */
#define STARTUP_TASK_STK_SIZE                  80

在stm32f10x_it.c中,還需要添加SysTick中斷的處理代碼:

void SysTick_Handler(void)

        OSIntEnter();
        OSTimeTick();
        OSIntExit();
}

    這個代碼是仿照OS_CPU_SysTickHandler()中代碼的,在邵老師書的3.11節亦有說明。這裏就不解釋。

    至此ucosii在stm32上的移植已全部完成。


轉載請註明出處:http://blog.csdn.net/lbl1234

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章