1. 程式人生 > >【stm32+uC/OS-II】ucosii移植簡單詳細步驟

【stm32+uC/OS-II】ucosii移植簡單詳細步驟

    μC/OS-II由Micrium公司提供,是一個可移植、可固化的、可裁剪的、佔先式多工實時核心,它適用於多種微處理器,微控制器和數字處理晶片(已經移植到超過100種以上的微處理器應用中)。同時,該系統原始碼開放、整潔、一致,註釋詳盡,適合系統開發。 μC/OS-II已經通過聯邦航空局(FAA)商用航行器認證,符合航空無線電技術委員會(RTCA)DO-178B標準。

——摘自百度百科

經過三天對uC/OS-II的研究和琢磨,成功移植了自己的uC/OS-II;回首看下,簡單的移植是非常簡單的;可能這句話比較囉嗦,等我下面解析完之後就認同了;

首先,來附圖,我相信只要剛剛認識ucosii的人,都見過這種型別的圖了;而且版本不一;


這個是摘自一個教程上面的,但是我覺得還是有點複雜,然後,我又仔細的精簡了框架和程式碼;當然只適合初學者;


可能有人還不知道什麼是BSP,Board Support Package,板級支援包;這樣的話,一看我們的程式碼就可以分為四部分了;

為了有點邏輯,我從uC/OS-II Source開始說起;這部分程式碼大家都知道是不用修改的,但是我們至少要知道他依賴的外部標頭檔案都有哪些;

Step one:

+------------------------------------------
|core:os_core.c
|  os:os_flag.c    os_mbox.c
|os_mem.c     os_mutex.c
|os_q.c       os_sem.c
|os_task.c    os_time.c
|      o

s_tmr.c
|head:ucos_ii.h
+------------------------------------------

理論上這幾個檔案我們完全不用修改!但是,他依賴外部的一些標頭檔案;
app_cfg.h //應用程式的一些功能,目測這裡是不需要的;但是他已經寫了,那我們就保留吧;所以我們就要先建立一個空的app_cfg.h檔案
os_cfg.h //做一些os功能的開關,我們可以由此來對系統進行一些裁剪;保留我們需要的功能;
os_cpu.h //為了適應os,我們必須把os與cpu之間建立一個橋樑;就是通過os_port來進行建立的;

step two:

os_ports 在uCOS-II\Ports\ARM-Cortex-M3\Generic\IAR
os_cpu_c.c

//有兩個地方要說下:1:在stm32的啟動程式碼裡面已經有一些功能函數了,所以我們要把他進行刪除,以及他所附帶的函式;並在os_cpu.h中註釋點他們的外部宣告;2:部分巨集定義也刪除了;

#if 0
#define  OS_CPU_CM3_NVIC_ST_CTRL    (*((volatile INT32U *)0xE000E010uL)) /* SysTick Ctrl & Status Reg. */
#define  OS_CPU_CM3_NVIC_ST_RELOAD  (*((volatile INT32U *)0xE000E014uL)) /* SysTick Reload  Value Reg. */
#define  OS_CPU_CM3_NVIC_ST_CURRENT (*((volatile INT32U *)0xE000E018uL)) /* SysTick Current Value Reg. */
#define  OS_CPU_CM3_NVIC_ST_CAL     (*((volatile INT32U *)0xE000E01CuL)) /* SysTick Cal     Value Reg. */
#define  OS_CPU_CM3_NVIC_PRIO_ST    (*((volatile INT8U  *)0xE000ED23uL)) /* SysTick Handler Prio  Reg. */


#define  OS_CPU_CM3_NVIC_ST_CTRL_COUNT                    0x00010000uL   /* Count flag.                */
#define  OS_CPU_CM3_NVIC_ST_CTRL_CLK_SRC                  0x00000004uL   /* Clock Source.              */
#define  OS_CPU_CM3_NVIC_ST_CTRL_INTEN                    0x00000002uL   /* Interrupt enable.          */
#define  OS_CPU_CM3_NVIC_ST_CTRL_ENABLE                   0x00000001uL   /* Counter mode.              */
#define  OS_CPU_CM3_NVIC_PRIO_MIN                               0xFFu    /* Min handler prio.          */
#endif
#if 0
void  OS_CPU_SysTickHandler (void)
void  OS_CPU_SysTickInit (INT32U  cnts)
#endif

os_cpu.h 同樣把下面幾個外部宣告的函式給去掉;
#if 0
                                                  /* See OS_CPU_C.C                                    */
void       OS_CPU_SysTickHandler(void);
void       OS_CPU_SysTickInit(void);
                                                  /* See BSP.C                                         */
INT32U     OS_CPU_SysTickClkFreq(void);
#endif

