最近做项目,需要用到ucos,拿到师兄的程序后,感觉非常失望,师兄用的是直接从官网上下载的那种移植好的程序,起码在我看来很乱,有很多定义了的东西都是没有用到的,总而言之,我不想用那个很乱的程序,于是我便自己从网上找教程,尝试着移植了一下,还好最终成功了。我并没有加太多的注释,是因为我也初学,对于那些系统里的函数,我实在也没有资格注释,而我自己写的那几个函数,又实在太简单了,没有注释的必要。如果有什么函数不明白,可以百度一下,我试了试,发现基本上都是能百度的到的。对这个系统不明白的话,最好也看看邵贝贝老师的那本嵌入式实时操作系统uCOS-II吧。
我毕竟也是个菜鸟营中的菜鸟,其中肯定有不足与错误之处,还望大伙发现的话能够不吝赐教。
我的完整工程代码的下载链接如下:
我是参考着百度文库上的一篇文章来的,步骤的话,基本上差不多,但是我还是稍微按照自己的喜好改了改的。该文章链接如下(点击打开链接)
建立工程:
我建了7个文件目录,分别为APP,BSP,CMSIS,FWlib,Project,uCOS_ii,User.如下图:
APP中应用程序文件,就是我自己写的任务文件;
BSP存放外设硬件驱动程序,也就是自己写的一些硬件初始化、时钟初始化什么的程序。
CMSIS用来存放cpu和系统的相关的文件.这里面还有个startup文件夹,用来存放启动文件。
工程建立在Project文件夹下,也就是新建工程的时候,workplace什么的选择Project.
Project::
复制 STM32F10x_StdPeriph_Lib_V3.5.0\ProjectSTM32F10x_StdPeriph_Template\EWARM\stm32f10x_flash.icf 到Project下
CMSIS::
复制固件库\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\CoreSupport 目录下的core_cm3.c和core_cm3.h 到工程文件夹下的CMSIS目录中。
复制固件库 STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x 目录下的 stm32f10x.h 到工程文件夹下的CMSIS目录中
在固件库\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\iar 目录中选取相应的开始文件,这里我选取的是startup_stm32f10x_md.s,复制到CMSIS下的startup文件夹内。
User::
复制固件库\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x 目录下的 system_stm32f10x.c、system_stm32f10x.h到User中,
复制固件库\STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Template目录中的stm32f10x_conf.h、stm32f10x_it.c、stm32f10x_it.h三个文件到User中.
在User下新建 main.c 和includes.h 文件.
FWlib::
复制固件库 \STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver下的inc和src到 FWlib 下。
uCOS_ii::
在工程目录 uCOS_ii 下建立Ports目录,并复制 ucos 解压目录\Micrium\Software\uCOS-II\Ports\arm-cortex-m3\Generic\IAR下的所有文件到此文件夹中。 在工程目录uCOS_ii 下建立Source目录,并复制 ucos 解压目录\Micrium\Software\uCOS-II\Source 下的所有文件到此文件夹中。
APP::
接着,os_cfg.h,用来配置ucos各个功能,app_cfg.h用来配置任务所需的各项参数。
这两个文件我是从\Micrium\Software\EvalBoards\ST\STM32F103ZE-SK\IAR\OS-Probe-LCD目录中借鉴的,用户也可以根据自己的需求来更改,具体更改方法网上有很多说明这里就不多说了。将这两个文件复制到APP目录下。
在APP下新建两个文件,分别为azhu_led.h和azhu_led.c,这是我写的用来实现LED灯亮灭的程序及其头文件。
BSP::
在BSP下新建两个文件BSP.h,,BSP.c,这是我自己写的配置GPIO啊什么硬件初始化,时钟初始化的程序。
建立工程:
建立一个空的工程,取名为azhuty,保存在Project文件夹下。向工程添加Group以及files如下图所示。
选取相应的芯片:右键单击azhuty-Debug,选择Options,在target里选择相应芯片。如下图所示
接着,单击C/C++Compiler,单击Proprocessor,配置如下:
哦,目录那里没有显示全,全部的是如下所示:
$PROJ_DIR$\..\APP
$PROJ_DIR$\..\BSP
$PROJ_DIR$\..\CMSIS
$PROJ_DIR$\..\CMSIS\startup
$PROJ_DIR$\..\FWlib\inc
$PROJ_DIR$\..\FWlib\src
$PROJ_DIR$\..\uCOS_ii\Ports
$PROJ_DIR$\..\uCOS_ii\Source
$PROJ_DIR$\..\User
接着单击Linker,配置如下:
接着,单击Debugger,配置如下:
至此,工程新建并配置完毕。
移植配置:
由于这个版本是官方已经移植好的,我们所需要修改的东西很少。
打开startup_stm32f10x_md.s (注意要去掉文件默认的只读属性,否则修改不成功)
把所有出现PendSV_Handler的地方替换成OS_CPU_PendSVHandler
把所有出现SysTick_Handler的地方替换成OS_CPU_SysTickHandler
之所以要修改这两个地方,是因为我们一般的中断向量用的是CMSIS给的,而ucos的中断向量是自己写的,我们修改CMSIS的向量表来统一这两个向量。
还要修改os_cfg.h中的
#define OS_APP_HOOKS_EN 0 /* Application-defined hooks are called from the uC/OS-II hooks*/
#define OS_ARG_CHK_EN 0 /*Enable (1) or Disable (0) argument checking */
#define OS_TMR_EN 0 /* Enable (1) or Disable (0) code generation for TIMERS */
这三个地方,这些功能我们暂时不用,要用的话要定义一些东西,这里不做介绍,参见邵老师的书吧。
还缺少一个函数定义如下
INT32U OS_CPU_SysTickClkFreq(void)
{
RCC_ClocksTypeDef rcc_clocks;
RCC_GetClocksFreq(&rcc_clocks);
return ((INT32U)rcc_clocks.HCLK_Frequency); //return SYSCLK_FREQ_72MHz;
}
这个函数主要是用来获得cpu频率,用来确定系统滴答的时间。如果知道系统时钟是多少可以不用这么复杂,
直接
INT32U OS_CPU_SysTickClkFreq(void)
{
return 72000000;
}
也可以。
因为我知道我用的 stm32f103vbt6 时钟是72MHz,所以我直接把后面那个简单的函数复制到了os_cpu_c.c中。
我自己添加的文件内含代码如下:
#ifndef __AZHULED_H__
#define __AZHULED_H__
#include "stm32f10x.h"
#include "ucos_ii.h"
void Azhu_LED1(void);
void Azhu_LED2(void);
void Azhu_LED3(void);
void Azhu_LED4(void);
#endif
#include "azhu_led.h"
void Azhu_LED1()
{
GPIO_ResetBits(GPIOA,GPIO_Pin_10);
OSTimeDly(500);
GPIO_SetBits(GPIOA,GPIO_Pin_10);
OSTimeDly(500);
}
void Azhu_LED2()
{
GPIO_ResetBits(GPIOA,GPIO_Pin_11);
OSTimeDly(500);
GPIO_SetBits(GPIOA,GPIO_Pin_11);
OSTimeDly(500);
}
void Azhu_LED3()
{
GPIO_ResetBits(GPIOA,GPIO_Pin_12);
OSTimeDly(500);
GPIO_SetBits(GPIOA,GPIO_Pin_12);
OSTimeDly(500);
}
void Azhu_LED4()
{
GPIO_ResetBits(GPIOA,GPIO_Pin_13);
OSTimeDly(500);
GPIO_SetBits(GPIOA,GPIO_Pin_13);
OSTimeDly(500);
}
#ifndef __BSP_H
#define __BSP_H
#include "stm32f10x.h"
#include "ucos_ii.h"
void BSP_Init(void);
void Azhu_LED_GPIO_Init(void);
void Azhu_NVIC_Config(void);
#endif // __BSP_H
#include "BSP.h"
void BSP_Init()
{
SystemInit();
Azhu_LED_GPIO_Init();
Azhu_NVIC_Config();
}
//下面是初始化控制LED灯的GPIO的程序,
//我是用的GPIOA端口,其中,
//GPIO_Pin_10 控制LED1,
//GPIO_Pin_11 控制LED2,
//GPIO_Pin_12 控制LED3,
//GPIO_Pin_13 控制LED4.
void Azhu_LED_GPIO_Init()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void Azhu_NVIC_Config()
{
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
}
#ifndef __INCLUDES_H__
#define __INCLUDES_H__
#include "ucos_ii.h"
#include "BSP.h"
#include "azhu_led.h"
#endif
#include "includes.h"
OS_STK startup_stk[STARTUP_TASK_STK_SIZE];
OS_STK task1_stk[TASK1_STK_SIZE];
OS_STK task2_stk[TASK2_STK_SIZE];
OS_STK task3_stk[TASK3_STK_SIZE];
OS_STK task4_stk[TASK4_STK_SIZE];
static void startup(void *p_arg);
static void task1(void *p_arg);
static void task2(void *p_arg);
static void task3(void *p_arg);
static void task4(void *p_arg);
u8 os_err;
int main(void)
{
OSInit();
OSTaskCreate(startup,
(void *)0,
&startup_stk[STARTUP_TASK_STK_SIZE-1],
STARTUP_TASK_PRIO);
OSStart();
return 0;
}
static void startup(void *p_arg)
{
BSP_Init();
OS_CPU_SysTickInit(); //初始化时钟滴答
os_err = OSTaskCreate(task1,
(void *)0,
(OS_STK *)&task1_stk[TASK1_STK_SIZE - 1],
(INT8U)TASK1_PRIO);
os_err = OSTaskCreate(task2,
(void *)0,
(OS_STK *)&task2_stk[TASK2_STK_SIZE - 1],
(INT8U)TASK2_PRIO);
os_err = OSTaskCreate(task3,
(void *)0,
(OS_STK *)&task3_stk[TASK3_STK_SIZE - 1],
(INT8U)TASK3_PRIO);
os_err = OSTaskCreate(task4,
(void *)0,
(OS_STK *)&task4_stk[TASK4_STK_SIZE - 1],
(INT8U)TASK4_PRIO);
OSTaskDel(OS_PRIO_SELF);
}
static void task1(void *p_arg)
{
while(1)
{
Azhu_LED1();
}
}
static void task2(void *p_arg)
{
while(1)
{
Azhu_LED2();
}
}
static void task3(void *p_arg)
{
while(1)
{
Azhu_LED3();
}
}
static void task4(void *p_arg)
{
while(1)
{
Azhu_LED4();
}
}