基于stm32的嵌入式操作系统程序设计及实现本科毕业论文(编辑修改稿)内容摘要:

包括创建任务,删除任务,改变任务的优先级,任务挂起和恢复等。 系统初始化时会自动产生两个任务:一个是空闲任务,它的优先级最低,该任务仅给一个整型变量做累加运算;另一个是统计任务,它的优先级为次低,该任务负责统计当前 CPU的利用率。 181。 C/OSII 任务间通信方式 ( 1) 信号量 信号量由两部 分组成:一部分是 16位的无符号整型信号量的计数值;另一部分是由等待该信号量的任务组成的等待任务表。 信号量用于对共享资源的访问,用钥匙符号,符号旁数字代表可用资源数,对于二值信号量该值为 1。 信号量还可用于表示某事件的发生,用旗帜符号表示,符号旁数字代表事件已经发生的次数。 互斥型信号量用于处理共享资源。 武昌工学院毕业论文(设计)专用稿纸 7 ( 2) 消息邮箱 一种通信机制,可以使一个任务或者中断服务子程序向另一个任务发送一个指针型的变量,通常该指针指向一个包含了消息的特定数据结构。 ( 3) 消息队列 另一种通信机制,允许一个任务或者中断服务子程序向另一 个任务发送以指针方式定义的变量或其它任务,因具体应用不同,每个指针指向的包含了消息的数据结构的变量类型也有所不同。 STM32 上移植方法 平台需求 181。 C/OSII的正常运行需要处理器平台满足以下要求: ( 1) 处理器的 C编译器 能产生可重入代码。 ( 2) 用 C语言就可以打开和关闭中断。 ( 3) 处理器支持中断,并且能产生定时中断 (通常在 10至 100Hz之间 )。 ( 4) 处理器支持能够容纳一定量数据 (可能是几千字节 )的硬件堆栈。 ( 5) 处理器有将堆栈指针和其它 CPU寄存器读出和存储到堆栈或内存中的指令。 移植方法 ( 1) 内核头文件( ) 在 OS_CP 中,主要声明了一些与微处理器相关的常量、宏和 typedef。 定义与处理器无关的数据类型 typede f unsigned char BOOLEAN。 typedef unsigned char INT8U。 typedef signed char NT8S。 typedef unsigned short INT16U。 typedef signed short INT16S。 typedef unsigned int INT32U。 typedef signed int NT32S。 typedef float FP32。 typedef double FP64。 typedef unsigned int OS_STK。 typedef unsigned int OS_CPU_SR。 在 STM32处理器及 keil MDK 或者 IAR 编译环境中可以通过查手册得知short类型是 16位而 int类型是 32位,这对于 CortexM3内核是一致的。 故这部分代码无需修改。 尽管 181。 C/OSII定义了 float 类型和 double 类型,但为了方便移植它们在 181。 C/OSII源代码中并未使用。 为了方便使用堆栈, 181。 C/OSII定义了一个堆栈数据类型。 在 CortexM3 中寄存器为 32位,故定义堆栈的长度也为 32位。 CortexM3 状态寄存器为 32位,定义 OS_CPU_SR主要是为了在进出临界代码 段武昌工学院毕业论文(设计)专用稿纸 8 保存状态寄存器。 ( 2) 临界代码段 181。 C/OSII为了保证某段代码的完整执行,需要临时的关闭中断,在这 段代码执行完成之后再打开中断。 这样的代码段称作临界代码段。 181。 C/OSII通过定义两个宏 OS_ENTER_CRITICAL() 和 OS_EXIT_CRITICAL() 来分别实现中断的关闭和打开。 一般来说,采用方法 3来实现这两个宏。 这两个宏分别定义如下 : define OS_CRITICAL_METHOD 3 define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save()。 } define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr)。 } 函数 OS_CPU_SR_Save()和 OS_CPU_SR_Restore(cpu_sr)在 中定义。 同时得注意,在使用这两个宏之前,必须定义 OS_CPU_SR cpu_sr。 否则编译时将出错。 ( 3) 栈的增长方向 尽管 181。 C/OSII支持两种方向生长的栈,但对于以 CortexM3为内核 的 STM32 微处理器来说,它支持向下增长的满栈,故需要定义栈增长方向宏为 1。 即定义成如下形式 define OS_STK_GROWTH 1 ( 4) 任务级任务切换 任务级任务切换调用宏 OS_TASK_SW()来实现。 因为这个宏也是与处理器相关的,因此这个宏在。 ( 5) 其他函数声明 在 OS_ ,还声明了以下几个函数,这几个函数均在 中实现。 void OSCtxSw(void)。 void OSIntCtxSw(void)。 void OSStartHighRdy(void)。 void OS_CPU_PendSVHandler(void)。 ( 6) 与处理器相关的汇编代码( ) 在 OS_CP。 OS_CPU_SR_Save()。 OS_CPU_SR_Restore()。 OSStartHighRdy()。 OSCtxSw()。 OSIntCtxSw()。 函数 实现 ( 1) 关中断函数( OS_CPU_SR_Save()) 即先保存当前的状态寄存器然后关中断。 故关中断实现代码如下 武昌工学院毕业论文(设计)专用稿纸 9 OS_CPU_SR_Save MRS R0, PRIMASK; CPSID I BX LR 这也是宏 OS_ENTER_CRITICAL() 的最终实现。 ( 2) 恢复中断函数( OS_CPU_SR_Restore()) 这是宏 OS_EXIT_CRITICAL()的最终实现。 也就是将状态寄存器的内容从 R0中恢复,然后跳转回去。 此函数完成的将中断状态恢复到关中断前的状态。 其代码如下: OS_CPU_SR_Restore MSR PRIMASK, R0 BX LR CortexM3处理器有单独的指令来打开或者关闭中断,所以这两个函数实现起来很简单。 ( 3) 启动最高优先级任务运行( OSStartHighRdy()) OSStart()调用 OSStartHighRdy()来启动最高优先级任务的运行,从而启动整个系统。 OSStartHighRdy()主要完成以下几项工作: ① 为任务切换设置 PendSV的优先级 ; ② 为第一次任务切换设置栈指针为 0; ③ 设置 OSRunning = TRUE,以表明系统正在运行; ④ 触发一次 PendSV,打开中断等待第一次任务的切换。 ( 4) 任务级和中断级任务切换 因为 CortexM3进入异常自动保存寄存器 R3R0, R12, LR, PC和 xPSR这种的特殊机制,这两个函数都是触发一次 PendSV来实现任务的切换。 首先是微处理器自动保存上面提到的寄存器,然后把当前的堆栈指针保存到任务的栈中,将要切换的任务的优先级和任务控制块的指针赋值给运行时的最高优先级指针和运行时的任务控制块指针,最后再把要运行的任务的堆栈指针赋值给微处理器的堆 栈指针,这样就可以退出中断服务程序了。 中断服务程序退出的时候将自动出栈 R3R0, R12, LR, PC和 xPSR。 具体的 PendSV服务程序的伪代码如下: OS_CPU_PendSVHandler : // 进入异常,处理器自动保存 R3R0, R12, LR, PC和 xPSR if (PSP != NULL) //判断不是开始第一次任务 { 保存 R4R11到任务的堆栈; OSTCBCurOSTCBStkPtr = SP。 //保存堆栈的指针到任务控制块 } 武昌工学院毕业论文(设计)专用稿纸 10 OSTaskSwHook()。 //实现用户扩展功能而定义的钩子 OSPrioCur = OSPrioHighRdy。 //设置运行任务为最高优先级就绪任务 OSTCBCur = OSTCBHighRdy。 // 设置运行的任务控制块为最高 //就绪任控制块务 PSP = OSTCBHighRdyOSTCBStkPtr。 //将要切换的任务堆栈指 // 针赋给微处理器的堆栈指 // 针从而实现切换 从堆栈中恢 复 R4R11。 从异常中返回; // 退出异常,处理器自动恢复 R3R0, R12, LR, PC和 xPSR 这样很容易写出 PendSV中断服务程序的代码了。 ( 5) 与 CPU 相关的 C 函数和钩子函数( ) 这个文件中包含 10个函数,具体如下: OSInitHookBegin ()。 OSInitHookEnd ()。 OSTaskCreateHook ()。 OSTaskDelHook ()。 OSTaskIdleHook ()。 OSTaskStatHook ()。 OSTaskStkInit ()。 OSTaskSwHook ()。 OSTCBInitHook ()。 OSTimeTickHook ()。 这 10个函数有 9个是为了扩展用户功能而定义的钩子函数,这些钩子函数可以都为空函数,也可以加上一些用户需要的扩展功能。 另外一个不是钩子函数,它是 OSTaskStkInit()。 这个函数的功能是当一个任务被创建时,它完成这个任务堆栈的初始化。 这个函数首先将用户为任务分配的堆栈顶 地址赋值给一个栈指针变量,然后再通过这个栈指针向任务的栈空间写入初值。 这个初值无关紧要,为0就可以了。 这个函数的代码时下如下: OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) { OS_STK *stk。 (void)opt。 //防止编译器报错 stk = ptos。 // 将栈顶地址赋值给栈指针变量 // 以进入异常的顺序来给栈赋初值 *(stk) = (INT32U)0x00000000L。 //xPSR *(stk) = (INT32U)task。 //Entry Point 武昌工学院毕业论文(设计)专用稿纸 11 *(stk) = (INT32U)0x00000000L。 // R14 (LR) *(stk) = (INT32U)0x00000000L。 //R12 *(stk) = (INT32U)0x00000000L。 //R3 *(stk) = (INT32U)0x00000000L。 // R2 *(stk) = (INT32U)0x00000000L。 // R1 *(stk) = (INT32U)p_arg。 //R0 : 传递的参数 // 剩下的寄存器初始化 *(stk) = (INT32U)0x00000000L。 // R11 *(stk) = (INT32U)0x00000000L。 //R10 *(stk) = (INT32U)0x00000000L。 // R9 *(stk) = (INT32U)0x00000000L。 //R8 *(stk) = (INT32U)0x00000000L。 //R7 *(stk) = (INT32U)0x00000000L。 // R6 *(stk) = (INT32U)0x00000000L。 // R5 *(stk) = (INT32U)0x00000000L。 // R4 return (stk)。 } 其他的钩子函数都为空函数。 这样,整个移植的代码就介绍完了。 整个移植的过程非常容易。 剩下的工作就是编写用户任务,并在开发板上验证,以此来验证该移植方案是可行的和成功的。 武昌工学院毕业论文(设计)专用稿纸 12 3 LCD 屏程序设计及调试 工 具概述 RVMDK 源自德国的 KEIL 公司,是 RealView MDK 的简称。 RealView MDK集成了业内最领先的技术,支持 ARM ARM9 和 CortexM3 核处理器,自动配置启动代码,集成 Flash 烧写模块,强大的 Simulation 设备模块,性能分析等功能。 keil4 工程建立以及仿真方法 ( 1) 新建工程。
阅读剩余 0%
本站所有文章资讯、展示的图片素材等内容均为注册用户上传(部分报媒/平媒内容转载自网络合作媒体),仅供学习参考。 用户通过本站上传、发布的任何内容的知识产权归属用户或原始著作权人所有。如有侵犯您的版权,请联系我们反馈本站将在三个工作日内改正。