新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > ucosii在stm32上的移植詳解4

        ucosii在stm32上的移植詳解4

        作者: 時(shí)間:2016-11-19 來源:網(wǎng)絡(luò) 收藏
        詳解3中有一個(gè)問題還沒解釋,就是stm32f10x_it.c中已經(jīng)有SysTick中斷函數(shù)的定義SysTick_Handler(),為什么官方版非要弄個(gè)OS_CPU_SysTickHandler()。答案就在啟動(dòng)文件上,一般我們自己開發(fā)基于stm32芯片的軟件,都會(huì)使用標(biāo)準(zhǔn)外設(shè)庫(kù)CMSIS中提供的啟動(dòng)文件,而官方移植的啟動(dòng)文件卻是自己寫的,在兩個(gè)文件init.s,vectors.s中(MicriumSoftwareEvalBoardsSTSTM3210B-EVALRVMDK)。init.s負(fù)責(zé)進(jìn)入main(),vectors.s設(shè)置中斷向量。OS_CPU_SysTickHandler和OS_CPU_PendSVHandler就是在vectors.s中被設(shè)置的。

        我的移植是使用標(biāo)準(zhǔn)外設(shè)庫(kù)CMSIS中startup_stm32f10x_hd.s作為啟動(dòng)文件的,那該怎么在這個(gè)文件中設(shè)置OS_CPU_SysTickHandler呢,事實(shí)上在startup_stm32f10x_hd.s文件中,PendSV中斷向量名為PendSV_Handler,所以只需用OS_CPU_PendSVHandler把所有出現(xiàn)PendSV_Handler的地方替換掉就可以了。
        那么為什么OS_CPU_SysTickHandler不用這種方式處理呢,這樣也就不用注釋os_cpu.c中的OS_CPU_SysTickHandler(),這主要是基于兩個(gè)原因:
        1. startup_stm32f10x_hd.s盡量少該,能不改就不改。
        2. 如果保留OS_CPU_SysTickHandler(),在以后開發(fā)過程中,改動(dòng)OS_CPU_SysTickHandler()中的內(nèi)容可能性是非常大的,如果一不小把該文件其他部分改了造成了問題,這個(gè)bug就非常難查了,所以我一般移植好后就把ucosii的這些文件設(shè)置為只讀。
        對(duì)于上面的原因1,一開始移植時(shí),我曾做過在PendSV_Handler()中調(diào)用OS_CPU_PendSVHandler(),后來發(fā)現(xiàn)這樣不行,這是為什么呢?問題出在LR寄存器上。
        PendSV_Handler()
        {
        OS_CPU_PendSVHandler();
        }

        本文引用地址:http://www.104case.com/article/201611/318074.htm

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

        這樣在進(jìn)入OS_CPU_PendSVHandler之后,LR寄存器中存放的是指令POP {r4,pc}的地址+1。在OS_CPU_PendSVHandler中的ORR LR, LR, #0x04就不會(huì)起作用,也就無法使用PSP,移植因此失敗。其實(shí)在AN-1018.pdf的3.04.06中也有強(qiáng)調(diào)OS_CPU_PendSVHandler必須被放置在中斷向量表中。一開始我也沒注意。
        到這里移植的大部分工作都做完了,下面剩下的就是把工程配置好,SysTick中斷處理好。
        在工程中建立ucosii組,把ucosii下的文件都加進(jìn)該組。這里別忘了把os_cpu_a.asm加入。
        在工程的Options中,c/c++選項(xiàng)卡的Include Paths中添加.srcucosiisrc;.srcucosiiport。
        編譯工程,會(huì)發(fā)現(xiàn)缺少app_cfg.h和os_cfg.h文件,app_cfg.h是用來配置應(yīng)用軟件的,主要是任務(wù)的優(yōu)先級(jí)和堆棧大小,中斷優(yōu)先級(jí)等信息。目前還沒有基于ucosii開發(fā)應(yīng)用軟件,所以只需在include文件夾中創(chuàng)建一個(gè)空的app_cfg.h文件即可。os_cfg.h是用來配置ucosii系統(tǒng)的。拷貝MicriumSoftwareEvalBoardsSTSTM3210B-EVALRVMDKOS-Probeos_cfg.h到templateinclude,對(duì)其做如下修改:

        #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

        所做的修改主要是把一些功能給去掉,減少內(nèi)核大小,也利于調(diào)試。等移植完成后,如果需要該功能,再做開啟。
        接下來就剩下處理好SysTick中斷和啟動(dòng)任務(wù)了。SysTick是系統(tǒng)的“心跳”,本質(zhì)上來說就是一個(gè)定時(shí)器。先把原來main.c中的內(nèi)容刪除,添加如下代碼:

        #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()用來初始化并啟動(dòng)SysTick定時(shí)器。
        RCC_GetClocksFreq()用來獲取系統(tǒng)時(shí)鐘。
        SysTick_Config()初始化并使能SysTick定時(shí)器。
        這里要注意的是OS_TICKS_PER_SEC,它是每秒鐘的ticks數(shù),如果為1000,就是1s中1000個(gè)ticks,也就是說1ms就會(huì)產(chǎn)生一個(gè)SysTick中斷。系統(tǒng)的時(shí)間片為1ms。
        在邵老師的書中3.11節(jié)已有明確說明,必須在調(diào)用OSStart()之后,才能開啟時(shí)鐘節(jié)拍器(SysTick)。一般會(huì)把它放在第一個(gè)任務(wù)(啟動(dòng)任務(wù))中。

        startup_task()用來創(chuàng)建其他應(yīng)用任務(wù),創(chuàng)建完其他任務(wù)后,就會(huì)自己刪除自己。

        文件中的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();
        }

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

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



        關(guān)鍵詞: ucosiistm32移

        評(píng)論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 古浪县| 定远县| 普宁市| 博客| 本溪| 石渠县| 无为县| 南郑县| 安远县| 麟游县| 霍邱县| 简阳市| 奈曼旗| 白玉县| 临泽县| 伊吾县| 北辰区| 台南县| 封丘县| 梅州市| 海口市| 读书| 康乐县| 长沙市| 瑞昌市| 仙居县| 通榆县| 黄大仙区| 宁国市| 兰坪| 石狮市| 琼中| 太湖县| 柞水县| 公主岭市| 长葛市| 紫云| 敦化市| 揭西县| 象州县| 焉耆|