μCOS_II移植到STM32F103VC过程

μC/OS-II移植STM32F103VC


一.μCOS-II源码文件结构介绍

下载地址:

https://www.micrium.com/download/micrium_stm32xxx_ucos-ii/   

这个地址下载的时候需要注册Micrium账号才能下载,源码是Micrium官方提供给移植内核ARM Cortex-M3的例子,我们所要移植的STM32F103VC芯片的内核是ARM Cortex-M3,因此我们下载这个源码文件。

下载成功之后是一个Micrium_STM32xxx_uCOS-II.exe可执行文件的压缩文件(图1)需要我们解压缩(图2)得到(图3)。

图1:

 

图2:

 

图3:

 

树形展开结构:

 

其中文件夹简单介绍:

AppNotes

在这个文件夹下有两个子文件夹,里面内容都是移植时的说明文件,我们只关心

Micrium\AppNotes\AN1xxx-RTOS\AN1018-uCOS-II-Cortex-M3\AN-1018.pdf因为这个是针对ARM Cortex-M3移植的说明。

Licensing

这个文件夹下是μCOS-II使用的许可证。

Software

CPU:STM32标准外设库。

EvalBoards: Micrium官方评估板相关代码。

uC-CPU:     基于Micrium官方评估板的uCOS-II移植代码。

uC-LCD:     Micrium官方评估板LCD驱动代码。

uC-LIB:     Micrium官方的一个库代码。

uCOS-II:    μC/OS-II源代码。

uC-Probe:   和uC-Probe相关代码。

在这个文件夹下有好多文件夹,我们只关心μCOS-II这个文件夹下的内容,在uCOS-II这个文件夹下分别有:Doc,Ports,Source三个文件夹,我们需要的是

Micrium\Software\uCOS-II\Ports\ARM-Cortex-M3\Generic\RealView 下os_cpu_c.c,os_cpu.h,os_cpu_a.asm这三个文件(图4)和Micrium\Software\uCOS-II\Source下的所有文件(图5),在之后创建工程目录结构的时候会将这些文件复制到相应目录下,并且在工程里面会添加进去相关文件。

图4:

 

图5:

 

 

二.STM32固件库V3.5.0文件结构介绍

上面的图示只是简单的将大部分内容的文件夹展现了出来,接下来介绍一下这些文件夹都存放的什么文件:

STM32F10x_StdPeriph_LibV3.5.0——————ST公司针对STM32提供的函数接口

_htmresc——————CMSIS内核和ST公司Logo

Libraries——————固件库

CMSIS——————Cortex内核软件接口标准

Core_Support——————为采用Cortex-M3核设计SOC的芯片商设计的芯片外设提供一个进入M3内核的接口

STM32F10x——————定义寄存器的地址及使用的结构封装,设备外设访问层,配置时钟频率相应的头文件

startup——————由汇编编写的系统启动文件,不同的文件对应不同的芯片型号

arm————————ARM编译器启动文件

gcc_ride7——————GCC编译器启动文件

iar——————IAR编译器启动文件

TrueSTUDIO——————TrueSTUDIO编译器启动文件

STM32F10x_StdPeriph_Driver——————CMSIS的设备外设函数,由stm32f10x_ppp.c或stm32f10x_ppp.h文件组成,ppp表示外设名称,每个外设驱动库函数对应一个头文件和源文件

STM32F10x_StdPeriph_Example——————标准外设库驱动的完整例程

STM32F10x_StdPeriph_Template————————官方的一个库工程模板

Utilities————————包含了用于STM3210B-EVAL和STM3210E-EVAL评估板的专用驱动

三.移植环境和准备工作

我这里移植的环境:

硬件:STM32F103VC芯片,ARM Cortex-M3内核

软件:μCOS-II源码版本V2.86

STM32固件库版本V3.5.0

Keil uvision5集成开发环境

准备工作:

