使用IAR移植ucos到stm32的步骤

更新时间:2024-03-05 05:35:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

芯片型号stm32f103ve,编译器IAR for ARM 6.3

准备材料

在st官网上下载最新的固件库(现在是v3.5.0),这个库作用非常大,可以帮我们快速开发出想要的功能,但是网上有很多人说这个库有漏洞,本人水平有限就不得而知了,这里直接上地址。

http://www.st.com/internet/com/SOFTWARE_RESOURCES/SW_COMPONENT/FIRMWARE/stm32f10x_stdperiph_lib.zip 解压后得到目录如下图

在ucos官网上下载移植stm32移植版的ucosii代码,这个需要注册一下,不多说直接上接上地址

http://micrium.com/download/uCOSII-ST-STM32F103ZE-SK.exe 下载安装后得到目录如下图

建立工程

首先建三个文件目录:CMSIS用来存放cpu和系统的相关的文件、STM32F10x_StdPeriph_Driver用来存放cpu的硬件驱动、ucosii用来存放ucos的源代码。 复制固件库\\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、system_stm32f10x.c、system_stm32f10x.h三个文件到工

程文件夹下的CMSIS目录中。

在固件库\\STM32F10x_StdPeriph_Lib_V3.5.0\\Libraries\\CMSIS\\CM3\\DeviceSupport\\ST\\ STM32F10x\\startup\\iar目录中选取相应的开始文件,这里我选取的是startup_stm32f10x_hd.s复制到到工程文件夹下的CMSIS目录中。

复制固件库\\STM32F10x_StdPeriph_Lib_V3.5.0\\Project\\STM32F10x_StdPeriph_Template目录中的stm32f10x_conf.h、stm32f10x_it.c、stm32f10x_it.h三个文件到工程文件夹下的CMSIS目录中。其中stm32f10x_conf.h是驱动的配置文件,可以根据实际需求注释掉不用的驱动,默认是全部启用的,这里就不做改变了。stm32f10x_it.c、stm32f10x_it.h是中断的相应函数所在的文件,但仅给出了一部分,如果用到其他的中断可以打开选取的startup_stm32f10x_hd.s文件,来确定相应的函数名称。

在工程目录STM32F10x_StdPeriph_Driver下面建立inc目录,并复制固件库

\\STM32F10x_StdPeriph_Lib_V3.5.0\\Libraries\\STM32F10x_StdPeriph_Driver\\inc目录下的所有文件到此文件夹中

在工程目录STM32F10x_StdPeriph_Driver下面建立src目录,并复制固件库

\\STM32F10x_StdPeriph_Lib_V3.5.0\\Libraries\\STM32F10x_StdPeriph_Driver\\src目录下的所有文件到此目录中

在工程目录ucosii下建立ports目录,并复制ucos安装目录\\Micrium\\Software\%uCOS-II\\ Ports\\arm-cortex-m3\\Generic\\IAR下的所有文件到此文件夹中。

在工程目录ucosii下建立source目录,并复制ucos安装目录\\Micrium\\Software\%uCOS-II \\Source下的所有文件到此文件夹中。

下面还需要系统运行所需的几个文件,一个是os_cfg.h,用来配置ucos各个功能,一个是app_cfg.h用来配置任务所需的各项参数。这两个文件我是从\\Micrium\\Software\\EvalBoards\\ ST\\STM32F103ZE-SK\\IAR\\OS-Probe-LCD目录中借鉴的,用户也可以根据自己的需求来更改,具体更改方法网上有很多说明这里就不多说了。将这两个文件复制到工程根目录下。 我们还缺少一个main函数的文件,我们新建立一个文本文档,取名为test.c

最后我们还缺少一个连接时的配置文件,这个文件我是从IAR给的例程里借鉴的,复制\\IAR Systems\\Embedded Workbench 6.0 Evaluation\\arm\\examples\\ST\\STM32F10x\\IAR-STM32-SK\\ GettingStarted\\config目录下的STM32F10x_FLASH.icf文件到工程根目录下。 至此我们所有的文件已经准备好了。

建立和配置工程

打开IAR建立一个ARM的空工程 取名test。向工程添加文件,格式我是按照目录形式安排的这个随便大家,直接上图。

配置工程: 选取相应的芯片

添加相应的包含目录和宏定义 我的包含目录为 $PROJ_DIR$\\

$PROJ_DIR$\\CMSIS

$PROJ_DIR$\\STM32F10x_StdPeriph_Driver\\inc $PROJ_DIR$\\STM32F10x_StdPeriph_Driver\\src $PROJ_DIR$\%ucosii\\ports $PROJ_DIR$\%ucosii\\source

需要的宏定义

USE_STDPERIPH_DRIVER STM32F10X_HD

其中USE_STDPERIPH_DRIVER表示要使用固件库,TM32F10X_HD表示选取的芯片为大容量芯片,这两个宏定义也可以在stm32f10x.h中的70行和105行取消相应的注释来选择,两种方法二选一。

选择链接配置文件

最后配置一下仿真,就此完成。

移植配置