os_cpu_a.asm
這部分是彙編程式碼;由於他裡面有部分指令集不適合stm32,所以我們要稍微改下:
1、將所有的PUBLIC 改為 EXPORT
2、把自己對齊部分也改下,也是因為指令集不匹配;
;       RSEG CODE:CODE:NOROOT(2)
AREA |.text|, CODE, READONLY, ALIGN=2
THUMB
REQUIRE8
PRESERVE8

注:AREA 一點不能頂頭寫,這是規定,不然回編譯出錯;

os_dbg.c
#define OS_COMPILER_OPT __root
這個不相容,需要把它改下;
#define OS_COMPILER_OPT //__root

step three:

將ST的官方庫導進去即可;

step four:

startup_stm32f10x_hd.s
將 PendSV_Handler 替換成 OS_CPU_PendSVHandler
stm32f10x_it.c
加標頭檔案: ucos_ii.h,
並新增如下程式碼:

/**
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
  */
void SysTick_Handler(void)
{
OSIntEnter();
OSTimeTick();
OSIntExit();

}

os_cfg.h對部分功能進行剪裁;

#define OS_FLAG_EN0
#define OS_MBOX_EN 0
#define OS_MEM_EN 0
#define OS_MUTEX_EN 0
#define OS_Q_EN 0
#define OS_SEM_EN 0
#define OS_TMR_EN 0
#define OS_DEBUG_EN 0
#define OS_APP_HOOKS_EN 0
#define OS_EVENT_MULTI_EN 0

這樣算是簡單系統以及移植完成了,下面就是寫自己的app了;我直接附上自己的main.c程式碼;

main.c

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

#define ON 	1
#define OFF 0
#define LED1(opt)	((opt) ? (GPIOD->BRR |= 1<<3):(GPIOD->BSRR |= 1<<3))
#define LED2(opt)	((opt) ? (GPIOD->BRR |= 1<<6):(GPIOD->BSRR |= 1<<6))
#define LED3(opt)	((opt) ? (GPIOB->BRR |= 1<<5):(GPIOB->BSRR |= 1<<5))

#define SystemFrequency 72000000
#define STARTUP_TASK_PRIO 4
#define STARTUP_TASK_STK_SIZE 80

void SysTick_init(void)
{
	SysTick_Config(SystemFrequency/OS_TICKS_PER_SEC);
}

void LED_Init()
{
	RCC->APB2ENR |= (1<<3)|(1<<5);
	GPIOB->CRL &= ~(0xff<<20);
	GPIOB->CRL |= 0x33<<(4*5);
	
	GPIOD->CRL &= ~(0xff<<(4*3));
	GPIOD->CRL &= ~(u32)((u32)0xff<<(4*6));
	GPIOD->CRL |= 0x33<<(4*3);
	GPIOD->CRL |= 0x33<<(4*6);
	
	LED1(OFF);
	LED2(OFF);
	LED3(OFF);
}
void TestLed1(void *p_arg)
{
	SysTick_init();
	while(1)
	{
		LED1(ON);
		OSTimeDlyHMSM(0,0,1,0);
		LED1(OFF);
		OSTimeDlyHMSM(0,0,1,0);
	}
}
void TestLed2(void *p_arg)
{
	SysTick_init();
	while(1)
	{
		LED2(ON);
		OSTimeDlyHMSM(0,0,0,500);
		LED2(OFF);
		OSTimeDlyHMSM(0,0,0,500);
	}
}
void TestLed3(void *p_arg)
{
	SysTick_init();
	while(1)
	{
		LED3(ON);
		OSTimeDlyHMSM(0,0,0,100);
		LED3(OFF);
		OSTimeDlyHMSM(0,0,0,100);
	}
}
static OS_STK task_testled1[STARTUP_TASK_STK_SIZE];
static OS_STK task_testled2[STARTUP_TASK_STK_SIZE];
static OS_STK task_testled3[STARTUP_TASK_STK_SIZE];
int main()
{
	LED_Init();
	OSInit();
	OSTaskCreate(TestLed1,(void *)0,&task_testled1[STARTUP_TASK_STK_SIZE-1],STARTUP_TASK_PRIO);
	OSTaskCreate(TestLed2,(void *)0,&task_testled2[STARTUP_TASK_STK_SIZE-1],STARTUP_TASK_PRIO-1);
	OSTaskCreate(TestLed3,(void *)0,&task_testled3[STARTUP_TASK_STK_SIZE-1],STARTUP_TASK_PRIO-2);
	OSStart();
	return 0;
}

OK,到此為止,已經移植完成;我們就可以測試下;希望大家多多指教;後期繼續深入學習ucosii的其他功能;