创建UCOS-II_Project工程存放文件的文件夹目录结构,树形结构见(图6

图6:

 

创建好存放源码文件的文件夹结构之后,现在我们开始复制源码到创建好的文件夹里面:

CMSIS:在这个文件夹下面存放内核硬件抽象层文件,复制(图7)文件到该目录下

图7:

 

MDK:该文件夹下存放创建好的keil工程相关文件,在之后创建工程的时候会用到。

CPU:在这个文件夹下存放的是μCOS-II和CPU架构之间的文件,复制uCOS-II\Cpu目录下文件(图8)到该目录下

图8:

 

STM32:

 inc:在这个文件夹下存放STM32固件库的.h文件,复制STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver\inc目录下文件(图9)到该目录下

图9:

 

src:在这个目录下存放STM32固件库的.c文件,复制STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver\src目录下文件(图10)到该目录下

图10:

 

UCOSII

src:在这个文件夹下存放μCOS-II的源码,复制uCOS-II\Source目录下文件(图11)到该目录下

图11:

 

USER:该文件夹用来存放创建好keil工程之后我们自己所写的板级硬件初始化文件和main函数文件等相关应用文件。

好了,基本的准备工作就做好了。

四.创建STM32的keil工程

点击keil开发软件的Project,选择下面的New μVision Project...(图12

图12:

新建工程地址选为:UCOS-II_Project\MDK  (图13

图13:

 

芯片选择(图14

图14:

 

修改工程名称(图15)

图15:

 

创建工程目录和向工程目录下添加文件(图16

图16:

修改编译输出文件目录路径(图17

图17:

创建完成之后的工程总体目录结构(图18),在这里创建好的工程里面cpu,ucosii工程目录里面没有文件,在之后的移植过程里会将关于ucosii的文件添加进去。

图18:

 

    创建好工程之后,需要加入main函数主文件和板级硬件初始化函数的文件,在这里我将已经写好的bsp.c,debug-uart.c,ucos-main.c文件已经加入工程里了,在下面贴出代码:

/*bsp.c*/
#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include "stm32f10x.h"

static void bsp_rcc_init (void) 
{    
    uint32_t  rcc_to;  
	
    RCC_DeInit();                                                /*  Reset the RCC clock config to the default reset state   */

    RCC_HSEConfig(RCC_HSE_ON);                                   /*  HSE Oscillator ON*/        
    rcc_to = BSP_RCC_TO_VAL;
  
    while ((rcc_to > 0) && (RCC_WaitForHSEStartUp() != SUCCESS)) {               /* Wait until the oscilator is stable                       */
      rcc_to--;
    }
   
    FLASH_SetLatency(FLASH_Latency_2);
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
    
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);         /* Fcpu = (PLL_src * PLL_MUL) = (8 Mhz / 1) * (9) = 72Mhz*/ 
    RCC_PLLCmd(ENABLE);

    rcc_to = BSP_RCC_TO_VAL;
	
    while ((rcc_to > 0) &&
      (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)) {
        rcc_to--;
    }

    RCC_HCLKConfig(RCC_SYSCLK_Div1);                             /* Set system clock dividers*/                            
    RCC_PCLK2Config(RCC_HCLK_Div1);    
    RCC_PCLK1Config(RCC_HCLK_Div2);    
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);

    FLASH_SetLatency(FLASH_Latency_2);                           /* Embedded Flash Configuration*/
    FLASH_HalfCycleAccessCmd(FLASH_HalfCycleAccess_Disable);
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
  
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
}

static void bsp_led_init()
{
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
  
  //PE8,9 ÍÆÍìÊä³ö
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOE, &GPIO_InitStructure);
}

void  bsp_led_on (uint8_t led_id)
{
	switch (led_id) {
		case 0:
			GPIO_ResetBits(GPIOE, GPIO_Pin_8|GPIO_Pin_9);
			break;
		case 1:
			GPIO_ResetBits(GPIOE, GPIO_Pin_8);
			break;
		case 2:
			GPIO_ResetBits(GPIOE, GPIO_Pin_9);
			break;		 
		default:
			break;
	}
}
void  bsp_led_off (uint8_t led_id)
{
	switch (led_id) {
		case 0:
			GPIO_SetBits(GPIOE, GPIO_Pin_8|GPIO_Pin_9);
			break;
		case 1:
			GPIO_SetBits(GPIOE, GPIO_Pin_8);
			break;
		case 2:
			GPIO_SetBits(GPIOE, GPIO_Pin_9);
			break;		 
		default:
			break;
	}
}
void  bsp_led_toggle (uint8_t led_id)
{
	uint16_t reg_val;
	switch (led_id) {
		case 0:
			 reg_val = GPIO_ReadOutputData(GPIOE);
			 reg_val ^= (GPIO_Pin_8|GPIO_Pin_9);
			 reg_val &= (GPIO_Pin_8|GPIO_Pin_9);
			 GPIO_SetBits(GPIOE, reg_val);
			 reg_val  = (~reg_val);
			 reg_val &= (GPIO_Pin_8|GPIO_Pin_9);                          
			 GPIO_ResetBits(GPIOE, reg_val);
			 break;
		case 1:
			 reg_val = GPIO_ReadOutputData(GPIOE);
			 reg_val ^= GPIO_Pin_8;
			 GPIO_SetBits(GPIOE,reg_val&GPIO_Pin_8);
			 GPIO_ResetBits(GPIOE,(~reg_val)&GPIO_Pin_8);
			 break;
		case 2:
			 reg_val = GPIO_ReadOutputData(GPIOE);
			 reg_val ^= GPIO_Pin_9;
			 GPIO_SetBits(GPIOE,reg_val&GPIO_Pin_9);
			 GPIO_ResetBits(GPIOE,(~reg_val)&GPIO_Pin_9);
			 break;
		default:
			 break;
	}
}

void SysTickInit(void)
{
	//every msec got int
	if (SysTick_Config(SystemCoreClock / OS_TICKS_PER_SEC))
  { 
    /* Capture error */ 
    while (1);
  }
}

void bsp_init(void){
	bsp_rcc_init();  
	bsp_led_init();
	
	/* Set the Vector Table base address at 0x08000000 */
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);

  /* Configure the NVIC Preemption Priority Bits */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
}
#include 
      
      
       
       
#include 
       
       
         #include "stm32f10x.h" void dbg_uart_gpio_init(void){ GPIO_InitTypeDef gpio_init; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); /* Configure GPIOA.9 as push-pull */ gpio_init.GPIO_Pin = GPIO_Pin_9; gpio_init.GPIO_Speed = GPIO_Speed_50MHz; gpio_init.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &gpio_init); /* Configure GPIOA.10 as input floating */ gpio_init.GPIO_Pin = GPIO_Pin_10; gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &gpio_init); } void dbg_uart_init(void){ USART_InitTypeDef usart_init; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); usart_init.USART_BaudRate = 115200; usart_init.USART_WordLength = USART_WordLength_8b; usart_init.USART_StopBits = USART_StopBits_1; usart_init.USART_Parity = USART_Parity_No ; usart_init.USART_HardwareFlowControl = USART_HardwareFlowControl_None; usart_init.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &usart_init); USART_Cmd(USART1, ENABLE); } void dbg_uart_int_init(void){ NVIC_InitTypeDef NVIC_InitStructure; /* Enable the USART1 Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); USART_ITConfig(USART1, USART_IT_TC, DISABLE); } void dbg_setup_uart(){ dbg_uart_gpio_init(); dbg_uart_init(); dbg_uart_int_init(); } int fputc(int ch, FILE * f) { USART_SendData(USART1, (uint8_t)ch); while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET ); return ch; } void uart1_sendstring(uint8_t* cp) { while((*cp)!='\0') { Usart1_Send_isr(*cp); cp++; } } void Usart1_Send_isr(uint8_t ch){ USART_SendData(USART1, (uint8_t)ch); while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET ); } #include 
        
          #include 
         
           #include 
          
            #include "task_cfg.h" #include "ucos-main.h" #include "debug-uart.h" #include "bsp.h" #include "App_Sem.h" #include "stm32f10x_usart.h" static void App_TaskStart (void *p_arg); extern void app_task_create (void); extern uint8_t SendFlag; extern uint8_t Open_Send_Flag; //app stack static OS_STK App_TaskStartStk[APP_TASK_START_STK_SIZE]; /* main */ int main (void) { INT8U os_err; //BSP_IntDisAll(); /* Disable all ints until we are ready to accept them. */ OSInit(); /* Initialize "uC/OS-II, The Real-Time Kernel". */ os_err = OSTaskCreateExt((void (*)(void *)) App_TaskStart, /* Create the start task. */ (void * ) 0, (OS_STK * )&App_TaskStartStk[APP_TASK_START_STK_SIZE - 1], (INT8U ) APP_TASK_START_PRIO, (INT16U ) APP_TASK_START_PRIO, (OS_STK * )&App_TaskStartStk[0], (INT32U ) APP_TASK_START_STK_SIZE, (void * )0, (INT16U )(OS_TASK_OPT_STK_CLR | OS_TASK_OPT_STK_CHK)); #if (OS_TASK_NAME_SIZE >= 11) OSTaskNameSet(APP_TASK_START_PRIO, (INT8U *)"Start Task", &os_err); #endif OSStart(); /* Start multitasking (i.e. give control to uC/OS-II). */ return (0); } /* App_TaskStart */ static void App_TaskStart (void *p_arg) { (void)p_arg; bsp_init(); /* Initialize BSP functions.*/ SysTickInit(); /* Initialize the SysTick.*/ dbg_setup_uart(); printf("uCos-II V2.86 FM.\r\n"); #if (OS_TASK_STAT_EN > 0) OSStatInit(); /* Determine CPU capacity.*/ #endif printf("Create App Task.\r\n"); app_task_create(); /*body*/ while(1){ if(SendFlag){ USART_ITConfig(USART1, USART_IT_TC, ENABLE); SendFlag = 0; Open_Send_Flag = 1; } bsp_led_toggle(0); //printf("uCos-II Test.\r\n"); OSTimeDly(OS_TICKS_PER_SEC); } } 
           
          
         
       
      
      
     
     
    
    
   
   

五.移植μC/OS-II到工程

 将UCOS-II_Project\CPU目录下的所有文件添加到工程里的cpu文件夹下,再将UCOS-II_Project\UCOSII\src目录下所有文件添加到工程里的ucosii文件夹下。(图19

图19:

 

添加完成之后接下来进行一些代码的修改,大致的修改内容会在接下来介绍,细微的代码修改,需要在编译过程中发现去修改。

1.在ucos_ii.h文件中,删除包含头文件:#include <app_cfg.h>

2.在os_cpu_c.c文件中,添加包含STM32的头文件:#include "stm32f10x.h"

  删除所有Hook函数

  删除

  #if OS_TMR_EN > 0

      static INT16U OSTmr(tr);

  #endif

3.在os_core.c文件中,大概在line 589行处,删除:

  #if OS_DEBUG_EN > 0

      OSDebugInit();

  #endif

4.找到最关键的os_cfg.h文件

5.在includes.h文件中加入包含头文件:#include <ucos_ii.h>

6.修改startup下面的startup_stm32f10x_hd.s文件:

  将PendSVHandler修改为OS_CPU_PendSVHandler

  将SysTickHandler修改为OS_CPU_SysTickHandler

六.创建任务进行测试

    这里的任务按照ucos-ii的创建任务函数去创建,这里贴出我的截图,可以参考:

    

#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include "task_cfg.h"
#include "ucos-main.h"
#include "debug-uart.h"
#include "bsp.h"
#include "App_Sem.h"
#include "stm32f10x_usart.h"

static void App_TaskStart (void *p_arg);
extern void app_task_create (void);

extern uint8_t SendFlag;
extern uint8_t Open_Send_Flag;
//app stack
static OS_STK App_TaskStartStk[APP_TASK_START_STK_SIZE];

/*
 main
*/
int  main (void)
{
    INT8U  os_err;
	
    //BSP_IntDisAll();                                            /* Disable all ints until we are ready to accept them.  */

    OSInit();                                                   /* Initialize "uC/OS-II, The Real-Time Kernel".         */

    os_err = OSTaskCreateExt((void (*)(void *)) App_TaskStart,  /* Create the start task.                               */
                             (void          * ) 0,
                             (OS_STK        * )&App_TaskStartStk[APP_TASK_START_STK_SIZE - 1],
                             (INT8U           ) APP_TASK_START_PRIO,
                             (INT16U          ) APP_TASK_START_PRIO,
                             (OS_STK        * )&App_TaskStartStk[0],
                             (INT32U          ) APP_TASK_START_STK_SIZE,
                             (void          * )0,
                             (INT16U          )(OS_TASK_OPT_STK_CLR | OS_TASK_OPT_STK_CHK));

#if (OS_TASK_NAME_SIZE >= 11)
    OSTaskNameSet(APP_TASK_START_PRIO, (INT8U *)"Start Task", &os_err);
#endif

    OSStart();                                                  /* Start multitasking (i.e. give control to uC/OS-II).  */

    return (0);
}


/*
	App_TaskStart
*/

static void App_TaskStart (void *p_arg)
{
  (void)p_arg;

  bsp_init();                                          /* Initialize BSP functions.*/
  SysTickInit();                                       /* Initialize the SysTick.*/
	dbg_setup_uart();
  printf("uCos-II V2.86 FM.\r\n");

#if (OS_TASK_STAT_EN > 0)
  OSStatInit();                                               /* Determine CPU capacity.*/
#endif
	printf("Create App Task.\r\n");	
	app_task_create();
	/*body*/
	while(1){
		if(SendFlag){
		USART_ITConfig(USART1, USART_IT_TC, ENABLE);
			SendFlag = 0;
			Open_Send_Flag = 1;
	}
		bsp_led_toggle(0);
		//printf("uCos-II Test.\r\n");	
		OSTimeDly(OS_TICKS_PER_SEC);
	}
}
#include "includes.h"
#include "task_cfg.h"
#include "App_Sem.h"

static OS_STK App_TaskEx1Stk[APP_TASK_EX1_STK_SIZE];
OS_EVENT* gEventSem;

void App_Task_Ex1 (void *p_arg){
	INT8U err;
	
	(void)p_arg;
	gEventSem = OSSemCreate(1);
	printf("Create sem ok.\r\n");
	while(1){
		OSSemPend(gEventSem,0,&err);
		printf("Task_Ex1 Got sem signal.\r\n");
	}
}

void rcv_data_proc(unsigned char dat){
	if(dat == 0x01){
		OSSemPost(gEventSem);
	}
}


/*
Create APP Task
*/
void app_task_create (void){
	INT8U  os_err;
	
	os_err = OSTaskCreate((void (*)(void *))App_Task_Ex1,
		                    (void*)0,
												(OS_STK*)&App_TaskEx1Stk[APP_TASK_EX1_STK_SIZE-1],
												(INT8U)APP_TASK_EX1_PRIO												 
	                     );
	#if (OS_TASK_NAME_SIZE >= 11)
    OSTaskNameSet(APP_TASK_EX1_PRIO, (INT8U *)"Ex1 Task", &os_err);
  #endif
}

     
     
    
    
   
   

七.错误总结:

   1.加入printf之后程序死于BEAB BKPT 0XAB 汇编代码的时候,需要在keil编译器里面修改target下面的USE Mcrolib,选择 Use MicroLIB ,也就是C微库。

   2.遇到warning:  #223-D: function "assert_param" declared implicitly的警告时候,MDK的在工程上点右键,选择options,选择C/C++选项,在defined的框里填上USE_STDPERIPH_DRIVER就可以了。



 


  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值