基于uCOS-II的嵌入式应用程序开发



《基于uCOS-II的嵌入式应用程序开发》由会员分享,可在线阅读,更多相关《基于uCOS-II的嵌入式应用程序开发(44页珍藏版)》请在装配图网上搜索。
1、,,,Click to edit Master text styles,,Second level,,Third level,,Fourth level,,Fifth level,,*,Click to edit Master title style,,,,,,,,XUPT,嵌入式系统,,原理与应用,Click to edit Master text styles,,Second level,,Third level,,Fourth level,,Fifth level,,Click to edit Master title style,,,,,Click to edit Master tex
2、t styles,,Second level,,Third level,,Fourth level,,Fifth level,,Click to edit Master title style,,,*,第八章,基于,µC/OS-II,的嵌入式应用程序开发,,目 录,8.1,嵌入式应用程序开发的特点,,8.2 µC/OS-II,应用程序结构分析,,8.3 µC/OS-II,程序设计技术,,8.4 µC/OS-II,在,ARM,微处理器上的移植,,8.5,应用程序设计及实例,2,8.1,嵌入式应用程序开发的特点,8.1.1,开发调试环境的建立,,,在嵌入式系统开发中,典型的调试环境一般通常由三部
3、分构成:一是通用计算机(用来运行调试软件,称为调试主机);二是协议转换器(连接调试主机发出的高级命令与微处理器,JTAG,接口的低级命令之间的接口);三是调试目标。硬件调试环境如下图:,,3,8.1,嵌入式应用程序开发的特点,8.1.2,基于嵌入式处理器的直接编程技术,,如果针对硬件电路直接设计应用程序,那么应用程序的代码必须包括以下几个部分:,,①启动部分:硬件加电后首先运行(硬件检测和资源分配),,②处理器管理部分:实现处理器状态转换和寄存器使用等,,③外围设备访问部分:外围设备(如串口)的初始化等,,④程序功能部分:实现程序所要完成的具体功能,,这样设计程序对设计人员的能力要求是很高的。
4、,,4,8.1,嵌入式应用程序开发的特点,8.1.3,基于嵌入式操作系统的编程技术,,随着嵌入式微处理器和程序设计技术的发展,人们把一个大的程序从功能上可划分为三个部分:,,① 板级支持包(,BSP,):其目的是屏蔽下层硬件,主要由,Boot Loader,和,Drivers,两部分构成。,,② 嵌入式实时操作系统(,RTOS,)。,,③ 应用程序:基于相应操作系统、在相应开发环境下设计的并最终运行在相应目标机上的程序。,,这里,可由掌握不同技术的人去设计不同的部分,并在三部分之间设计相应的接口以供三部分之间相互调用。,5,8.2 µC/OS-II,应用程序结构分析,下面以一个简单实例来说明基
5、于,µC/OS-II,操作系统设计的嵌入式应用程序的结构。,,程序清单,8.1,两个,LED,交替闪烁,,#include “config.h” (1),,#define LED1 (1<<18) //,定义,LED1,,,P1.18,控制,LED1 (2),,#define LED2 (1<<19) //,定义,LED2,,,P1.19,控制,LED2 (3),,#define TASK_STACK_SIZE 128 //,定义用户任务的堆栈长度,(4),,OS_ST
6、K task1Stk[TASK_STACK_SIZE]; //,定义任务,LED1,的堆栈,(5),,OS_STK task2Stk[TASK_STACK_SIZE]; //,定义任务,LED2,的堆栈,(6),,,void task1(void *pdata); //LED1,任务函数声明,(7),,void task2(void *pdata); //LED2,任务函数声明,(8),6,8.2 µC/OS-II,应用程序结构分析,7,int main(void) //,主函数,(
7、9),,{,,OSInit(); //,初始化,µC/OS-II (10),,OSTaskCreate(task1,(void *)0, //,创建,LED1,任务,, //,优先级为,4 (11),,OSTaskCreate(task2,(void *)0, //,创建,LED2,任务,, //,优先级为,5 (12),,OSStart(); //,启动,µC/OS-II,,任务开始执行,(13),,return(0);
8、 (14),,},,// main,函数中所调用的,OSInit,、,OSTaskCreate,和,OSStart,,,是,,//µC/OS-II,操作系统提供的,API,函数。,,// main,函数并没有直接调用,task1,和,task2,,只是在,main,中调用,,//OSTaskCreate,创建两个任务时分别把,task1,和,task2,作为参数。,,,8.2 µC/OS-II,应用程序结构分析,8,void task1(void *pdata) //,任务,LED1,函数定义,(15)
9、,,{,,pdata=pdata; //,防止出现编译警告,(16),,TargetInit(); //,目标板初始化,包括初始化中断系统,(17),,PINSEL2 &=,~,0x08; //,选择管脚,P1.18,~,25,为,GPIO (18),,IO1DIR |= 0x03<<18; //,设置,LED(P1.18,、,P1.19),为输出,(19),,IO1SET = 0x03<<18; //LED1,和,LED2,熄灭,(20),,while(1)
10、 //,超级循环,(21),,{,,IO1CLR=LED1; //,点亮,LED1 (22),,OSTimeDly(OS_TICKS_PER_SEC/4); //,延时,1/4,秒,(23),,IO1SET=LED1; //,熄灭,LED1 (24),,OSTimeDly(OS_TICKS_PER_SEC/4); //,延时,1/4,秒,(25),,},,},8.2 µC/OS-II,应用程序结构分析,9,void task2(void *pdat
11、a) //,任务,LED2,函数定义,(26),,{,,pdata=pdata; (27),,while(1) //,超级循环,(28),,{,,IO1CLR=LED2; //,点亮,LED2 (29),,OSTimeDly(OS_TICKS_PER_SEC/3); //,延时,1/3,秒,(30),,IO1SET=LED2; //,熄灭,LED2
12、(31),,OSTimeDly(OS_TICKS_PER_SEC/3); //,延时,1/3,秒,(32),,},,},,//task1,和,task2,中的“,pdata=pdata;”,是防止在编译时出现警告。,,//task1,和,task2,中调用的,OSTimeDly,,是,µC/OS-II,提供的,API,函数。,,// PINSEL2,、,IO1DIR,等都是宏定义,代表寄存器地址,,给该寄,,//,存器赋值可以实现不同的功能,它们都在(*,.h,)文件中定义。,8.2 µC/OS-II,应用程序结构分析,10,上述程序的功能是让,2,个,LED,灯以不同的速度闪烁,其执行
13、流程如下图:,,8.2 µC/OS-II,应用程序结构分析,11,关于该程序的执行过程作以下说明:,,①该程序首先从,main,函数开始执行,初始化,µC/OS-II,,创建任务,task1,和,task2,,最后启动,µC/OS-II,中任务调度程序的执行。,,②任务调度程序、任务,task1,和,task2,、空闲任务(,µC/OS-II,中)等的交替执行。当任务调度程序执行后,任务调度程序会选择当前处于就绪态的最高优先级的任务来执行;当正在执行的任务调用延时函数延时时,就会挂起该任务,程序又会执行调度程序来调度其它任务的执行。,,③main,函数最后一条语句是,return(0),,但程
14、序一直在任务调度程序、任务,task1,和,task2,等之间交替执行,永远也不会返回到,main,函数,所以永远也不会执行,return(0),。,,由以上分析可知,在使用,µC/OS-II,操作系统的嵌入式应用程序中,程序的基本结构除,main,函数外,还包括一个个任务函数,当然也包括非任务函数。设计程序的任务主要是划分和设计一个个任务函数。,8.3 µC/OS-II,程序设计技术,8.3.1,任务的划分与设计,,⒈ 任务的特性,,,任务的基本特性有:动态性、独立性和并发性,,① 任务的动态性是指:在程序的运行过程中,各个任务的状态是动态变化的。这些状态有就绪态、运行态和等待态等。,,②
15、任务的独立性是指:程序中的所有任务在逻辑上都是平等的。它们的执行是由调度程序调度来实现的,这样,在每个任务看来,,CPU,为自己独占。任务之间要传输信息时必须通过第三方来完成,如消息邮箱等。,,③ 任务的并发性是指:所有任务共有一个,CPU,,但在某一时刻,一个,CPU,只能运行一个任务。高优先级的任务可以剥夺另一个正在运行的低优先级任务的运行权而进入运行状态。高优先级任务在运行一段时间后必须将自己挂起(如调用延时函数等) 以让出,CPU,而让处于就绪态的低优先级的任务得到执行。这样所有任务的运行时间就会相互重叠,表面上看起来好象同时运行一样。,12,8.3 µC/OS-II,程序设计技术,⒉
16、 任务的划分方法,,在进行任务划分时,可以有不同的方案,但其要达到的目标都是一致的。首先要满足系统对“实时性”的要求,其次要使任务数目合理和简化软件系统,最后要降低系统对资源的需求。任务的划分有下列一些基本原则:,,① 设备依赖性任务的划分:以,CPU,为中心,将与各种输入,/,输出设备相关的功能 分别划分为独立的任务(如键盘任务、显示任务等)。,,② 关键任务的划分:“关键性”是指某种功能在应用系统中的重要性。若该功能不能正常实现,将会造成重大影响,如火灾报警中传感器信号的检测。,,③ 紧迫任务的划分:“紧迫性”是指某种功能必须在规定的时间内得到运行,并在规定的时刻前执行完毕。,,此外,
17、还有:数据处理任务的划分、功能聚合任务的划分、触发条件相同任务的划分、运行周期相同任务的划分、顺序操作任务的划分等原则。这些原则只是一般性原则,设计任务时必须具体问题具体分析。,13,8.3 µC/OS-II,程序设计技术,⒊ 任务函数的代码结构,,在任务函数中,必须至少调用一次操作系统的服务函数,否则低优先级的任务将永远无法得到运行。按照执行方式可以将任务函数的结构分为三类。,,① 单次执行的任务:此类任务在创建后只执行一次,执行结束后即自行删除。其任务函数的代码结构如下:,,void MyTask(void *pdata) //,单次执行的任务函数,,{,,,进行准备工作的
18、代码;,,任务实体代码;,,调用任务删除函数;,//,调用,OSTaskDel(OS_PRIO_SELF),,},,“进行准备工作的代码”完成各项准备工作,如定义和初始化变量等;“任务实体代码”完成该任务的具体功能,通常包含对系统函数的调用,除若干临界段代码(中断被关闭)外,其它代码均可以被中断,用以保证高优先级的就绪任务能够及时得到运行;“调用任务删除函数”将自己删除。,14,8.3 µC/OS-II,程序设计技术,② 周期性执行的任务,,此类任务在创建后按一个固定的周期来执行。其任务函数的结构如下:,,void MyTask(void *pdata) //,周期性执行的任务
19、函数,,{,,,进行准备工作的代码;,,,while (1) //,无限循环,,{,,任务实体代码;,,调用系统延时函数;,//,调用,OSTimeDly(),或,OSTimeDlyHMSM(),,},,},,“调用系统延时函数”使自己挂起,把,CPU,的控制权交给操作系统,由操作系统(中的调度程序)来调度其它已经就绪的最高优先级的任务运行。当延时时间到后,该周期性任务重新进入就绪状态。,15,8.3 µC/OS-II,程序设计技术,③ 事件触发执行的任务,,此类任务在创建后,很快可以获得运行权,但实体代码的执行需要等待某种事件的发生,在相关事件发生之前,
20、该任务则被,µC/OS-II,挂起。其结构如下:,,void MyTask(void *pdata) //,事件触发执行的任务函数,,{,,,进行准备工作的代码;,,,while (1) //,无限循环,,{,,调用获取事件的函数;,//,如等待信号量等,,任务实体代码;,,,},,},,“调用获取事件的函数”调用,µC/OS-II,提供的获取某种事件(如信号量)的函数,来等待另外一个任务(或,ISR,)发出的信息,此后该任务处于挂起状态;当另外一个任务(或,ISR,)调用了,µC/OS-II,提供的通信函数发出相关信息时,,µC/
21、OS-II,就使该任务进入就绪状态,并且通过任务调度,使该任务的实体代码得到执行。相关事件发生一次,任务实体代码就执行一次。,16,8.3 µC/OS-II,程序设计技术,8.3.2,任务间的行为同步方法,,在实时操作系统,µC/OS-II,的支持下,系统的整体功能是通过各个任务(包括,ISR,)的协同运行来实现的。一个任务的运行,往往需要和其它的任务配合才能达到预期的效果,任务之间的这种配合和协调关系就称为任务间的行为同步。,,µC/OS-II,所提供的控制任务间行为同步的通信手段有:计数信号量、事件标志组、消息邮箱和消息队列。,,通常使用的行为同步方法有:,,① 两个任务之间的单向同步:即
22、一个任务为控制方,它发出控制信息;而另一个任务为被控制方,它获得控制方发出的控制信息后即进入就绪状态。这可使用信号量来实现。,17,8.3 µC/OS-II,程序设计技术,② 两个任务之间的双向同步:即两个任务同为控制方和被控制方。在这种情况下,首先一个任务必须为控制方,它发出控制信息后就变为被控制方,此时其需等待另一个任务发出的控制信息后才能继续运行;而另一个任务首先为被控制方,当它获得控制方发出的控制信息后才能运行,并变为控制方。这可使用消息邮箱来实现。,,③ 一个任务同步多个任务:即一个任务为控制方,它发出控制信息,来控制多个任务的执行。此时可采用具有消息分发功能的通信机制(当然也可采用
23、多个通信工具)来实现。,,④ 两个以上任务同步一个任务:即多个任务为控制方,它们发出控制信息来控制一个任务的执行。此时可采用“事件标志组”来实现。,,18,8.3 µC/OS-II,程序设计技术,8.3.3,共享资源的同步方法,,被两个以上并发程序单元(任务或,ISR,)访问的资源称为共享资源(如全局变量、外设等)。任务对共享资源进行访问的代码段落称为关键段落。各个任务访问同一共享资源的关键段落必须互斥,才能保障共享资源信息的可靠性和完整性。这种使得不同任务访问共享资源时能够确保共享资源信息可靠和完整的措施称为共享资源同步。,,实现共享资源同步的方法有:关中断、关调度、使用互斥信号量等。,,中
24、断有可能会引起任务切换,使某个低优先级的任务挂起,使某个高优先级的任务得到执行。如果这两个任务对同一个共享资源进行访问,这就有可能引起错误的结果。此时可以关闭中断。,,当共享资源的使用者全部是任务(即不包含,ISR,)时,就可以采用“关调度”的方法来访问共享资源。关调度可使,µC/OS-II,的任务调度器停止工作,不能进行任务切换,从而保证关键段落代码的执行不会受到其它任务的干扰。,,当需要访问的共享资源比较复杂,且访问过程比较费时时,关中断和关调度措施都会严重影响到系统的实时性。当该共享资源的使用者全部是任务(即不包含,ISR,)时,就可以采用互斥信号量的方法来访问这个共享资源。,8.3 µ
25、C/OS-II,程序设计技术,8.3.4,任务间的数据通信方法,,ISR,与任务函数在形式上与普通,C,函数没有什么区别。,ISR,的运行是由异步事件引起的,任务函数的运行是由,µC/OS-II,中的调度器调度的,它们之间不能直接调用,其数据通信是通过以下几种方法实现的。,,① 全局变量:,提供数,据的任务或,ISR,向全局变量中写数据,使用数据的任务或,ISR,从全局变量中读数据,对全局变量的访问必须遵循“共享资源同步”的规则。任务或,ISR,向全局变量中写入数据后,并不能通知相关的任务,也就是不能实现“行为同步”。,,② 内存数据块:当需要传输的数据量很大时,采用内存数据块来存放这些数据是
26、最方便的。内存数据块是共享资源,也不能用来实现“行为同步”。,,③ 消息邮箱:当每次发送的数据都要求接收方及时接收时,在数据通信的同时必然发生“行为同步”,此时可使用消息邮箱,并,要求接收消息的任务总是在等待消息。,,④ 消息队列:消息队列是具有“行为同步”功能和缓冲功能的数据通信手段,它与消息邮箱的不同之处是可以存放多条消息。,20,8.4 µC/OS-II,在,ARM,微处理器上的移植,,所谓移植,就是使一个实时内核能够在某个微处理器或微控制器上运行。,µC/OS-Ⅱ,在设计时就已经充分考虑了可移植性。,,8.4.1 µC/OS-II,对处理器的要求,,要使,µC/OS-Ⅱ,能正常运行,
27、处理器平台必须满足以下要求:,,① 处理器的,C,编译器能够产生可重入代码。,,② 用,C,语言就可以打开和关闭中断。,,③ 处理器支持中断,并且能产生定时中断,(,通常在,10,至,100Hz,之间,),。,,④ 处理器支持能够容纳一定量数据,(,一般是几千字节,),的硬件堆栈。,,⑤ 处理器有将堆栈指针和其它,CPU,寄存器读出和存储到堆栈(或内存) 的指令。,,,LPC2000,系列微控制器(,ARM7,)可以满足第③、④和⑤点的要求,所使用的,ADS1.2,的,C,编译器可以满足第①和②点要求。,21,8.4 µC/OS-II,在,ARM,微处理器上的移植,,8.4.2 µC/
28、OS-II,移植所涉及的文件,,移植,µC/OS-Ⅱ,涉及到三个文件:,,⒈,OS_CPU.H,文件,,OS_CPU.H,文件是操作系统移植头文件。其中包括了用,#define,定义的与处理器相关的常量、宏和数据类型等。其文件结构如下:,,…… //,数据类型,(,与编译器相关,),,,typedef,unsigned char INT8U; /*,无符号,8,位整数 *,/,,,typedef,unsigned,int,OS_STK; /*,堆栈入口宽度为,16,位 *,/,,……
29、 //,与处理器相关的代码,,#define OS_ENTER_CRITICAL() ??? /*,禁止中断 *,/,,#define OS_STK_GROWTH 1 //,堆栈增长方向:,1=,向下,, 0=,向上,,……,22,8.4 µC/OS-II,在,ARM,微处理器上的移植,,⒉,OS_CPU_A.ASM,文件,,OS_CPU_A.ASM,是与处理器有关的汇编语言代码文件,,,主要进行任务切换。它在,ADS,中的后缀名为“,.S”,,即文件名为,OS_CPU_A.S,。其中要求用户编写的四个汇编语言函数为:,,①,OSStar
30、tHighRdy(),:,µC/OS-Ⅱ,启动时运行优先级最高的任务,,②,OSCtxSw(),:任务级的任务切换函数,,③,OSIntCtxSw(),:中断级的任务切换函数,,④,OSTickISR(),:时钟中断处理函数,,如果用户的编译器支持在,C,语言代码中插入汇编语言代码的话,用户就可以将所有与处理器相关的代码放到,OS_CPU_C.C,文件中,而不必再拥有一些分散的汇编文件。,23,8.4 µC/OS-II,在,ARM,微处理器上的移植,,⒊,OS_CPU_C.C,文件,,OS_CPU_C.C,是移植中要修改的,C,语言程序文件。其中要求用户编写六个,C,语言函数:,,①,OSTa
31、skStkInit(),:初始化任务的堆栈结构,,②,OSTaskCreateHook(),:创建任务钩子函数,允许用户扩展,µC/OS-Ⅱ,功能,,③,OSTaskDelHook(),:删除任务钩子函数,,④,OSTaskSwHook(),:任务切换钩子函数,,⑤,OSTaskStatHook(),:统计任务钩子函数,用来扩展统计任务的功能,,⑥,OSTimeTickHook(),:时钟节拍钩子函数,,,用户必须编写的唯一函数是,OSTaskStkInit(),,其它五个钩子函数是用来扩展相应的功能,必须声明但不一定要包含代码。,24,8.4 µC/OS-II,在,ARM,微处理器上的移植,
32、,8.4.3 µC/OS-II,的移植过程及内容,,移植,µC/OS-Ⅱ,到一个具体处理器的过程如下:,,第一步:设置,OS_CPU.H,文件中的数据类型等,,① 定义与编译器无关的数据类型,,,µC/OS-Ⅱ,中没有使用与编译器相关的,C,中的,short,等数据类型,而是使用了如,INT16U,代表,16,位的无符号整数类型等。所以要对,INT16U,等进行重新定义。,,,typedef,unsigned short INT16U; /*,无符号,16,位整数 *,/,,,② 用,#define,设置一个常量的值,,根据微处理器和,C,编译器支持的堆栈增长方向来定义,µC/O
33、S-Ⅱ,中的堆栈增长方向常量,,#define OS_STK_GROWTH 1 /*,堆栈是从上往下增长的 *,/,,③ 用,#define,声明三个宏,,OS_ENTER_CRITICAL(),和,OS_EXIT_CRITICAL(),的功能分别是关中断和开中断。而宏,OS_TASK_SW(),的功能是在任务级进行任务调度。,25,8.4 µC/OS-II,在,ARM,微处理器上的移植,,第二步:编写四个汇编语言函数,(OS_CPU_A.ASM),,① OSStartHighRdy(),,在调用,OSStart(),之前,用户必须至少已经建立了自己的一个任务。当调用
34、,OSStart(),时,它会调用,OSStartHighRdy(),运行优先级最高的任务。,,②,OSCtxSw(),,该函数是任务级的任务切换函数,在任务因为被阻塞而主动请求或,CPU,调度时执行。主要工作是先将当前任务的,CPU,现场保存到该任务堆栈中,然后获得就绪的最高优先级任务的堆栈指针,从该堆栈中恢复此,CPU,现场,使之继续执行,从而完成一次任务切换。,,③,OSIntCtxSw(),,该函数是中断级的任务切换函数,在时钟中断,ISR,中发现有高优先级任务在等待时,不必返回被中断的任务,而是直接调度就绪的高优先级任务执行。,,④,OSTickISR(),,该函数是时钟中断处理函数
35、,主要负责处理时钟中断,调用系统实现的,OSTimeTick(),函数。如果有等待时钟信号的高优先级的任务,则需要在中断级别上调用其执行。,26,8.4 µC/OS-II,在,ARM,微处理器上的移植,,第三步:用,C,语言编写六个简单的函数,(OS_CPU_C.C),,在这些函数中,,OSTaskStkInit(),是最重要的,其功能是初始化任务的栈结构。,OSTaskStkInit(),的代码如下:,,OS_STK *OSTaskStkInit(void (*task)(void *pd),void *pdata,OS_STK *ptos, INT16U opt),,{,,OS_STK *
36、stk;,,opt = opt; // 'opt',没使用,作用是避免编译器警告,,stk = ptos; //,获取堆栈指针,,*stk = (OS_STK) task; /* pc */ //,建立任务环境,,ADS1.2,使用满递减堆栈,,*--stk = (OS_STK) task; /* lr */,,*--stk = 0; /* r12 */,,*--stk = 0; /* r11 */,,*--stk = 0;
37、 /* r10 */,,*--stk = 0; /* r9 */,,*--stk = 0; /* r8 */,,*--stk = 0; /* r7 */,,*--stk = 0; /* r6 */,,*--stk = 0; /* r5 */,27,8.4 µC/OS-II,在,ARM,微处理器上的移植,,*,--stk = 0; /* r4 */,,*--stk = 0;
38、 /* r3 */,,*--stk = 0; /* r2 */,,*--stk = 0; /* r1 */,,*--stk = (unsigned int) pdata; /* r0,,第一个参数使用,R0,传递 *,/,,*--stk = (USER_USING_MODE|0x00); /* CPSR,,允许,IRQ,FIQ,中断 *,/,,*--stk = 0; /*,关中断计数器,O
39、sEnterSum; */,,return (stk);,,},,,除,OSTaskStkInit(),之外,其余函数必须声明,但不一定要包含代码。,,第四步:测试,,一旦代码移植结束,下一步工作就是测试。测试首先可以在没有应用程序的情况下测试,也就是让内核自己测试自己。这样做有两个好处:第一,避免使问题复杂化;第二,如果出现问题,可以知道问题出在内核代码上。其次可以运行一些简单的任务和时钟节拍中断服务例程。最后,一旦多任务调度成功地运行了,再添加应用程序的任务就是非常简单的工作了。,28,8.4 µC/OS-II,在,ARM,微处理器上的移植,,8.4.4 µC/OS-II,的裁剪,,每个
40、具体的嵌入式应用系统对实时操作系统的要求并不完全相同。可以根据实际情况,把不需要的系统服务删除掉,即对其进行裁减。,,对,μC/OS-II,的裁剪是在配置文件,OS_CFG.H,中进行的,其配置项是由一系列,#define constant,语句构成。通过设置不同的配置项,可以达到保留或裁剪不同功能、降低系统对存储空间要求的目的。,,下面给出几个常用的配置项:,,①,OS_MAX_EVENTS,:定义系统中最大的事件控制块数量。,,②,OS_MAX_TASKS,:定义用户程序中最大的任务数。其值不能大于,62,。,,③,OS_LOWEST_PRIO,:设定系统中的任务最低优先级(,0,最高,,
41、63,最低)。,,④,OS_MAX_QS,:定义系统中最大的消息队列数。,,⑤,OS_CPU_HOOKS_EN,:此常量设定是否在文件,OS_CPU_C.C,中声明对外接口函数。,29,8.5,应用程序设计及实例,要让,µC/OS-Ⅱ,能够在,ARM,处理器上运行,就要对其进行移植,编写移植代码;而要在,µC/OS-Ⅱ,操作系统基础上设计应用程序,并且让其能够在,ARM,处理器上运行,还需要做那些工作呢?,,当,ARM,芯片加电复位后,系统就会进入管理模式、,ARM,状态,其,PC,(,R15,)寄存器的初始值为,0x00000000,,此时系统从,0x00000000,处开始执行程序。程序首
42、先应该对硬件及其运行环境进行初始化,然后才能转入相应的功能处理程序去运行。因此所设计程序分为两部分:硬件及其运行环境初始化部分和应用程序部分。,30,8.5,应用程序设计及实例,8.5.1,硬件及其运行环境初始化,,ARM,公司只设计内核,并不生产芯片,它把内核授权给其他厂商,其他厂商购买了授权后加入自己的外设,生产出各具特色的芯片。依据这种情况,并不容易设计出统一的初始化代码。,,在一般,32,位,ARM,应用系统中,软件大多数采用,C,语言进行编写,但为了能够进行系统初始化,通常会用一个汇编文件作为启动代码。根据具体设计方法不同,一个应用系统中会包含多个文件。下面分别介绍可能的各个文件。,
43、,⒈ 启动代码(,STARTUP.S,),,启动代码文件是用汇编语言编写的,内容包括:中断异常向量表的定义、各异常处理函数的定义、,ARM,控制器各工作模式堆栈的定义、芯片加密处理以及相关常量的定义、标识符的引入与导出等。,31,8.5,应用程序设计及实例,下面给出,LPC2131,的部分初始化代码:,,;,各模式堆栈大小的常量定义,,SVC_STACK_LEGTH EQU 0,,FIQ_STACK_LEGTH EQU 0,,IRQ_STACK_LEGTH EQU 256,,ABT_STACK_LEGTH EQU 0,,U
44、ND_STACK_LEGTH EQU 0,,;,各模式常量定义,,NoFIQ EQU 0x40 ;F,位,,Bit6,,NoInt EQU 0x80 ;I,位,,Bit7,,USR32Mode EQU 0x10 ;,用户模式:,10000,,SVC32Mode EQU 0x13 ;,管理模式:,10011,,SYS32Mode EQU 0x1f ;,系统模式:,11111,,FIQ32Mode EQ
45、U 0x11 ;FIQ,中断模式:,10001,,IRQ32Mode EQU 0x12 ;IRQ,中断模式:,10010,32,8.5,应用程序设计及实例,;,引入的外部标识符(在本文件中使用而在其他文件中定义),,IMPORT __use_no_semihosting_swi,,,IMPORT FIQ_Exception ;,快速中断异常处理程序,,,IMPORT TargetResetInit ;,目标板基本初始化,,,IMPORT __main
46、 ;C,语言主程序入口,,;,输出到外部的标识符(在本文件定义而在其他文件中可以使用),,EXPORT bottom_of_heap,,EXPORT StackUsr,,EXPORT Reset,,EXPORT __user_initial_stackheap,,,CODE32,,AREA vectors,CODE,READONLY,,ENTRY,33,8.5,应用程序设计及实例,;,中断异常向量表定义,,Reset,,LDR PC, ResetAddr ;0x00,:复位,,,LDR PC, UndefinedAddr ;0x04,:未定义
47、地址,,,LDR PC, SWI_Addr ;0x08,:软件中断,,,LDR PC, PrefetchAddr ;0x0C,:预取指中止,,,LDR PC, DataAbortAddr ;0x10,:数据中止,,,DCD 0xb9205f80 ;0x14,:保留,,,LDR PC, [PC, #-0xff0] ;0x18,:,IRQ,中断,,,LDR PC, FIQ_Addr ;0x1C,:,FIQ,中断,,;,各异常处理程序地址,,ResetAddr DCD
48、 ResetInit ;,复位初始化处理程序地址,,UndefinedAddr DCD Undefined ;,未定义指令处理程序地址,,SWI_Addr DCD SoftwareInterrupt ;,软件中断处理程序地址,,PrefetchAddr DCD PrefetchAbort ;,预取指中止处理程序地址,,DataAbortAddr DCD DataAbort ;,数据中止处理程序地址,34,8.5,应用程序设计及实例,Nouse DCD 0
49、 ;,未使用,,IRQ_Addr DCD 0 ;IRQ,中断,在“,LDR PC,[PC, #-0xff0]”,中处理,,FIQ_Addr DCD FIQ_Handler ;FIQ,中断处理程序地址,,;,各异常处理程序、开,/,关中断处理程序,(SWI),定义,,Undefined ;,未定义指令,,,B Undefined ;,死循环,,PrefetchAbort ;,取指令中止,,
50、,B PrefetchAbort ;,死循环,,DataAbort ;,取数据中止,,,B DataAbort,,FIQ_Handler ;,快速中断,,,STMFD SP!, {R0-R3, LR} ;,寄存器,R0-R3,,,LR,入栈,,,BL FIQ_Exception ;,调用,FIQ,异常处理程序(,Target.c,),,,LDMFD SP!, {R0-R3, LR} ;,寄存器,R0
51、-R3,,,LR,出栈,,,SUBS PC, LR, #4 ;,计算返回地址,35,8.5,应用程序设计及实例,SoftwareInterrupt ;,软中断,中断号为,0,~,3,,CMP R0, #4 ;,判断传过来的参数是否大于,4,,LDRLO PC, [PC,R0,LSL #2] ;,如果小于,4,,参数正确,进行查表,,,MOVS PC, LR ;,否则,参数出错,返回,,SwiFunction,,DCD IRQDisable ;0,号调用,禁止
52、,IRQ,中断,,,DCD IRQEnable ;1,号调用,使能,IRQ,中断,,,DCD FIQDisable ;2,号调用,禁止,FIQ,中断,,,DCD FIQEnable ;3,号调用,使能,FIQ,中断,,IRQDisable ;,禁止,IRQ,中断,,,MRS R0, SPSR ;,读取,SPSR,的值,,,ORR R0, R0, #NoInt ;,设置关,IRQ,中断(置位,I,位),,,MSR SPSR_c,
53、R0 ;,回写,SPSR,,MOVS PC, LR ;,返回,36,8.5,应用程序设计及实例,IRQEnable ;,使能,IRQ,中断,,,MRS R0, SPSR ;,读取,SPSR,的值,,,BIC R0, R0, #NoInt ;,设置开,IRQ,中断(清零,I,位),,,MSR SPSR_c, R0 ;,回写,SPSR,,MOVS PC, LR ;,返回,,FIQDisable
54、 ;,禁止,FIQ,中断,,,MRS R0, SPSR ;,读取,SPSR,的值,,,ORR R0, R0, #NoFIQ ;,(置位,F,位),,,MSR SPSR_c, R0 ;,回写,SPSR,(设置关,FIQ,中断),,,MOVS PC, LR ;,返回,,FIQEnable ;,使能,FIQ,中断,,,MRS R0, SPSR ;,读取,SPSR,的值,,,BIC R0, R0, #NoFIQ ;,(清零,F
55、,位),,,MSR SPSR_c, R0 ;,回写,SPSR,(设置开,FIQ,中断),,,MOVS PC, LR ;,返回,37,8.5,应用程序设计及实例,;,各模式堆栈初始化,,InitStack ;,此时禁止,IRQ,(,I=1,)和,FIQ,(,F=1,),且为,ARM,状态(,T=0,),,,MOV R0, LR,,MSR CPSR_c, #0xd3 ;,设置管理模式堆栈,,,LDR SP, StackSvc,,MSR CPSR_c, #0xd2 ;,设置中断模式
56、堆栈,,,LDR SP, StackIrq,,MSR CPSR_c, #0xd1 ;,设置快速中断模式堆栈,,,LDR SP, StackFiq,,MSR CPSR_c, #0xd7 ;,设置中止模式堆栈,,,LDR SP, StackAbt,,MSR CPSR_c, #0xdb ;,设置未定义模式堆栈,,,LDR SP, StackUnd,,MSR CPSR_c, #0xdf ;,设置系统模式堆栈,38,8.5,应用程序设计及实例,;,切换到系统模式之后,除非进行模式切换,否则将在系统模式
57、下运行。,,,LDR SP, =StackUsr,,MOV PC, R0 ;,返回,,;,复位异常处理程序,,ResetInit,,BL InitStack ;,初始化堆栈,,,BL TargetResetInit ;,目标板基本初始化,(target.c),,B __main ;,跳转到,C,语言入口,,;,库函数初始化堆和栈,不能删除,,__user_initial_stackheap,,LDR R0,=bottom_of_heap,,MOV PC,LR,
58、,StackSvc DCD SvcStackSpace+(SVC_STACK_LEGTH - 1)* 4 ;,管理模式堆栈,,StackIrq DCD IrqStackSpace+(IRQ_STACK_LEGTH - 1)* 4 ;IRQ,模式堆栈,,StackFiq DCD FiqStackSpace+(FIQ_STACK_LEGTH - 1)* 4 ;FIQ,模式堆栈,,StackAbt DCD AbtStackSpace+(ABT_STACK_LEGTH - 1)* 4 ;,中止模式堆栈,,StackUnd DCD UndtStackSpace+(UND_STACK_
59、LEGTH - 1)* 4 ;,未定义模式堆栈,39,8.5,应用程序设计及实例,;,芯片加密处理,,,IF :DEF: EN_CRP,,IF . >= 0x1fc,,INFO 1,"\nThe data at 0x000001fc must be 0x87654321.\nPlease delete some source before this line.",,ENDIF,,CrpData,,WHILE . < 0x1fc,,NOP ;,循环用,NOP,填充,直到,0x1fc,,WEND,,CrpData1,,DCD 0x8765432
60、1 ;,当此数为,0x87654321,时,用户程序被保护,,,ENDIF,40,8.5,应用程序设计及实例,;,各模式堆栈空间分配,,,AREA MyStacks, DATA, NOINIT, ALIGN=2 ;,通过分散加载文件定位,,SvcStackSpace SPACE SVC_STACK_LEGTH * 4 ;,管理模式堆栈空间,,IrqStackSpace SPACE IRQ_STACK_LEGTH * 4 ;,中断模式堆栈空间,,FiqStackSpace SPACE FIQ_STACK_LEGTH * 4 ;,快
61、速中断模式堆栈空间,,AbtStackSpace SPACE ABT_STACK_LEGTH * 4 ;,中止模式堆栈空间,,UndtStackSpace SPACE UND_STACK_LEGTH * 4 ;,未定义模式堆栈空间,,,AREA Heap, DATA, NOINIT ;Heap,通过分散加载文件定位,,bottom_of_heap SPACE 1,,AREA Stacks, DATA, NOINIT ;Stacks,通过分散加载文件定位,,StackUsr,,END,41,8.5,应用程序设计及实例,从前
62、面知道,,ARM,芯片复位后,系统进入管理模式、,ARM,状态,此时,PC,寄存器的值为,0x00000000,,系统就从,0x00000000,处开始执行程序。而,0x00000000,处放置着异常向量表,程序将根据异常向量表进行跳转。其执行过程如下:,,① 芯片根据异常处理程序地址表,得到复位处理程序(,ResetInit,)的地址,并跳转到复位处理程序(,ResetInit,)处去执行。,,② 调用,InitStack(),函数,初始化,ARM,处理器各工作模式的堆栈。,,③ 调用目标板初始化函数(在,TARGET.C,中定义),初始化目标板。,,④ 跳转到用户,C,程序入口,main(
63、),处,执行用户程序。,,在芯片启动过程中,在堆栈初始化(,InitStack(),函数)的末尾,处理器切换到系统模式,因而用户程序是在系统模式下运行的。,42,8.5,应用程序设计及实例,⒉ 目标板初始化(,TARGET.C,),,目标板初始化代码文件是用,C,语言编写的,其内容主要包括:启动代码调用的初始化函数、用户调用的初始化函数、一些异常处理函数以及一些系统库函数的实现等。,,⒊ 有关的头文件(*,.H,),,要设计一个系统,为了进行必要类型定义、常量与变量声明以及函数声明等,会有各种各样的头文件。如下:,,① 用户配置文件(,config.h,):包含一些类型定义和系统时钟定义。,,
64、②,target.h,文件:包含一些特殊定义和开,/,关,IRQ,中断、,FIQ,中断的函数声明。根据所用的目标板和编译器的要求来修改该文件。,,③,LPC2294.h,文件:包含,LPC2000,系列芯片的特殊寄存器定义文件,其中包含特殊寄存器的定义及固件程序函数的声明。,43,8.5,应用程序设计及实例,44,⒋ 分散加载文件(*,.scf,),,有时候希望把不同的代码放在不同的存储空间上,也就是生成的映像文件需要包含多个域,每个域在加载和运行时可以有不同的地址。要生成这样的映像文件,必须通过某种方式告诉连接器相关的地址映射关系。在,ADS,中,可以通过分散加载机制实现。,,8.5.2,应用程序设计,,(参考书中相关实例),,,,,(完),
- 温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 专题党课讲稿:以高质量党建保障国有企业高质量发展
- 廉政党课讲稿材料:坚决打好反腐败斗争攻坚战持久战总体战涵养风清气正的政治生态
- 在新录用选调生公务员座谈会上和基层单位调研座谈会上的发言材料
- 总工会关于2025年维护劳动领域政治安全的工作汇报材料
- 基层党建工作交流研讨会上的讲话发言材料
- 粮食和物资储备学习教育工作部署会上的讲话发言材料
- 市工业园区、市直机关单位、市纪委监委2025年工作计划
- 检察院政治部关于2025年工作计划
- 办公室主任2025年现实表现材料
- 2025年~村农村保洁员规范管理工作方案
- 在深入贯彻中央8项规定精神学习教育工作部署会议上的讲话发言材料4篇
- 开展深入贯彻规定精神学习教育动员部署会上的讲话发言材料3篇
- 在司法党组中心学习组学习会上的发言材料
- 国企党委关于推动基层党建与生产经营深度融合工作情况的报告材料
- 副书记在2025年工作务虚会上的发言材料2篇