一、 实验简介(实验目的)
在本实验中实现UCOSII(实时多任务操作系统内核)的使用,最重要的应用——任务调度。
二、 实验设备(实验设备及用到的模块)
1.电脑:window10及以上
2.开发板名称:正点原子战舰V3 STM32F103开发板
3.模块名称:LED模块
4.数据通信方式及设备
三、 实验原理(软硬件全面阐述)
1.芯片该部分工作原理
LED部分对应芯片引脚
在战舰 STM32 开发板上的LED0连接的引脚是PB5,LED1连接的引脚是PE5。
2.模块工作原理、电路图
LED的STM32连接原理图
通过位带操作 PB5 输出高低电平从而控制 LED0。
3. 用到的库函数阐述
(1)、建立任务函数
OSTaskCreate(void(*task)(void*pd),void*pdata,OS_STK*ptos,INTU prio)
(2)、任务删除函数
INT8U OSTaskDel(INT8U prio);
(3)、请求任务删除函数
INT8U OSTaskDelReq(INT8U prio);
(4)、改变任务的优先级函数
INT8U OSTaskChangePrio(INT8U oldprio,INT8U newprio);
(5)、任务挂起函数
INT8U OSTaskSuspend(INT8U prio);
(6)、任务恢复函数
INT8U OSTaskResume(INT8U prio);
(7)、任务信息查询
INT8U OSTaskQuery(INT8U prio,OS_TCB *pdata);
4. 关键程序分析
UCOSIII默认有5个系统任务:
- 空闲任务:UCOSIII创建的第一个任务,UCOSIII必须创建的任务,此任务有UCOSIII自动创建,不需要用户手动创建。
- 时钟节拍任务:此任务也是必须创建的任务。
- 统计任务:可选任务,用来统计CPU使用率和各个任务的堆栈使用量。此任务是可选任务,由宏OS_CFG_STAT_TASK_EN控制是否使用此任务。
- 定时任务:用来向用户提供定时服务,也是可选任务,由宏OS_CFG_TMR_EN控制是否使用此任务。
- 中断服务管理任务:可选任务,由宏OS_CFG_ISR_POST_DEFERRED_EN控制是否使用此任务。
在主函数的代码 start_task 中创建了 2个任务分别为 led0_task, led1_task。LED0亮了隔80ms灭了隔920ms,LED1 每隔 300ms 翻转一次。
四、 程序分析(程序总体介绍,模块设计)
1.程序总体概述
(1).创建任务堆栈
任务堆栈是任务的重要部分,堆栈是在RAM中按照“先进先出(FIFO)”的原则组织的一块连续的存储空间。为了满足任务切换和响应中断时保存CPU寄存器中的内容及任务调用其它函数时的需要,每个任务都应该有自己的堆栈。
(2).任务堆栈初始化
把任务初始数据存放到任务堆栈的工作就叫做任务堆栈的初始化,UCOSIII提供了完成堆栈初始化的函数:OSTaskStkInit()。
(3).使用任务堆栈
作为任务创建函数OSTaskCreate()的参数,函数OSTaskCreate()如下:
(4).堆栈增长
函数OSTaskCreate()中的参数p_stk_base是任务堆栈基地址,那么如果CPU的堆栈是向上增长的话那么基地址就&START_TASK_STK[0],如果CPU堆栈是向下增长的话基地址就是&START_TASK_STK[START_STK_SIZE-1]STM32的堆栈是向下增长的。
2. 各个模块阐述
(1).delay.c文件
是ALIENTEK编写的文件,主要是使用滴答定时器来完成高精度延时。在使用UCOS的时候还完成了针对UCDOS的相关配置,主要是滴答定时器作为CUOS系统时基的配置。
(2).滴答定时器
在STM32中SysTick就是用于产生系统时基的,SysTick有4个控制寄存器。滴答定时器的中断优先级为最低,在汇编文件os_cpu_a.asm文件中定义。
(3).usart.c和sys.c文件
使用UCOS和不使用UCOS下usart.c文件最大的不同就是串口1中断服务函数:USART1_IRQHandler(),sys.c文件则完全相同,使用UCOS时的串口1中断服务函数。
void USART1_IRQHandler(void)
{
#if SYSTEM_SUPPORT_OS //使用UCOS操作系统
OSIntEnter();
#endif
//中间处理函数,和不是用UC0S时相同
#if SYSTEM SUPPORT OS
OSIntExit(); //退出中断
#endif
}
3.程序分析总结
1) 移植 UCOSII
ALIENTEK 提供的SYSTEM 文件夹里面的系统函数直接支持UCOSII,只需要在sys.h 文件里面将:SYSTEM_SUPPORT_UCOS 宏定义改为1。即可通过 delay_init 函数初始化UCOSII 的系统时钟节拍,为UCOSII 提供时钟节拍。
2) 编写任务函数并设置其堆栈大小和优先级等参数
设置函数堆栈大小,需要根据函数的需求来设置,如果任务函数的局部变量多,嵌套层数多,那么相应的堆栈就得大一些。设置任务优先级,需要根据任务的重要性和实时性设置,记住高优先级的任务有优先使用 CPU 的权利。
3) 初始化 UCOSII,并在 UCOSII 中创建任务
调用 OSInit,初始化 UCOSII 的所有变量和数据结构,然后通过调用 OSTaskCreate 函数创建我们的任务。
4) 启动 UCOSII
调用OSStart,启动UCOSII。