μCOSII在Cortex-M3核ARM处理器上的移植

发布者:脑力舞者最新更新时间:2009-03-30 来源: 电子科技关键字:μCOSII  Cortex-M3  ARM处理器  移植 手机看文章 扫描二维码
随时随地手机看文章

  目前,嵌入式技术已被广泛应用到汽车电子、无线通信、数码产品等各个领域。嵌入式操作系统及嵌入式处理器技术发展迅猛,嵌入式操作系统典型代表有μCOS—II、μClinux、Winclow CE、VxWorks等;嵌入式处理器包括ARM、MIPS、PowerPC等。随着软硬件技术的发展,人们开始意识到基于嵌入式操作系统的程序开发模式的便利性及可靠性,并且在程序开发过程中开始倾向于从传统超循环开发模式转向基于嵌入式操作系统的开发模式。

  1 软硬件开发环境及处理器介绍

  1.1 软件硬开发环境

  本移植过程使用的软件环境是RealView MDK开发套件,此产品是ARM公司最新推出的针对各种嵌入式处理器的软件开发工具,该开发套件功能强大,包括了μVision3集成开发环境和RealView编译器。使用的硬件平台是深圳英蓓特公司推出的全功能评估板STMl03V100,其上所采用的处理器是ST意法半导体公司生产的32位哈佛结构ARM处理器STM32F103VBT6,该处理器内置ARM公司最新的Cortex—M3核,并且具有非常丰富的片上资源。

  1.2 关于基于Cortex-M3的ARM处理器的介绍

  基于Cortex—M3核的ARM处理器支持两种模式,分别称为线程模式和处理模式。程序可以在系统复位时或中断返回时两种情况下进入线程模式,而处理模式只能通过中断或异常的方式来进入。处于线程模式中代码可以分别运行在特权方式下和非特权方式下。处于处理模式中的代码总是运行在特权方式下。运行在特权方式下的代码对系统资源具有完全访问权,而运行在非特权方式下的代码对系统资源的访问权受到一定限制。处理器可以运行在Thumb状态或Debug状态。在指令流正常执行期间,处理器处于Thumb状态。当进行程序调试时,指令流可以暂停执行,这时处理器处于Debug状态。处理器有两个独立的堆栈指针,分别称为MSP和PSP。系统复位时总是处于线程模式的特权方式下,并且默认使用的堆栈指针是MSP。本移植过程中假设任务总是运行在线程模式的特权方式下且总是使用堆栈指针PSP。

  2 移植过程详解

  2.1 μCOS-II内核介绍

  μCOS—II是一个实时可剥夺型操作系统内核,该操作系统支持最多64个任务,但每个任务的优先级必须互不相同,优先级号小的任务比优先级号大的任务具有更高的优先级,并且该操作系统总是调度优先级最高的就绪态任务运行。此内核的代码是美国人Jean J.Labrosse用C语言编写的,具有很好的可移植性,其2.52版本通过了美国航天航空管理局的安全认证,可靠性非常高。文中所述的移植过程使用的就是该版本的源代码。

  2.2 开始移植

  μCOS—II v2.52的源代码按照移植要求分为需要修改部分和不需要修改部分。其中需要修改源代码的文件包括头文件OS_CPU.H、C语言文件OS_CPU.C以及汇编格式文件OS_CPU_A.ASM。

  2.2.1 修改头文件OS_CPU.H

  头文件OS_CPU.H中需要修改的内容有与编译器相关的数据类型重定义部分和与处理器相关的少量代码。由于本移植过程中使用的是RealView编译器,因此通过查阅此编译器的相关说明文档可以得到其所支持的基本数据类型,据此修改OS_CPU.H中与编译器相关的数据类型重定义部分。修改后代码如下所示:

 

  其中定义的数据类型OS_STK指出了处理器堆栈中的数据是32位的,OS_CPU_SR指出了处理器状态寄存器字长也为32位。

  头文件中与处理器相关部分代码包括临界区访问处理、处理器堆栈增长方向及任务切换宏定义。临界区代码访问涉及到全局中断开关指令,由文献可以得知关中断和开中断可以分别由指令CPSID i和CPSIE i实现,文中临界段访问处理如下:

 

  其中INT_DIS()和INT_EN()分别对应关中断和开中断处理过程。

  根据文献可知文中所使用的处理器支持的堆栈为满递减方式,即堆栈的增长方向是从内存高地址向低地址方向递减并且堆栈指针总是指向栈顶的数据。在头文件OS_CPU.H中相应代码只须修改一条,如下所示

