copyright 个人网站,漂亮网页模板,lamp网站开发,wordpress数据库修改登陆密码文章目录 一.概要二.什么是实时操作系统三.FreeRTOS的特性四.FreeRTOS的任务详解1.任务函数定义2.任务的创建3.任务的调度原理 五.CubeMX配置一个FreeRTOS例程1.硬件准备2.创建工程3.调试FreeRTOS任务调度 六.CubeMX工程源代码下载七.小结 一.概要
FreeRTOS是一个迷你的实时操… 文章目录 一.概要二.什么是实时操作系统三.FreeRTOS的特性四.FreeRTOS的任务详解1.任务函数定义2.任务的创建3.任务的调度原理 五.CubeMX配置一个FreeRTOS例程1.硬件准备2.创建工程3.调试FreeRTOS任务调度 六.CubeMX工程源代码下载七.小结 一.概要
FreeRTOS是一个迷你的实时操作系统内核。作为一个轻量级的操作系统功能包括任务管理、时间管理、信号量、消息队列、内存管理、记录功能、软件定时器、协程等可基本满足较小系统的需要。 由于RTOS需占用一定的系统资源(尤其是RAM资源)只有μC/OS-II、embOS、salvo、FreeRTOS等少数实时操作系统能在小RAM单片机上运行。相对μC/OS-II、embOS等商业操作系统FreeRTOS操作系统是完全免费的操作系统具有源码公开、可移植、可裁减、调度策略灵活的特点可以方便地移植到各种单片机上运行。
二.什么是实时操作系统
操作系统是一个控制程序作为硬件和应用程序之间的桥梁主要是和硬件打交道负责协调分配计算资源和内存资源给不同的应用程序使用并防止系统出现故障。面对来自不同应用程序的大量且互相竞争的资源请求操作系统通过一个调度算法和内存管理算法尽可能把资源公平且有效率地分配给不同的程序。应用程序则通过调用操作系统提供的API接口获得相应资源完成指定的任务。
实时操作系统RTOS-Real Time Operating System中实时Real Time指的是任务Task或者说实现一个功能的线程Thread必须在给定的时间(Deadline)内完成。
三.FreeRTOS的特性
具有抢占式或者合作式的实时操作系统内核 功能可裁剪最小占用10kB左右rom空间0.5kB ram空间 灵活的任务优先级分配 具有低功耗模式 有互斥锁、信号量、消息队列等功能 运行过程可追踪 支持中断嵌套
四.FreeRTOS的任务详解
FreeRTOS的核心是任务调度器Task Scheduler它负责按照一定的调度策略将任务分配给处理器执行。每个任务都是一个独立的函数可以有不同的优先级和堆栈大小。任务调度器根据任务的优先级和调度策略决定哪个任务被执行。
下图就是任务调度简单介绍
下面代码就是个简单的示例代码通过调用osThreadCreate函数创建了两个任务LED_Thread1驱动LED灯灭和LED_Thread2驱动LED灯亮。在main函数中通过调用osKernelStart函数启动了实时系统使得任务可以被调度执行由于两个任务都能不断运行所以能驱动LED灯闪烁。
//定义任务函数1
void LED_Thread1(void const * argument)
{(void) argument;for (;;){HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET);//PB4输出高LED灭osDelay(100);//等待100ms}
}
//定义任务函数2
void LED_Thread2(void const * argument)
{(void) argument;for (;;){HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);//PB4输出低LED亮osDelay(250);//等待250ms}
}int main(void)
{HAL_Init();SystemClock_Config();//外部8M晶振系统168M主频MX_GPIO_Init();MX_FREERTOS_Init();osThreadDef(THREAD1, LED_Thread1, osPriorityNormal, 0, 128);THREAD1Handle osThreadCreate(osThread(THREAD1), NULL);//建立任务1osThreadDef(THREAD2, LED_Thread2, osPriorityNormal, 0, 128);THREAD2Handle osThreadCreate(osThread(THREAD2), NULL);//建立任务2osKernelStart();while (1){}}1.任务函数定义
无论采用何种方法创建任务均需要用到任务函数。FreeRTOS 规定任务函数的返回值必须为void而且带有一个void型指针参数。
void LED_Thread1(void const * argument)
{(void) argument;for (;;){HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET);//PB4输出高LED灭osDelay(100);//等待100ms}
}
STM32F407VET6单片机只有一个内核那怎么让多个人同时干活呢其实每个子任务虽然都是死循环但并不是每个子任务一直都在执行每个子任务在执行期间可能需要延时这边就通过 osDelay(100)等待100ms,单片机就可以停止此任务然后切换到其它任务执行这样看起来就是多个人在同时干活了。
2.任务的创建
osThreadDef(THREAD1, LED_Thread1, osPriorityNormal, 0, 128);//定义一个任务任务名任务函数优先级堆栈大小
THREAD1Handle osThreadCreate(osThread(THREAD1), NULL); //根据上面定义的任务创建一个任务osThreadDef函数中的128是任务栈大小定义
任务栈大小指定了任务可以使用多少RAM来存储局部变量和其他临时数据。这个大小应该足够大能够容纳任务在执行期间可能出现的最大需求。
osThreadDef函数中的LED_Thread1是任务函数
任务函数是任务执行的代码它应该是一个无返回值的函数其参数是一个可选的指针可以用来传递任何需要的数据我们代码中的任务就是控制GPIO输出高或者低电平。
osThreadDef函数中的osPriorityNormal任务优先级
任务优先级决定了任务在操作系统调度下的执行顺序。数值越大优先级越高。
osThreadCreate函数的返回值THREAD1Handle是任务句柄
任务句柄是一个指针可以用来引用已经创建的任务以便可以在任务创建后对其进行操作例如删除、挂起、恢复等。
3.任务的调度原理
FreeRTOS默认使用抢占式调度策略对同等优先级的任务使用时间片轮询调度时间片轮询就是可轮流享有相同的单片机时间可设置一个时间片等于SysTick中断周期。 抢占式调度是指调度器始终运行优先级最高且处于可运行状态的任务无论任务何时可以运行。如在中断服务函数中更改了优先级最高且可运行的任务调度器会停止当前执行的低优先级任务并启动高优先级任务。 刚才程序中的osDelay 是通过将当前任务加入到延时列表中并设置一个定时器来在指定的延时时间延时时间过去之后将任务从延时列表中移除并将其设置为就绪状态。这样当定时器触发时任务重新被加入到就绪列表中等待被调度器再次调度执行。
上面代码中的LED_Thread1驱动LED灯灭和LED_Thread2驱动LED灯亮两个任务的调度顺序以及时间如下图所示横坐标是时间箭头代表运行顺序
下面代码截图就是操作系统底层寻找就绪任务的最高优先级获取优先级最高的就绪任务的 TCB任务控制块然后更新到 pxCurrentTCB 当前运行的任务只可能有一个因此pxCurrentTCB只是单个TCB_t指针它始终指向当前运行的任务。通过xPortPendSVHandlerPendSV_Handler函数实现调度 PendSV_Handler 是 ARM Cortex-M 处理器中的一个特殊的中断处理函数用于处理挂起 PendSVPending Supervisor Call中断。PendSV 中断是 Cortex-M 架构中的一种特殊的软件中断它可以用来实现任务切换或者其他与系统调度相关的操作。 PendSV_Handler 在中断向量表的位置
__asm void xPortPendSVHandler( void )
{extern uxCriticalNesting;extern pxCurrentTCB;extern vTaskSwitchContext;PRESERVE8mrs r0, pspisb/* Get the location of the current TCB. */ldr r3, pxCurrentTCB//获取当前TCB的位置 ldr r2, [r3]/* 任务是否使用FPU上下文如果是则保存vfp寄存器 */tst r14, #0x10it eqvstmdbeq r0!, {s16-s31}/* 保存核心寄存器 */stmdb r0!, {r4-r11, r14}/* 将新的栈顶保存到TCB的第一个成员中*/str r0, [r2]stmdb sp!, {r0, r3}mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITYmsr basepri, r0dsbisbbl vTaskSwitchContextmov r0, #0msr basepri, r0ldmia sp!, {r0, r3}/*pxCurrentTCB中的第一项是堆栈的任务顶部 */ldr r1, [r3]ldr r0, [r1]/*弹出核心寄存器*/ldmia r0!, {r4-r11, r14}/* 任务是否使用FPU上下文如果是则弹出vfp寄存器 */tst r14, #0x10it eqvldmiaeq r0!, {s16-s31}msr psp, r0isb#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */#if WORKAROUND_PMU_CM001 1push { r14 }pop { pc }nop#endif#endifbx r14
}
五.CubeMX配置一个FreeRTOS例程
1.硬件准备
STLINK接STM32F407VET6开发板STLINK接电脑USB口。
2.创建工程
打开STM32CubeMX软件,新建工程 Part Number处输入STM32F407VE再双击就创建新的工程
配置下载口引脚
配置外部晶振引脚
可以查看STM32F407VET6开发板原理图PB4连接LED灯所以配置PB4为GPIO输出 配置系统主频168Mhz,使用外部晶振 配置FreeRTOS
配置工程文件名保存路径KEIL5工程输出方式
生成工程
用Keil5打开工程
添加代码
3.调试FreeRTOS任务调度
调试代码能更好理解任务调度。 下载调试在LED_Thread1打断点程序能运行到断点处停止
在LED_Thread2打断点程序也能运行到断点处停止
在xPortPendSVHandler调度函数中打断点可以看到操作系统将要跳转到任务1运行
单步执行运行指针就跳转到任务1开始运行
xPortPendSVHandler调度函数中打断点可以看到操作系统将要跳转到任务2运行
单步执行运行指针就跳转到任务2开始运行
六.CubeMX工程源代码下载
通过网盘分享的文件13.FREERTOS实验.zip 链接: https://pan.baidu.com/s/1nHEHJUsQn-xOAdiQx0s-1A 提取码: y5gh
如果链接失效可以联系博主给最新链接
程序下载下来之后解压就行
七.小结
FreeRTOS实时操作系统能使在STM32软件开发中程序结构清晰单片机执行效率提升许多在多个任务模块的代码中可以考虑使用FreeRTOS。