ucosiiucosiiucosiiucosii在stm32stm32stm32stm32上的移植详解1111转载请注明出处:虽然目前网上已经有不少关于ucosii在stm32上的移植版本,包括micrium也有官方移植版本。但这些版本具体是怎么移植出来的,又该怎么基于移植好的ucosii开发应用软件,网上介绍的并不多。这里介绍一下我的移植经历,希望对大家有所帮助。我的移植基本上是从零开始的。首先想要做好移植,有两方面的内容是必须要了解。1.目标芯片;2.ucosii内核原理。虽然我们移植的目标芯片是stm32,但操作系统的移植基本是针对Cortex-M3内核(以下简称CM3)而言的,所以我们只需了解CM3内核就好了。stm32芯片就是CM3内核加上各种各样的外设。怎么才能了解CM3呢?看一本书ARMCortex-M3权威指南(宋岩译,网上多的很)就好了,很多同学可能想,看完这本书移植的新鲜劲都没了,因此我把该书和移植有关的章节都列了出来,并对其中的重点内容进行介绍,我数了数相关章节还不到100页,就这点内容,总要看了吧。相关章节如下:chapter2Cortex-M3概览2.1-2.9主要了解Cortex-M3的概貌。刚开始看时不用追求全部理解,后面会有详细介绍,很多内容多看几遍就明白。其中2.8指令集,只要了解,CM3只使用thumb2就ok了。chapter3Cortex-M3基础3.1寄存器组R0-R12:通用寄存器R13:堆栈寄存器有两个,MSP和PSP,同时只能看见一个引用R13时,引用的是正在使用的那个MSP:可用于异常服务和应用程序PSP:只能用于应用程序系统复位后,用的堆栈指针是MSP。R14:连接寄存器,又名LR存储返回地址R15:程序计数寄存器,又名PC3.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复位序列0x00000000MSP初值0x00000004PC初值复位向量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个。优先级相同,看中断号,中断号小的优先。7.3向量表初始在0x00000000处,可以通过向量表偏移量寄存器(VTOR)(地址:0xE000_ED08)更改,一般无需更改。7.4中断输入及挂起行为需要看。7.5Fault异常可不看。7.6SVC和PendSVSVC主要用在分特权级和用户级的操作系统,ucosii不区分特权级和用户级,可以不管这个东西。这里说点题外话,一开始我很奇怪为什么会提供这种中断,因为这种中断一般都是用在大型的操作系统上,如linux系统上,可CM3又不提供MMU,应该是无法移植linux系统。后来我才知道uclinux是针对没有MMU的嵌入式系统而设计的,不过还是很怀疑有人会在像stm32这种芯片上用uclinux。PendSVPendSV中断主要做上下文切换,也就是任务切换,是ucosii移植过程中最重要的中断。主要有两点:1.PendSV中断是手工往NVIC的PendSV悬起寄存器中写1产生的(由OS写)。2.PendSV中断优先级必须设为最低。在讲移植代码时会介绍具体是如何做的。对于7.6的PendSV部分应认真研读一下。chapter8NVIC与中断控制NVIC负责芯片的中断管理,它和CM3内核紧密相关。如果对于CM3中断配置不是很了解,可以看看8.1,8.2,8.3,8.4节。8.7节讲述了SysTick定时器,需要看。chapter9中断的具体行为9.1中断/异常的响应序列当CM3开始响应一个中断时1.xPSR,PC,LR,R12以及R3‐R0入栈2.取向量3.选择堆栈指针MSP/PSP,更新堆栈指针SP,更新连接寄存器LR,更新程序计数器PC对移植ucosii来说,需要注意1,39.2异常返回在CM3中,进入中断时,LR寄存器的值会被自动更新。9.6节对更新后的值进行说明。这里统称EXC_RETURN。返回时通过把EXC_RETURN往PC里写来识别返回动作的。因为EXC_RETURN是一个特殊值,所以对于CM3,汇编语言就不需要类似reti这种指令,而用C语言开发时,不需要特殊编译器命令指示一个函数为中断服务程序。实际上,中断服务程序如果是c代码编写,汇编成汇编代码,函数结尾一般是reti。9.3嵌套的中断只要注意:中断嵌套不能过深即可。9.4和9.5这两节说明CM3对中断的响应能力大大提高了,主要是硬件机制的改进。但对移植来说,并不需要关注。9.6异常返回值对不同状态进入中断时,LR寄存器的值进行说明,需要看。这里有一点需要注意,该点在讲移植代码时再介绍。9.7和9.8对移植来说,并不需要关注。chapter10Cortex-M3的低层编程这一章仅需关注10.2节,因为对移植来说汇编与C的接口是必须面对的。10.2汇编与C的接口有两点需要知道:1.当主调函数需要传递参数(实参)时,它们使用R0‐R3。其中R0传递第一个,R1传递第2个……在返回时,把返回值写到R0中。2.在函数中,用汇编写代码时,R0-R3,R12可以随便使用,而使用R4‐R11,则必须先PUSH,后POP。以上内容和移植多少都有些关系,刚开始看,可能不太明白,多看几遍就好了。ucosiiucosiiucosiiucosii在stm32stm32stm32stm32上的移植详解2222分类:stm32rtos2011-07-2709:04475人阅读评论(2)收藏举报转载请注明出处:在详解1中主要讲了移植需要用到的CM3内核知识,本文讲一讲ucosii的原理和代码组成。ucosii最经典的学习资料莫过于邵贝贝老师的嵌入式实时操作系统uc/os-ii(第2版),我想这本书对学ucosii已经足够了,因为他把ucosiiV2.55代码都讲了一遍。移植前应该好好看看此书。下面说说我对ucosii的理解。应该说ucosii这个内核还是比较简单的,基本可以分为任务调度,任务同步和内存管理三个部分。任务调度ucosii为保证实时性,给每个任务分配一个不同的优先级。当发生任务切换时,总是切换到就绪的最高优先级任务。有2种情况会发生任务切换。1.任务等待资源就绪或自我延时;2.退出中断;情况1可以理解为任务主动放弃cpu的使用权。情况2可以理解为中断后,某种资源可能就绪了,需要任务切换。需要注意的是SysTick中断,这个中断是os的“心跳”,必须得有。这样就使得cpu会发生周期性地做任务切换。由于ucosii不支持时间片轮转调度,因此在该中断中必须做的工作仅有os的时间管理。也就是调用OSTimeTick()。任务同步任务同步和大多数操作系统的做法差不多,如果学过操作系统或是有多线程编程经验的话,应该很好理解。无非是任务A因为某个资源未就绪,就放弃cpu使用权,等任务B或是中断使该资源就绪,当再次任务进行切换时如果任务A优先级最高,则任务A继续执行。具体怎么实现就看邵老师的书吧。内存管理ucosii的内存管理比较简单,就不说了。下面看看ucosii代码组成:os_core.c是ucosii的核心,它包含了内核初始化,任务切换,事件块管理等,其中事件块是各个同步量(这里我把互斥量,信号量,邮箱,队列统称为同步量,不是很科学,图个方便。事件标志组不是以事件块为基础的,不过原理也差不多)的基础。os_task.c任务管理代码。os_flag.cos_mbox.cos_mutex.cos_q.cos_sem.c各个同步量管理代码。os_mem.c内存管理代码。os_time.c时间管理代码,主要做各种延时。os_tmr.c定时器管理代码,这部分代码时从V2.81版才开始有的,邵老师的书讲的是V2.55版的代码,是没有这部分内容的。如果前面的代码都理解的话,这部分代码也是不难理解的。一个定时器大体由3部分组成:定时时间,回调函数和属性。当定时时间到了的话,就进行一次回调函数的处理,定时器属性说明定时器是周期性的定时还是只做一次定时。如果用户使能了OS_TMR_EN,ucosii会在内部创建一个定时器任务,负责处理各个定时器。这个任务一般应该由硬件定时器的中断函数中调用OSTmrSignal()去激活。所以从本质上说os_tmr.c中的定时器是由一个硬件定时器分化出来的。默认情况下是由SysTick中断里通过OSTimeTickHook()去激活定时器任务的。移植相关文件os_cpu.h:进行数据类型定义,处理器相关代码和几个函数原型。os_cpu_c.c:定义一些用户hook函数。os_cpu_a.asm:移植需要用汇编代码完成的函数,主要就是任务切换函数。os_dbg.c:内核调试相关数据和函数,可以不改。ucosii内核就介绍到这里。ucosiiucosiiucosiiucosii在stm32stm32stm32stm32上的移植详解3333分类:stm32rtos2011-07-2709:48869人阅读评论(1)收藏举报转载请注明出处:移植详解1和2中主要讲了移植需要用到的基础知识,本文则对具体的移植过程进行介绍。首先从micrium网站上下载官方移植版本(编译器使用ARM/Keil的,V2.86版本,V2.85有问题)。下载地址:解压缩后得到如下文件夹和文件:Micrium\AppNotesLicensingSoftwareReadMe.pdfAppNotes包含ucosii移植说明文件。这两个文件中我们仅需关心Micrium\App