由于这个版本是官方已经移植好的,我们所需要修改的东西很少只有两个地方。 打开startup_stm32f10x_hd.s(注意要去掉文件默认的只读属性,否则修改不成功) 把所有出现PendSV_Handler的地方替换成OS_CPU_PendSVHandler 把所有出现SysTick_Handler的地方替换成OS_CPU_SysTickHandler

之所以要修改这两个地方,是因为我们一般的中断向量用的是CMSIS给的,而ucos的中断向量是自己写的,我们修改CMSIS的向量表来统一这两个向量这种方法最简单,当然你也可以,修改ucos系统的函数名,这种方法我没有试,不过我见过另一个同事这么修改的也成功了(我不推荐这种方法,因为不知道修改ucos函数调用复杂,修改以后可能会编译出错,有心情的可以试一下)。

当然也有网上别人的移植教程是重写void OS_CPU_SysTickHandler(void); void OS_CPU_SysTickInit(void);两个函数,同时替换了PendSV_Handler。这种方法也可以。 具体再深一步的话要研究这几个函数在系统中的作用,可以参见邵老师的书或者百度,这里不多说了(因为我说不明白-_-!)。

编译一下,咦发现出错了,仔细研究发现是因为core_cm3.h中的函数声明和intrinsics.h中的函数声明重复了,这里把1049行#elif (defined (__ICCARM__)) 直接修改#elif (defined (__ICCARM__USR)) 不让编译器编译。 还要修改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; }

也可以。

当然还有个错误是缺少main函数,下面我们就来写。

首先把app_cfg.h所有内容删掉替换成下面的(因为这个文件是借鉴的下面要自己写了) #ifndef __APP_CFG_H__ #define __APP_CFG_H__

/* task stack size */

#define STARTUP_TASK_STK_SIZE 128 #define TASK1_STK_SIZE 128 #define TASK2_STK_SIZE 128 #define TASK3_STK_SIZE 128 #define TASK4_STK_SIZE 128

/* task priority */

#define STARTUP_TASK_PRIO 4 #define TASK1_PRIO 5 #define TASK2_PRIO 6 #define TASK3_PRIO 7 #define TASK4_PRIO 8 #endif

这个文件主要就是每个任务的优先级和堆栈大小。

我们建立5个任务,其中一个是启动任务,其余四个分别闪一个led等。代码如下。 #include \#include \

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]; u8 os_err;

static void task1(void *p_arg) {

for (;;) {

GPIO_WriteBit(GPIOA,GPIO_Pin_4 ,Bit_SET); OSTimeDly(500);

GPIO_WriteBit(GPIOA,GPIO_Pin_4 ,Bit_RESET); OSTimeDly(500); } }

static void task2(void *p_arg) {

for (;;) {

GPIO_WriteBit(GPIOA,GPIO_Pin_5 ,Bit_SET); OSTimeDly(500);

GPIO_WriteBit(GPIOA,GPIO_Pin_5 ,Bit_RESET); OSTimeDly(500); } }

static void task3(void *p_arg) {

for (;;) {

GPIO_WriteBit(GPIOA,GPIO_Pin_6 ,Bit_SET); OSTimeDly(500);

GPIO_WriteBit(GPIOA,GPIO_Pin_6 ,Bit_RESET); OSTimeDly(500); } }

static void task4(void *p_arg) {

for (;;) {

GPIO_WriteBit(GPIOA,GPIO_Pin_7 ,Bit_SET); OSTimeDly(500);

GPIO_WriteBit(GPIOA,GPIO_Pin_7 ,Bit_RESET); OSTimeDly(500); } }

static void startup(void *p_arg) {

OS_CPU_SysTickInit(); //初始化时钟滴答

os_err = OSTaskCreate(task1, //任务1

(void *)0, //不带参数

(OS_STK *)&task1_stk[TASK1_STK_SIZE - 1],//堆栈指针 (INT8U)TASK1_PRIO); //优先级

os_err = OSTaskCreate(task2, //任务2 (void *)0, //不带参数

(OS_STK *)&task2_stk[TASK2_STK_SIZE - 1],//堆栈指针 (INT8U)TASK2_PRIO); //优先级

os_err = OSTaskCreate(task3, //任务3 (void *)0, //不带参数

(OS_STK *)&task3_stk[TASK3_STK_SIZE - 1],//堆栈指针 (INT8U)TASK3_PRIO); //优先级 //

os_err = OSTaskCreate(task4, //任务4 (void *)0, //不带参数

(OS_STK *)&task4_stk[TASK4_STK_SIZE - 1],//堆栈指针 (INT8U)TASK4_PRIO);

OSTaskDel(OS_PRIO_SELF); //任务建立完成删掉这个任务 }

所用main函数为 int main(void) {

GPIO_InitTypeDef GPIO_InitStructure;

SystemInit();

NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);

RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA , DISABLE);

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_Init(GPIOA, &GPIO_InitStructure);

OSInit();

OSTaskCreate(startup, (void *)0, &startup_stk[STARTUP_TASK_STK_SIZE-1], STARTUP_TASK_PRIO);

OSStart(); return 0; }

编译通过,下载到目标板上,运行4个灯同时闪了起来.移植成功. 本人刚学stm32 和ucos不久,希望大家能多多指正.

本文来源:https://www.bwwdw.com/article/eqoa.html

Top