#define OS_STK_GROWTH1

  此定义中的1代表堆栈方向是向下递减的。

  头文件OS_CPU.H中最后一个要修改的地方是任务切换宏定义,μCOS—II内核就是通过这个宏调用来触发任务级的任务切换。任务切换一般是通过陷阱或软件中断来实现的,在基于Cortex—M3核的处理器中支持一条称为超级用户调用的指令SVC,此指令是ARM软件中断指令SWI的升级版。此处的宏定义代码修改为如下形式

#define OS_TASK_SW()OS_SVC()

  其中OS_SVC()之中包含了SVC指令,它可以由嵌入汇编的方式在C语言代码中进行定义,如下所示

_asm void OS_SVC(void){SVCOx00}

  以上代码以嵌入汇编的方式定义了一个输入参数和返回值都为空的C语言函数,嵌入汇编的格式在RealView编译器的说明文档中有详细的说明。

  2.2.2 修改C语言文件OS_CPU.C

  根据文献可知文件OS_CPU.C中有10个C语言函数需要编写,这些函数中唯一必要的函数是OSTaskStkInit,其他9个函数必须声明,但不一定要包含任何代码。为了简洁起见,本移植过程只编写了OSTaskStkInit,此函数的作用是把任务堆栈初始化成好像刚发生过中断一样。要初始化堆栈首先必须了解微处理器在中断发生前后的堆栈结构,根据文献易知微处理器在中断发生前后的堆栈结构,并且可知寄存器xPSR、PC、LR、R12、R3、R2、R1、RO是中断时由硬件自动保存的。初始化时需要注意的地方是xPSR、PC和LR的初值,对于其他寄存器的初值没有特别的要求。xPSR比特位是Thumb状态位,初始化时须置1,否则执行代码时会引起一个称为Invstate的异常,这是因为内置Cortex—M3核的微处理器只支持Thumb和Thumb2指令集。堆栈中PC和LR须初始化为任务的入口地址值,这样才能在任务切换时跳转到正确的地方开始执行。此函数可以用以下代码来实现

 

  2.2.3 修改汇编语言文件OS_CPU_A.ASM

  汇编文件OS_CPU_A.ASM中需要编写的函数分别为OSStartHighRdy、OSCtxSw、OSIntCtxSw和OSTickISR。第一个函数的作用是启动多任务调度,此函数只在操作系统开始调度任务前执行一次,以后不再调用。按照文献中所述须将堆栈中的寄存器依次弹出,然后执行一条中断返回指令来开始第一个用户任务的调度。但基于Cortex—M3核的ARM处理器在执行中断返回指令时必须处于处理模式下,否则将会引起内存访问异常。当系统上电启动时或程序重置后,处理器会进入线程模式,而要在函数OSStartHighRdy中执行中断返回指令就首先需要进行模式转换,进入处理模式,而进行同步可控制模式转换的途径是超级用户调用,即通过SVC指令产生软件中断可转换到处理模式。实际上考虑到此函数只在启动多任务调度开始前被调用一次,并且第一次调度任务运行时任务堆栈中除了xPSR、PC和LR的初值以外,其他寄存器的初值无关紧要。因此可以简化该函数的编写,只须从第一个任务的堆栈中取出该任务的首地址,然后修改堆栈指针使其指向任务堆栈中内存地址最高处,即相当于抛弃任务堆栈中所有数据,最后根据取出的地址直接跳转到任务入口地址处开始执行。这样可以免去软件中断和模式切换,从而简化了对此函数的编写。需要说明的是在抛弃任务堆栈中所用数据的同时也将xPSR的初值抛弃了,但这并不影响第一个任务投人运行,因为在跳转到第一个任务运行之前,指令流是在Thumb状态下正常执行的,xPSR已经有了确定的值。此函数代码如下所示

 

