ucosii(必做)
一、题目要求
- 下载附件,尝试在vc6.0 中编译运行ucos
- 下载附件,尝试在vs2017中编译运行ucos,给出你遇到的问题和解决方式
二、vc6.0中编译运行ucos
运行截图如下:
三、vs2017中编译运行ucos
安装失败未能实现
ucosii(选做)
一、题目要求
阅读附件中的代码,回答:
- ucos是如何分层的?
- HAL都有哪些代码?
- 分析任务是如何切换的。
二、ucos分层
ucosii一共分为四层:硬件相关层,驱动接口层,应用接口层,应用层。
1.硬件相关层:在这层中,要尽量所有硬件相关都囊括在其中。不管是GPIO还是定时器,或串行接口。只要提供标准统一的接口,就可以让上层会因此而变的很潇洒。这其中有三个最为重要的接口Open,Close,Ctrl。 Open主要来完成对应硬件初始化,形参中包括了些,初始化的相关参数。Close失能硬件。Ctrl来实现一些控制的修改如:优先级,中断回调函数等等,硬件的不同,内容也大为不同。
2.驱动接口层::这一层会用到一个或多个硬件层的接口,进行组合来实现特定功能的程序。这部分程序可举例进行说明。以Flash为列,它这里主要调用硬件层的SPI函数接口,但是主要的写,读指令都是在这里函数中完成的。
3.应用接口层:主要连接驱动和应用。又是连接应用层模块与模块之间的一层, 这一块有很强的特殊性,第一包括了驱动抽象接口层,第二包括了模块与模块的接口层。第三又与应用层密不可分。
4.应用层:这里所有模块都算是应用层,在模块内所有变量,或函数(接口除处)应该都本地化。在模块内可以有本模块化共用的主头文件,来方便本模块的维护。对硬件的访问其实直接调用应用接口就可完成。
三、HAL代码部分
硬件抽象层(HAL)是体系结构相关的底层程序,硬件抽象层就是:“将硬件差别与操作系统其他层相隔离的一薄层软件,它是通过采用使多种不同硬件在操作系统的其他部分看来是同一种虚拟机的做法来实现的。“硬件抽象层是一个编程层,允许计算机操作系统在逻辑层而不是硬件层与硬件设备交互。Windows 2000就是支持硬件抽象层的操作系统之一。操作系统核心或者硬件驱动程序都可以调用硬件抽象层。无论哪种情况,调用程序都不用了解硬件的具体设计细节,只需要给出抽象层所需的参数即可。
#if defined(STM32F205xx) #include "stm32f205xx.h" #elif defined(STM32F215xx) #include "stm32f215xx.h" #elif defined(STM32F207xx) #include "stm32f207xx.h" #elif defined(STM32F217xx) #include "stm32f217xx.h" #else #error "Please select first the target STM32F2xx device used in your application (in stm32f2xx.h file)" #endif stm32f2xx_hal.h:stm32f2xx_hal.c/h 主要实现HAL库的初始化、系统滴答相关函数、及CPU的调试模式配置 stm32f2xx_hal_conf.h :该文件是一个用户级别的配置文件,用来实现对HAL库的裁剪,其位于用户文件目录,不要放在库目录中。 库文件: stm32f2xx_hal_ppp.c/.h // 主要的外设或者模块的驱动源文件,包含了该外设的通用API stm32f2xx_hal_ppp_ex.c/.h // 外围设备或模块驱动程序的扩展文件。这组文件中包含特定型号或者系列的芯片的特殊API。以及如果该特定的芯片内部有不同的实现方式,则该文件中的特殊API将覆盖_ppp中的通用API。 stm32f2xx_hal.c/.h // 此文件用于HAL初始化,并且包含DBGMCU、重映射和基于systick的时间延迟等相关的API 其他库文件 用户级别文件: stm32f2xx_hal_msp_template.c // 只有.c没有.h。它包含用户应用程序中使用的外设的MSP初始化和反初始化(主程序和回调函数)。使用者复制到自己目录下使用模板。 stm32f2xx_hal_conf_template.h // 用户级别的库配置文件模板。使用者复制到自己目录下使用 system_stm32f2xx.c // 此文件主要包含SystemInit()函数,该函数在刚复位及跳到main之前的启动过程中被调用。 **它不在启动时配置系统时钟(与标准库相反)**。 时钟的配置在用户文件中使用HAL API来完成。 startup_stm32f2xx.s // 芯片启动文件,主要包含堆栈定义,终端向量表等 stm32f2xx_it.c/.h // 中断处理函数的相关实现
四、任务切换
需要任务切换时,就必须尽快切换(虽然由于优先级问题,仍然是本任务,但仍需相应一下);而一些处理器提供的中断机制就刚好满足这个需求,从而奠定了切换的基础。中断分为软中断和硬中断。所谓的软中断就是可有程序自身触发的中断(例如,SWI);而硬中断则是硬件本身检测到中断触发信号而强制触发中断。众所周知,任务就是一个个死循环,没有切换则一直执行程序。而切换又分为两类:自身切换(类似于自废武功)和强制切换(类似于暴力实施)。任务的自身切换是由程序自身触发的,从而使用软中断;强制切换则是达到允许执行时间后,而由硬件强制切换的,从而使用硬中断。
任务的自身切换则是因为任务本身知道自身在等待某个消息,而不想让CPU在自己身上空运行而触发中断;从而任务切换程序里面 OS_Sched() 就是调用的软中断OS_TASK_SW();
任务的强制切换则是因为任务本身的运行寿命到达限制,CPU强制切换到别的任务,让其他任务有执行的机会。从而负责强制切换的为定时器中断( interrupt 66 void OSTickISR(void)),其内部调用函数(void OSTimeTick (void))便负责任务切换的具体事务。
具体任务切换过程如下:
1.中断产生
2.CPU对当前的工作状态进行保存,做压栈操作,注意这里,不是每次压栈都是将所有寄存器内容压栈,而是中断内容越复杂,压栈内容
越多!
其中入栈时先SP+1再将内容压入当前SP所指示的堆栈单元中,出栈则先将SP所指示的内部ram单元中内容送入直接地址寻址的单元中,
再将SP减1.
堆栈用于响应中断或调用子程序时保护断点地址,也可通过栈操作指令(push和pop保护和恢复现场)
3.中断执行完后进行出栈操作
4.返回RETI