完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
一、设计方案及可行性分析
题目要求:ucOS-III的移植;设计三个小实验:单一任务、多任务、并发任务。 1、设计方案 首先运行老师给的范例代码熟悉开发软件和开发板的使用;收集资料简单了解UCOSIII的基本概念,然后进行UCOSIII移植(移植到STM32f407开发板);移植成功后开始进行UCOSIII实例编程(实例老师给了,就只需要进行代码修改与调试运行) 2、可行性分析 uC/OS-III(Micro C OS Three微型的C语言编写的操作系统第3版)是一个可升级、可固化、基于优先级的实时内核。它管理的任务个数不受限制。它是第三代内核,提供了现代实时内核所期望的所有功能包括资源管理、同步、内部任务交流等。uC/OS-III也提供了很多特性是在其他实时内核中所没有的,比如能在运行时测量运行性能,直接得发送信号或消息给任务,任务能同时等待多个信号量和消息队列。 OSIII有以下几个重要特性: 极短的关中断时间 任务数目不受限制 优先级数量不受限制 内核对象数目不受限制 软件定时器 同时等待多个内核对象 直接向任务发送信号 直接向任务发送消息 任务寄存器 任务时钟节拍处理 防止死锁 所谓移植,是指能让uC/OS-III在某个微处理器或者为控制器上能够运行。为了方便移植,uC/OS-III的绝大部分代码使用C语言写的。在移植过程中我们重点是需要用C语言和汇编语言编写一些与处理器有关的代码。而且uC/OS-III中那些与CPU寄存器打交道的代码只能用汇编语言编写(除非C编译器支持内嵌汇编语言)。得益于uC/OS-III在设计时对可移植性的充分考虑,其在各个平台上的移植还是比较容易的。值得一提的是Micrium公司已经在各个主流的处理器上做好了移植工作,这些移植好的代码在官网上是可以直接免费下载的。我们站在巨人的肩膀上从官方移植文件入手。 二、详细设计思路 1.UCOSIII移植过程 1)移植成功的几个前提条件: 处理器有可用的ANSI C编译器,能生成可重入性代码。 处理器支持中断,并且可产生定时中断(通常在10~1000Hz之间)。 可以开关中断。 处理器支持能够容纳足够多的数据(数千字节)的硬件堆栈。 处理器有将堆栈指针和其他CPU寄存器读出并存储到堆栈或内存中的指令。 处理器有足够的RAM空间用来存储UCOSIII的变量、数据结构体和内部任务堆栈。 编译器应该支持32位数据类型。 移植主要涉及三方面的内容:CPU、操作系统和板级代码(板级支持包BSP)。我们的移植对象为STM32F407。 2)移植具体过程 选择一个基础的用ST官方库代码进行编写的程序作为移植基础。这里我们选择一个简单的跑马灯程序作为移植的基础程序(跑马灯程序本来是裸机跑的程序,我们要将uC/OS-III移植到该跑马灯程序中)。 下载UCOSIII源码。 在待移植的工程目录(跑马灯程序)中新建一个uC/OS-III文件夹,然后将我们下载的Micrium官方移植工程中的uC-CPU、uC-LIB、UCOS-III这三个文件复制到工程中。这里还需在UCOSIII文件中新建两个文件:UCOS_BSP、UCOS_CONFIG。向UCOS_CONFIG中添加文件,复制Micrium官方移植好的工程中的相关文件到UCOS_CONFIG文件夹下,文件路径为:Micrium官方移植SoftwareEvalBoardsMicriumuC-Eval-STM32F107uCOS-III;复制Micrium官方移植好的工程的相关文件到UCOS_BSP文件下,路径为:Micrium官方移植SoftwareEvalBoardsMicriumuC-Eval-STM32F107BSP。 准备好了所需文件后,还要将文件添加到我们的工程中去,在KEIL中先添加分组,如下图所示: 添加完分组还要给分组添加文件,添加情况如图所示: 为了编译时能找到相关文件,这里还需要设置包含路径,设置情况如下图所示: 修改bsp.c和bsp.h文件;修改os_cpu_c.c文件;修改os_cfg_app.h 修改sys.h: 将SYSTEM_SUPPORT_OS置1,以支持UCOS操作系统。 2.说明程序中用到的关键数据类型的定义,绘制关键程序的流程图,以及各子模块间的调用关系图。 本次实验中,我们用到FSMC驱动LCD,通过前面电路的介绍,我们知道TFTLCD的RS接在FSMC的A18上面,CS接在FSMC_NE4上,并且是16位数据总线,即我们使用的是FSMC的第四区,我们在lcd.h里面定义LCD操作结构体为: //LCD地址结构体 typedef struct { u16 LCD_REG; u16 LCD_RAM; } LCD_TypeDef; //使用NOR/SRAM的 Bank1.sector4,地址位HADDR[27,26]=11 A18作为数据命令区分线 //注意16位数据总线时STM32内部地址会右移一位对齐! #define LCD_BASE ((u32)(0x6C000000 | 0x0007FFFE)) #define LCD ((LCD_TypeDef *) LCD_BASE) 其中,LCD_BASE,必须根据外部电路的连接设定,我们使用Bank1.sector4就是从地址0X6C000000开始,而0X0007FFFE,是A18的偏移量。我们将这个地址强制转换成LCD_TypeDef的结构体地址,就可以得到LCD-》LCD_REG的地址为0X6C07FFFE,而LCD-》LCD_RAM的地址为0X6C080000。所以有了这个定义,当我们要往LCD写命令/数据时,可以这样写: LCD-》LCD_REG=CMD;//写命令LCD-》LCD_RAM=DATA;//写数据而读的时候反过来操作就可以了,如下表示:CMD =LCD-》LCD_REG;//读LCD寄存器DATA =LCD-》LCD_RAM;//读LCD数据 接下来介绍lcd.h里的另一个重要结构体: //写寄存器函数 //regval:寄存器值 void LCD_WR_REG(vu16 regval) { regval=regval; //使用-O2优化的时候,必须插入的延时 LCD-》LCD_REG=regval;//写入要写的寄存器序号 } //写LCD数据 //data:要写入的值 void LCD_WR_DATA(vu16 data) { data=data; //使用-O2优化的时候,必须插入的延时 LCD-》LCD_RAM=data; } //读LCD数据 //返回值:读到的值 u16 LCD_RD_DATA(void) { vu16 ram; //防止被优化 ram=LCD-》LCD_RAM; return ram; } //写寄存器 //LCD_Reg:寄存器地址 //LCD_RegValue:要写入的数据 void LCD_WriteReg(u16 LCD_Reg,u16 LCD_RegValue) { LCD-》LCD_REG = LCD_Reg; //写入要写的寄存器序号 LCD-》LCD_RAM = LCD_RegValue; //写入数据 } //读寄存器 //LCD_Reg:寄存器地址 //返回值:读到的数据 u16 LCD_ReadReg(u16 LCD_Reg) { LCD_WR_REG(LCD_Reg); //写入要读的寄存器序号 delay_us(5); return LCD_RD_DATA(); //返回读到的值 } //开始写GRAM void LCD_WriteRAM_Prepare(void) { LCD-》LCD_REG=lcddev.wramcmd; } //LCD写GRAM //RGB_Code:颜色值 void LCD_WriteRAM(u16 RGB_Code) { LCD-》LCD_RAM = RGB_Code;//写十六位GRAM } 因为FSMC自动控制了WR/RD/CS等这些信号,通过这些函数,我们就可以对LCD进行各种操作了。 接下来要介绍的函数是坐标设置函数,代码如下: //设置光标位置 //Xpos:横坐标 //Ypos:纵坐标 void LCD_SetCursor(u16 Xpos, u16 Ypos) { if(lcddev.id==0X9341||lcddev.id==0X5310) { LCD_WR_REG(lcddev.setxcmd); LCD_WR_DATA(Xpos》》8); LCD_WR_DATA(Xpos&0XFF); LCD_WR_REG(lcddev.setycmd); LCD_WR_DATA(Ypos》》8); LCD_WR_DATA(Ypos&0XFF); }else if(lcddev.id==0X6804) { if(lcddev.dir==1)Xpos=lcddev.width-1-Xpos;//横屏时处理 LCD_WR_REG(lcddev.setxcmd); LCD_WR_DATA(Xpos》》8); LCD_WR_DATA(Xpos&0XFF); LCD_WR_REG(lcddev.setycmd); LCD_WR_DATA(Ypos》》8); LCD_WR_DATA(Ypos&0XFF); }else if(lcddev.id==0X5510) { LCD_WR_REG(lcddev.setxcmd); LCD_WR_DATA(Xpos》》8); LCD_WR_REG(lcddev.setxcmd+1); LCD_WR_DATA(Xpos&0XFF); LCD_WR_REG(lcddev.setycmd); LCD_WR_DATA(Ypos》》8); LCD_WR_REG(lcddev.setycmd+1); LCD_WR_DATA(Ypos&0XFF); }else { if(lcddev.dir==1)Xpos=lcddev.width-1-Xpos;//横屏其实就是调转x,y坐标 LCD_WriteReg(lcddev.setxcmd, Xpos); LCD_WriteReg(lcddev.setycmd, Ypos); } } 该函数实现将LCD的当前操作点设置到指定坐标(x,y)。因为不同型号的屏不太一样,所以进行了区别对待。 3.实验现象 1.编译结果 2.下载 3.LCD显示高优先级任务 4.LCD显示中优先级任务 5.LCD显示低优先级任务 三、源代码及注释 该部分代码通过切换不同的任务来得到不同的实验现象。其中,高优先级任务将显示一个矩形并带有实验日期;中优先级将显示绿色矩形+横线,带有“Middle Task”字样;低优先级将显示“Low Task”字样和实验日期。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1683 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1582 浏览 1 评论
1013 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
703 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1627 浏览 2 评论
1892浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
675浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
538浏览 3评论
558浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
526浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-4 02:52 , Processed in 0.778244 second(s), Total 77, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号