BX r0;直接跳转到第一个任务的入口地址

  第二个汇编语言函数OSCtxSw是任务级的任务切换函数。若在任务执行过程中有一个比当前任务优先级更高的任务进入就绪态,μCOS—II内核就会启动OSCtxSw进行任务切换。该函数会保存当前任务状态,然后恢复那个优先级更高的任务状态,使之投入运行。前述的宏定义#defineOS_TASK_SW()OS_SVC()中的OS_SVC()包含了SVC软件中断指令,此中断的中断向量应该设为函数OSCtxSw的入口地址,即OSCtxSw是SVC指令产生中断的中断服务程序,其源代码如下

[page]

 

 

  由于微处理器在进入中断时按堆栈增长方向自动顺序保存了如下8个寄存器:xPSR、PC、LR、R12、R3、R2、R1、R0,因此在程序中只须保存另外8个寄存器,保存顺序可以随意,但注意弹栈时要按照先进后出的方式进行。按照本文开头的假定,任务总是运行在线程模式的特权方式下且总是使用堆栈指针PSP。而中断产生后,中断服务程序将处于处理模式下,并且默认使用的堆栈指针是MSP。因此在保存堆栈指针的时候需要保存的是当前任务的PSP。中断返回前新任务的堆栈指针需要恢复到PSP中。中断返回使用如下指令

  MOVrO,#Oxfffffffd

  BXr0

  其中立即数#0xfffffffd包含了返回信息,用这两条指令可以使中断返回时使用任务堆栈指针PSP,返回后任务处于线程模式且使用任务堆栈指针PSP。

  第三个汇编语言函数OSIntCtxSw与OSCtxSw类似。若任务执行过程中产生了中断,且中断服务程序使得一个比当前被中断的任务具有更高优先级的任务就绪时,μCOS—II内核就会在中断返回之前调用函数OSIntCtxSw。在此函数中不需要像任务级任务切换函数那样保存当前任务状态,因为当前任务已经被中断,在进入中断服务程序的时候任务状态已被保存。其源代码与函数OSctxSw中保存当前任务堆栈PSP指令以后部分相同,此处不再列出。

  第4个汇编语言函数OSTickISR是系统时钟节拍的中断服务函数。处理器STM32F103VBT6中有一个专用系统时钟节拍定时器SysTick,本移植过程使用此定时器产生每100 ms一次的时钟节拍中断。此函数源代码如下

 

  3 程序开发模式讨论

  传统应用程序开发模式称为超循环模式,即通常主程序是由C语言中的for语句或while语句构成的一个无限循环,程序在此循环中检测事件的发生,从而转向不同的任务。这种程序开发模式有两个主要的不足之处。首先从程序维护和可靠性的角度来看,所有任务都需要程序开发人员来进行全局性的维护,当系统变得庞大和复杂时,任务的维护会变得非常麻烦,同时程序的可靠性也受到影响。其次,从任务级响应时间来看,这个时间是不确定的,因为程序在循环体中检测事件发生的位置是固定的,但事件的发生是随机的,因此从事件发生到程序检测到事件发生这段时间也是不确定的。

  在基于嵌入式操作系统的应用程序开发过程中,应用程序开发人员只需关心各个任务本身,而任务调度由操作系统代劳。以下的例子说明了基于μCOS—II嵌入式操作系统的应用程序开发模式

 

  其中函数SysInit的作用是根据具体应用对处理器芯片进行必要的初始化,例如对系统的时钟分配以及通用输入输出端口配置。函数OSInit是μCOS—II操作系统的内核初始化程序。第一个OSTaskCreate函数创建了任务Taskl,此任务的入口地址是Taskl,优先级是0。第二个OSTaskCreate函数创建了任务Task2,此任务的入口地址是Task2,优先级是1。函数OSTaskCrate还会将其创建的任务置于就绪态。文献叙述了函数OSTa-skCreate的各个参数的含义。函数OSStart用于启动多任务调度。OSTimeDly是μCOS—II内核提供的系统调用函数,用于延时或定时,这里的参数5表示延时5个时钟节拍。应用程序开发人员需要做的就是通过调用μCOS—II内核提供的任务创建函数OSTaskCreate将编写好的任务程序交给操作系统管理。

  该例中在调用OSStart后,操作系统发现任务Taskl的优先级最高,于是操作系统就调度任务Taskl使其投入运行,而任务Task2暂时不能获得处理器的使用权。任务Taskl首先点亮一个LED,然后延时一段时间,当运行到OSTimeDly处时,该任务被挂起而处于等待状态,此时任务Task2成为优先级最高的就绪态任务,于是操作系统调度Task2运行。当5个时钟节拍的延时时间结束时,系统时间节拍中断服务子程序会重新将任务Taskl置于就绪状态,此时任务Taskl再一次成为优先级最高的就绪态任务,于是操作系统保存任务Task2的状态,并恢复任务Taskl的状态使其又一次获得处理器的使用权。此后程序执行过程将重复上述步骤。可以看到,在这个例子中的现象是某个LED灯不停的闪烁。

  μCOS—II操作系统内核是实时可剥夺型的,这意味着在任务执行过程中或中断服务子程序中,一旦有一个新的更高优先级的任务就绪,内核将立刻调度此新任务运行,这说明响应任务的时间是即刻的、确定的。

  综上所述,基于嵌入式操作系统的应用程序开发过程相对于以往传统应用程序开发大为简化而且任务级响应时间也得到最优化。

  4 结束语

  通过将移植过程中修改的μCOS—II内核代码与上述例子中的应用程序代码在μVision3集成开发环境中编辑整合后进行编译、链接并且下载到目标硬件平台进行长时间观察,发现LED不停的闪烁,说明本移植过程是成功的。

