logo资料库

UCos-ii_在STM32上的移植详解.pdf

第1页 / 共30页
第2页 / 共30页
第3页 / 共30页
第4页 / 共30页
第5页 / 共30页
第6页 / 共30页
第7页 / 共30页
第8页 / 共30页
资料共30页,剩余部分请下载后查看
stm32标准外设库使用详解.doc
stm32上的ucosii移植详解1.doc
stm32上的ucosii移植详解2.doc
stm32上的ucosii移植详解3.doc
stm32上的ucosii移植详解4.doc
stm32上的ucosii移植详解5.doc
下载代码 stm32 标准外设库是 stm32 全系列芯片的外设驱动,有了它可以大大加速我们 开发 stm32。 首先从 st 公司的网站下载最新的 stm32 标准外设库,写本文时最新的版本是 V3.5.0。 解压该 zip 文件,得到如下文件夹和文件 STM32F10x_StdPeriph_Lib_V3.5.0\ _htmresc Libraries Project Utilities Release_Notes.html stm32f10x_stdperiph_lib_um.chm 其中 Libraries 包含库的源代码,Project 包含 stm32 各个外设的使用范例和一 个工程模板,Utilities 是使用st 公司评估板的例子,stm32f10x_stdperiph_lib_um.chm 教我们怎么用标准外设库。 工程目录结构 既然准备使用 32 位单片机,应该是个不小项目,因此工程目录也应该做个规划。 这里我推荐一下我所使用的目录结构。假设工程名字叫 template,建一个名为 template 的文件夹,该目录下有个 3 个固定文件夹 doc,src,include,doc 用来存 放工程相关的资料文件,src 放源代码,在 src 下每个功能模块一个文件夹,include 放各个模块都要使用的公共头文件。output 放编译输出文件,内含两个子文件夹 obj 和 list。 template\ doc src include output\obj \list
整理库代码 由于 Libraries 下的 CMSIS 文件夹中很多代码是和编译器及芯片相关的,导致 文件夹多且深度大,不利于工程维护,实际上一个项目往往是用固定的编译器和芯 片,因此有必要对库进行整理。 在 src 下建立 libstm32 目录 1. 把 Libraries\STM32F10x_StdPeriph_Driver\下的内容拷贝到 libstm32 目录 下 2. 在 libstm32 目录下建立 cmsis 文件夹,把 Libraries\CMSIS\CM3\CoreSupport\下的 core_cm3.c,core_cm3.h; Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\下的 stm32f10x.h, system_stm32f10x.c,system_stm32f10x.h 拷贝到 cmsis 文件夹中。 3. 根据你所选的芯片类型,将 Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm\下对应的启动 文件拷贝到 cmsis 文件夹中。这里我拷贝的是 startup_stm32f10x_hd.s(大容量型 stm32 芯片的启动文件)。 下面对该库文件做个简单介绍: Libraries\STM32F10x_StdPeriph_Driver\下的内容很好理解就是 stm32 的各个 外设模块驱动代码。 misc.h 和 misc.c 是和 CM3 内核有关的 NVIC 和 SysTick 的驱动代码。 Libraries\CMSIS 下是什么呢?cmsis 英文全称:Cortex Microcontroller Software Interface Standard,是 Cortex 系列处理器硬件抽象层,可以理解为 cortex 内核的软件接口。 core_cm3.c, core_cm3.h 它们的目录名为 CoreSupport,说明这两个文件是 CM3 内核支撑文件,其他使 用 CM3 内核的芯片也可以用,不一定是 stm32。这两个文件用来获取设置 CM3 内 核,配置一些内核寄存器。 stm32f10x.h, system_stm32f10x.c, system_stm32f10x.h 和 startup_stm32f10x_hd.s 在 DeviceSupport 目录下,说明这几个文件是和具体的芯 片有关的,也就是 stm32 芯片的支撑文件。其中 stm32f10x.h 是标准外设库的入口, 使用标准外设库的代码中必须包含该头文件。system_stm32f10x.c, system_stm32f10x.h 这两个文件提供函数用来初始化 stm32 芯片,配置 PLL、系 统时钟和内置 flash 接口。startup_stm32f10x_hd.s 是大容量型 stm32 芯片的启动 文件。
建立工程 使用 keil MDK(我使用 4.12 版)在 template 目录下建立工程,工程名为 template。选一个 stm32 系列的芯片,哪一个都无所谓(我选的是 STM32F101RC, 因为我的板子就是用这个芯片),接下来要注意的是当弹出是否拷贝启动代码到工 程文件夹时要选 No,因为标准外设库里已经有启动代码了。 将 UV4 中 project window 里的顶层目录名改为 template,并将第一个 group 名改为 libstm32。把 libstm32 目录下所有.c 和.s 文件加载到工程里的 libstm32。 在 src 下建立一个 init 目录用来放置系统初始化代码。把 Project\STM32F10x_StdPeriph_Template\下的 stm32f10x_it.c 拷贝到 init 文件夹 中,stm32f10x_it.h,stm32f10x_conf.h 拷贝到 include 文件夹中。 stm32f10x_it.c,stm32f10x_it.h 是中断服务程序文件。stm32f10x_conf.h 是标 准外设库的配置文件,对于工程中不需要的外设,可以注释掉里面的包含的头文件。 这里我建议先仅留下 stm32f10x_gpio.h,stm32f10x_rcc.h,misc.h,用到什么再打 开什么,这样编译起来快一点,当然也可都留着。 使用stm32 标准外设库 事实上,stm32 标准外设库的使用在 stm32f10x_stdperiph_lib_um.chm 中的 How to use the Library 一节中已有说明,下面我把其中的步骤罗列一下: 1. 根据所选芯片,把 Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm 中的启动代码 加到工程中,这一步在上面已经做过了。 2. 在 stm32f10x.h 的 66-73 行,根据所选芯片类型,去掉相应注释,这里我去掉 STM32F10X_HD 行的注释(大容量型 stm32 芯片)。 3. 去掉 105 行的 USE_STDPERIPH_DRIVER 注释,启用 stm32 标准外设库。 4. 在 system_stm32f10x.c 的 110-115 行,根据所选芯片主频,去掉相应注释,默 认 SYSCLK_FREQ_72MHz 注释已去掉,如果你的芯片主频是 72MHz,就不用做 修改了,这里我的芯片是 36MHz,注释 SYSCLK_FREQ_72MHz,去掉 SYSCLK_FREQ_36MHz 注释。
跑马灯程序 现在可以使用 stm32 标准外设库了,下面以一个简单的跑马灯程序说明。 在 init 目录下建立 main.c 作为系统入口。 在 src 下建立一个 bsp 目录用来放置板级支持代码,建立 led.c,led.h。 代码如下: led.h #ifndef _LED_H_ #define _LED_H_ #include #define LED_0 0 #define LED_1 1 #define LED_2 2 void led_init(void); void led_on(uint32_t n); void led_off(uint32_t n); #endif led.c #include "stm32f10x.h" #include "led.h" void led_init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); }
GPIO_SetBits(GPIOC, GPIO_Pin_6); break; GPIO_SetBits(GPIOC, GPIO_Pin_7); break; GPIO_SetBits(GPIOC, GPIO_Pin_8); break; void led_on(uint32_t n) { switch (n) { break; case LED_0: case LED_1: case LED_2: default: } } void led_off(uint32_t n){ switch (n) { } } main.c #include "led.h" static void delay(uint32_t ms){ uint32_t count = 8000; while (count--); count = 8000; } while (ms--) { } GPIO_ResetBits(GPIOC, GPIO_Pin_6); break; GPIO_ResetBits(GPIOC, GPIO_Pin_7); break; case LED_0: case LED_1: case LED_2: default: break; GPIO_ResetBits(GPIOC, GPIO_Pin_8); break;
int main(void){ led_init(); for (;;) { led_on(LED_0); led_off(LED_1); led_off(LED_2); delay(1000); led_off(LED_0); led_on(LED_1); led_off(LED_2); delay(1000); led_off(LED_0); led_off(LED_1); led_on(LED_2); delay(1000); } } 在 project 中建立 init,bsp 组,并将各种代码加入。在工程的 Options 中,c/c++ 选项卡的 Include Paths 中添加.\include; .\src\libstm32\cmsis; .\src\libstm32\inc; .\src\bsp;。 Output 选项卡 Select Folder for Objects 中选.\output\obj。 Listing 选项卡 Select Folder for Listings 中选.\output\list。 Debug 选项卡选 use ULINK Cortex Debugger, Run to main()打钩,这一步大家 可以根据自己手上的仿真器做不同选择。编译运行。
ucosii在stm32 上的移植详解 虽然目前网上已经有不少关于 ucosii 在 stm32 上的移植版本,包括 micrium 也 有官方移植版本。但这些版本具体是怎么移植出来的,又该怎么基于移植好的 ucosii 开发应用软件,网上介绍的并不多。这里介绍一下我的移植经历,希望对大家有所 帮助。 我的移植基本上是从零开始的。首先想要做好移植,有两方面的内容是必须要 了解。1.目标芯片;2.ucosii 内核原理。 虽然我们移植的目标芯片是 stm32,但操作系统的移植基本是针对 Cortex-M3 内核(以下简称 CM3)而言的,所以我们只需了解 CM3 内核就好了。stm32 芯片 就是 CM3 内核加上各种各样的外设。 怎么才能了解 CM3 呢?看一本书<>(宋岩译,网 上多的很)就好了,很多同学可能想,看完这本书移植的新鲜劲都没了,因此我把 该书和移植有关的章节都列了出来,并对其中的重点内容进行介绍,我数了数相关 章节还不到 100 页,就这点内容,总要看了吧。 相关章节如下: chapter2 Cortex-M3 概览 2.1 - 2.9 主要了解 Cortex-M3 的概貌。刚开始看时不用追求全部理解,后面会有详细介 绍,很多内容多看几遍就明白。其中 2.8 指令集,只要了解,CM3 只使用 thumb2 就 ok 了。 chapter3 Cortex-M3 基础 3.1 寄存器组 R0-R12: 通用寄存器 R13: 堆栈寄存器 有两个,MSP 和 PSP,同时只能看见一个 引用 R13 时,引用的是正在使用的那个 MSP:可用于异常服务和应用程序 PSP:只能用于应用程序 系统复位后,用的堆栈指针是 MSP。 R14: 连接寄存器,又名 LR,存储返回地址 R15: 程序计数寄存器,又名 PC 3.2 特殊功能寄存器 程序状态字寄存器组(PSRs) 中断屏蔽寄存器组(PRIMASK, FAULTMASK, BASEPRI) 控制寄存器(CONTROL) 程序状态字寄存器组(PSRs)分为 应用程序 PSR(APSR) 中断号 PSR(IPSR) 执行 PSR(EPSR)
每个都是 32 位,由于这 3 个寄存器有效位是错开的,因此可以组合访问。 中断屏蔽寄存器组(PRIMASK, FAULTMASK, BASEPRI),这三个寄存器用于 控制异常的使能和除能。 控制寄存器(CONTROL)它有两个作用: 1.定义特权级别 2.选择当前使用哪个堆栈指针 3.3 操作模式和特权极别 操作模式: 处理者模式和线程模式 异常处理:处理者模式 主程序:线程模式 ucosii 不区分特权级和用户级,程序始终工作在特权级 这两个堆栈指针的切换是全自动的,就在出入异常服务例程时由硬件处理。 3.4 - 3.7 没什么好讲的,需要看。 3.8 复位序列 0x00000000 MSP 初值 0x00000004 PC 初值 复位向量 chapter7 异常 7.1 异常类型 分为系统异常(编号 1-15)和外部中断(大于 15) 7.2 优先级 CM3 支持 3 个固定的高优先级和多达 256 级的可编程优先级。 在 NVIC 中,每个中断都有一个优先级配置寄存器(1 个 byte),用来配置该 中断的优先级。但该寄存器并不是每个位都被使用,不同制造商生产的芯片不相同, 譬如 stm32 使用 4 位,也就是说 stm32 支持 16 个可编程优先级(参考:chapter9)。 注意该寄存器是以 MSB 对齐的,因此 stm32 每个中断的优先级配置寄存器 7:4 位有效,3:0 位无效。 对于优先级,CM3 又分为抢占优先级和亚优先级, NVIC 中的应用程序中断及复位控制寄存器(AIRCR)的优先级分组(10:8)描述了 如何划分抢占优先级和亚优先级。 什么意思?以 stm32 为例,优先级配置寄存器不是 7:4 位有效吗,如果 AIRCR 中的优先级分组值为 4,则优先级配置寄存器的 7:5 位确定抢占优先级,位 4 确定 亚优先级。此时所有中断有 8 个抢占优先级,每个抢占优先级有 2 个亚优先级。 抢占优先级高的中断可以抢占抢占优先级低的中断,即抢占优先级决定了中断是 否可以嵌套。 相同抢占优先级的中断不能嵌套,但当抢占优先级相同的异常有不止一个到来 时,就优先响应亚优先级最高的异常。 参考附录 D 表 D.9 中断优先级寄存器阵列 0xE000_E400 - 0xE000_E4EF 共 240 个。 表 D.16 系统异常优先级寄存器 0xE000_ED18 - 0xE000_ED23 共 12 个。 优先级相同,看中断号,中断号小的优先。
分享到:
收藏