关键字:μCOSII  Cortex-M3  ARM处理器  移植 引用地址:μCOSII在Cortex-M3核ARM处理器上的移植

上一篇:基于μC/OS-II的电力参数监测仪设计
下一篇:嵌入式Linux的safe mode设计与实现

推荐阅读最新更新时间:2024-05-02 20:47

教程:只需六步,将Hal库移植到标准库
手头上正好有STM32的开发板和ESP-12E模块,想着控制个WS2812玩玩。到MCU开发的时候下载了生成的代码发现是HAL库的,无奈自己刚刚学习stm32,用的是标准库这里参考了官方的移植MSP340教程并修改出适用于STM32标准库的教程。 步骤1、下载好的代码包是这样的,需要把这两个文件夹直接复制到自己工程的文件夹里面: 步骤2、添加到自己的工程组里面,并添加路径: 步骤3、正题来了,现在开始移植工作,需要修改的文件分别如下:3.1、打开gizwits_product.h需要修改的地方如下,查看代码行数可以快速找到) 3.2、打开gizwits_product.c,需要修改的地方如下: 下面删除的
[单片机]
教程:只需六步,将Hal库<font color='red'>移植</font>到标准库
ARM Cortex-M3 即插即用的跟踪仿真器
  IAR Systems 在 Embedded World 上发布第一款支持 ARM Cortex-M3 的高速跟踪仿真器。这个即插即用的仿真器与 IAR Embedded Workbench 集成开发环境完全兼容,可以把应用下载到硬件开发板上直接调试,从而加快项目的开发进度。   使用 IAR J-Trace 非常简单,通过 USB 线与运行 Windows 操作系统的主机连接,并通过这个 USB 接口供电。此外,通过一个独立的 JTAG 接口,它可以被用作 JTAG 仿真器。   IAR J-Trace 结合了 ETM ( embedded trace macrocell ) 和嵌入式 ICE( incircuit
[嵌入式]
μC/OS-II在S3C44BOX处理器上的移植
摘要:介绍实时操作系统μC/OS-II的特点和内核结构,给出μC/OS-II在Samsung嵌入式S3C44BOX ARM7微处理器上的移植的步骤及详细相关代码,同时阐述μC/OS-II在应用中应注意的问题。 关键词:μC/OS-II S3C44BOX 移植 实时操作系统 μC/OS-II功能强大,支持56个用户任务,其内核为占先式,支持信号量、邮箱、消息队列等多种常用的进程间通信机制,现已成功应用到众多商业嵌入式系统中,是一个成熟稳定的实时内核。与大多商用RTOS不同的是,μC/OS-II公开所有的源代码,90%的代码使用标准的ANSI C语言书写,程序可读性强、移植性好;同时它可免费获得,即使商业应用也只收取少量的许可费用
[嵌入式]
内核移植(1)首次生成uImage映象文件
1、先修改顶层Makefile,如下: ARCH ?= $ (SUBARCH) CROSS_COMPILE ?= 改为: ARCH ?= arm CROSS_COMPILE ?= arm-linux- 2、执行make s3c2410_defconfig 3、make uImage,首次编译完内核用了4分钟,尾部出现如下信息: LD arch/arm/boot/compressed/vmlinux OBJCOPY arch/arm/boot/zImage Kernel: arch/arm/boot/zImage is ready UIMAGE arch/arm/boot
[单片机]
ARM处理器的寄存器介绍
在ARM体系中通常有以下3种方式控制程序的执行流程: **在正常执行过程中,每执行一条ARM指令,程序计数器(PC)的值加4个字节;每执行一条Thumb指令,程序计数器寄存器(PC)加2个字节。整个过程是按顺序执行。 **跳转指令,程序可以跳转到特定的地址标号处执行,或者跳转到特定的子程序处执行。其中,B指令用于执行跳转操作;BL指令在执行跳转操作同时,保存子程 序的返回地址;BX指令在执行跳转操作同时,根据目标地址为可以将程序切换到Thumb状态;BLX指令执行3个操作,跳转到目标地址处执行,保存子程序的返回 地址,根据目标地址为可以将程序切换到Thumb状态。 **当异常中断发生时,系统执行完当前指令
[单片机]
OK6410A 开发板 (六) 1 OK6410A linux-4.0 移植
增加 arch/arm/configs/forlinx6410_defconfig 增加 firmware/sd8686.bin 增加 firmware/sd8686_helper.bin 用下面的编译器 $ arm-none-linux-gnueabi-gcc --version arm-none-linux-gnueabi-gcc (Sourcery CodeBench Lite 2014.05-29) 4.8.3 20140320 (prerelease) Copyright (C) 2013 Free Software Foundation, Inc. This is free software; see the
[单片机]
Windows下u-boot-2011.03在Mini2440移植详解(5)
增加Nand Flash ECC的支持 又参考了网址http://blog.csdn.net/fulinus/article/details/8737129 修改相关文件: 1.u-boot-2011.03driversmtdnands3c2440_nand.c 2.u-boot-2011.03includeconfigsmini2440.h 一开始一直不能确定的是:nand- ecc.size 和nand- ecc.bytes到底是多少?板子上带的Nand Flash是:K9F1208U0B:64MB,8位。每1页包含512字节的main数据区和16字节的spare数据区。main区用于存储数据,spare区
[单片机]
Windows下u-boot-2011.03在Mini2440<font color='red'>移植</font>详解(5)
U-boot移植到mini2440上
本文章中的很多内容参考友善之臂的说明文档《mini2440之U-boot移植详细手册-20100419》,使用的U-boot的版本是u-boot-2010.03 说明:此次移植的目的不是为了制作一个功能强大的U-boot,只是做一个最简单的U_boot。该U-boot能够实现通过串口和电脑通信,可以将环境变量保存在NOR Flash中,通过TFTP服务器将使用NFS根文件系统的内核镜像从电脑拷贝到内存中执行。而且这个U-boot只支持从NOR中启动。 在移植U-Boot之前建议对U-Boot中的源码组织结构有较深的理解,可参考我的另一篇博文Bootloader介绍和Uboot源码结构 移植U-Boot的原则是,先选取与
[单片机]
小广播
最新嵌入式文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved