freertos使用基础
FreeRtos快速入门
- 一,基础知识
- 1.工作方式简介(不深入介绍原理)
- 2,移值
- 3,什么是内存管理
- 二,API的作用跟使用方法(基础知识)
- 一,任务管理(怎么创建任务,任务传递参数,删除任务。。。)
- 1.创建任务
- 2: 使用任务参数(传递参数)
- 3. 任务的删除
- 4: 设置任务优先级
- 5. 任务状态(运行和非运行)
- 5.1.阻塞状态Blocked:
- 5.2. 暂停状态Suspended:
- 5.3. 就绪状态Ready:
- 6空闲任务及其钩子函数
- 7.调度算法
- 三,实战代码操作
最近跟着韦东山老师学习 FreeRTOS ,记录下来加强记忆。
一,基础知识
1.工作方式简介(不深入介绍原理)
FreeRTOS 的官网为:https://www.freertos.org/
FreeRTOS 的内核支持抢占式, 合作式和时间片调度。任务与任务、 任务与中断之间可以使用任务通知、消息队列、二值信号量、数值型信号量、 递归互斥信号量和互斥信号量进行通信和同步。
RTOS 系统的核心就是任务管理, FreeRTOS 是一个抢占式的实时多任务系统, 其任务调度器也是抢占式的。高优先级的任务可以打断低优先级任务的运行而取得 CPU 的使用权,这样就保证了那些紧急任务的运行。 这样我们就可以为那些对实时性要求高的任务设置一个很高的优先级。 高优先级的任务执行完成以后重新把 CPU 的使用权归还给低优先级的任务,这个就是抢占式多任务系统的基本原理。
2.任务状态介绍
● 运行态
当一个任务正在运行时, 那么就说这个任务处于运行态, 处于运行态的任务就是当前正在使用处理器的任务。 如果使用的是单核处理器的话那么不管在任何时刻永远都只有一个任务处于运行态。
● 就绪态
处于就绪态的任务是那些已经准备就绪(这些任务没有被阻塞或者挂起), 可以运行的任务,但是处于就绪态的任务还没有运行,因为有一个同优先级或者更高优先级的任务正在运行!
● 阻塞态
如果一个任务当前正在等待某个外部事件的话就说它处于阻塞态, 比如说如果某个任务调用了函数 vTaskDelay()的话就会进入阻塞态, 直到延时周期完成。任务在等待队列、信号量、事件组、通知或互斥信号量的时候也会进入阻塞态。任务进入阻塞态会有一个超时时间,当超过这个超时时间任务就会退出阻塞态,即使所等待的事件还没有来临!
● 挂起态
像阻塞态一样,任务进入挂起态以后也不能被调度器调用进入运行态, 但是进入挂起态的任务没有超时时间。任务进入和退出挂起态通过调用函数 vTaskSuspend()和 xTaskResume()。
————————————————
版权声明:本文为CSDN博主「温人之周.」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xxxx123041/article/details/122229384
2,移值
链接: https://blog.csdn.net/weixin_43930521/article/details/124432875
3,什么是内存管理
链接: https://img-blog.csdnimg.cn/20200313171835198.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMjEyMDky,size_16,color_FFFFFF,t_70
二,API的作用跟使用方法(基础知识)
一,任务管理(怎么创建任务,任务传递参数,删除任务。。。)
记住这个图
BaseType_t xTaskCreate
( TaskFunction_t pxTaskCode, // 函数指针, 任务函数const char * const pcName, // 任务的名字const configSTACK_DEPTH_TYPE usStackDepth, // 栈大小,单位为 word,10 表示40 字节void * const pvParameters, // 调用任务函数时传入的参数UBaseType_t uxPriority, // 优先级TaskHandle_t * const pxCreatedTask ); // 任务句柄, 以后使用它来操作这个任
务
1.创建任务
void vTask1( void *pvParameters )
{const char *pcTaskName = "T1 run\r\n";
volatile uint32_t ul; /* volatile 用来避免被优化掉 */
/* 任务函数的主体一般都是无限循环 */
for( ;; )
{/* 打印任务 1 的信息 */
printf( pcTaskName );
/* 延迟一会(比较简单粗暴) */
for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ )
{}
}
}
void vTask1( void *pvParameters )
{const char *pcTaskName = "T1 run\r\n";
volatile uint32_t ul; /* volatile 用来避免被优化掉 */
/* 任务函数的主体一般都是无限循环 */
for( ;; )
{/* 打印任务 1 的信息 */
printf( pcTaskName );
/* 延迟一会(比较简单粗暴) */
for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ )
{}
}
}
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, // 函数指针, 任务函数const char * const pcName, // 任务的名字const configSTACK_DEPTH_TYPE usStackDepth, // 栈大小,单位为 word,10 表示
40 字节void * const pvParameters, // 调用任务函数时传入的参数UBaseType_t uxPriority, // 优先级TaskHandle_t * const pxCreatedTask ); // 任务句柄, 以后使用它来操作这个任
务
int main( void )
{prvSetupHardware();xTaskCreate(vTask1, "Task 1", 1000, NULL, 1, NULL);
xTaskCreate(vTask2, "Task 2", 1000, NULL, 1, NULL);
/* 启动调度器 */
vTaskStartScheduler();
/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */
return 0;
}
2: 使用任务参数(传递参数)
创建两个任务,但是两个任务调用一个函数,并传入不同参数。
void vTaskFunction( void *pvParameters )
{const char *pcTaskText = pvParameters;
volatile uint32_t ul; /* volatile 用来避免被优化掉 *//* 任务函数的主体一般都是无限循环 */
for( ;; )
{/* 打印任务的信息 */printf(pcTaskText);//pcTaskText来自pvParameters,/* 延迟一会(比较简单粗暴) */for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ ){}
}
}
static const char *pcTextForTask1 = "T1 run\r\n";
static const char *pcTextForTask2 = "T2 run\r\n";
int main( void )
{prvSetupHardware();
xTaskCreate(vTaskFunction, "Task 1", 1000, (void *)pcTextForTask1, 1, NULL);
xTaskCreate(vTaskFunction, "Task 2", 1000, (void *)pcTextForTask2, 1, NULL);
/* 启动调度器 */
vTaskStartScheduler();
/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */
return 0;
}
3. 任务的删除
只需要一个函数就可实现删除任务,可以删除自己也可以删除其他人
void vTaskDelete( TaskHandle_t xTaskToDelete )
void vTask1( void *pvParameters )
{const TickType_t xDelay100ms = pdMS_TO_TICKS( 100UL );
BaseType_t ret;
/* 任务函数的主体一般都是无限循环 */
for( ;; )
{/* 打印任务的信息 */
printf("Task1 is running\r\n");
ret = xTaskCreate( vTask2, "Task 2", 1000, NULL, 2, &xTask2Handle );
if (ret != pdPASS)
printf("Create Task2 Failed\r\n");
// 如果不休眠的话, Idle 任务无法得到执行
// Idel 任务会清理任务 2 使用的内存
// 如果不休眠则 Idle 任务无法执行, 最后内存耗尽
vTaskDelay( xDelay100ms );
}
}
void vTask2( void *pvParameters )
{/* 打印任务的信息 */
printf("Task2 is running and about to delete itself\r\n");
// 可以直接传入参数 NULL, 这里只是为了演示函数用法
vTaskDelete(xTask2Handle);
}
int main( void )
{prvSetupHardware();xTaskCreate(vTask1, "Task 1", 1000, NULL, 1, NULL);
/* 启动调度器 */
vTaskStartScheduler();
/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */
return 0;
}
4: 设置任务优先级
相当于排队,谁排队靠前,谁优先级高
FreeRTOS 会确保最高优先级的、可运行的任务,马上就能执行
对于相同优先级的、可运行的任务,轮流执行
Task3优先级最高,只有它运行 vTaskDelay();休眠函数时其他任务才可以运行;
void vTask1( void *pvParameters )
{/* 任务函数的主体一般都是无限循环 */for( ;; ){/* 打印任务的信息 */printf("T1\r\n"); }
}
void vTask2( void *pvParameters )
{/* 任务函数的主体一般都是无限循环 */for( ;; ){/* 打印任务的信息 */printf("T2\r\n");}
}
void vTask3( void *pvParameters )
{const TickType_t xDelay3000ms = pdMS_TO_TICKS( 3000UL );
/* 任务函数的主体一般都是无限循环 */for( ;; ){/* 打印任务的信息 */printf("T3\r\n");// 如果不休眠的话, 其他任务无法得到执行vTaskDelay( xDelay3000ms );}
}
int main(void)
{prvSetupHardware();
xTaskCreate(vTask1, "Task 1", 1000, NULL, 1, NULL);
xTaskCreate(vTask2, "Task 2", 1000, NULL, 1, NULL);
xTaskCreate(vTask3, "Task 3", 1000, NULL, 2, NULL);
/* 启动调度器 */
vTaskStartScheduler();
/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */
return 0;
}
5. 任务状态(运行和非运行)
5.1.阻塞状态Blocked:
如果优先级高的任务,不进入休眠状态。则其他的低优先级的任务就处于:阻塞状态;
5.2. 暂停状态Suspended:
字面意思就是停下任务,并没有删除,还可以重启;
void vTaskSuspend( TaskHandle_t xTaskToSuspend );
要退出暂停状态,只能由别人来操作:
别的任务调用:vTaskResume
中断程序调用:xTaskResumeFromISR
5.3. 就绪状态Ready:
就是可运行状态。可以通过Delay 函数,决定它什么时候好准备好,直白一点就是延时多久时间可以运行这个函数;
vTaskDelay:至少等待指定个数的 Tick Interrupt 才能变为就绪状态;(就比如单片机的延时函数)
vTaskDelayUntil:等待到指定的绝对时刻,才能变为就绪态。(就比如单片机,自动重装载定时中断)
##if 1
vTaskDelay(xDelay50ms);
##else
vTaskDelayUntil(&xLastWakeTime, xDelay50ms);
##endif
6空闲任务及其钩子函数
钩子函数,把这个宏定义为 1:configUSE_IDLE_HOOK
任务优先级为0,最低优先级,要么有同级任务,轮询执行;要么就,有休眠函数
{
1.vTaskDelay(xDelay50ms);
2.vTaskDelayUntil(&xLastWakeTime, xDelay50ms);
}
或者不运行;
void vApplicationIdleHook(void)
{flagIdleTaskrun = 1;
flagTask1run = 0;
flagTask2run = 0;
flagTask3run = 0;
/* 故意加入打印让 flagIdleTaskrun 变为 1 的时间维持长一点 */
printf("Id\r\n");
}
7.调度算法
(了解就行)
// 实验 1:抢占
##define configUSE_PREEMPTION 1
##define configUSE_TIME_SLICING 1
##define configIDLE_SHOULD_YIELD 1
// 实验 2:不抢占
##define configUSE_PREEMPTION 0
##define configUSE_TIME_SLICING 1
##define configIDLE_SHOULD_YIELD 1
// 实验 1:时间片轮转
##define configUSE_PREEMPTION 1
##define configUSE_TIME_SLICING 1
##define configIDLE_SHOULD_YIELD 1
// 实验 2:时间片不轮转
##define configUSE_PREEMPTION 1
##define configUSE_TIME_SLICING 0
##define configIDLE_SHOULD_YIELD 1// 实验 1:空闲任务让步
##define configUSE_PREEMPTION 1
##define configUSE_TIME_SLICING 1
##define configIDLE_SHOULD_YIELD 1
// 实验 2:空闲任务不让步
##define configUSE_PREEMPTION 1
##define configUSE_TIME_SLICING 1
##define configIDLE_SHOULD_YIELD 0
三,实战代码操作
在这里插入代码片
freertos使用基础相关推荐
- FreeRTOS(基础)
FreeRTOS(基础) 基本概念 ROTS 可剥夺内核 为什么学习FreeRtos FreeRTOS 特点 FreeRTOS 任务状态 FreeRTOS资料与源码下载 FreeRTOS移植 1.添加 ...
- 【STM32】FreeRTOS任务基础
00. 目录 文章目录 00. 目录 01. 概述 02. FreeRTOS任务 03. FreeRTOS协程 04. 任务状态 05. 任务优先级 06. 任务实现 07. 任务控制块 08. 任务 ...
- FreeRTOS任务基础知识
任务特性 在RTOS中,一个实时应用可以作为一个独立的任务,支持抢占,支持优先级,每个任务都有自己的堆栈,当任务切换时将上下文环境保存在堆栈中,再次调用任务时,取出上下文信息,继续运行. 任务优先级 ...
- freertos任务基础知识(freertos篇)
多任务 对于单任务系统就是常说裸机大while循环,有的时候也需要加一些中断服务函数完成一些处理,相比于多任务而言上面的单任务系统也叫做前后台系统,即(中断服务函数叫前台程序,大while叫后台程序) ...
- 无需另配定时器在STM32 HAL下实现微秒级延时(兼容FreeRTOS)
目录 前言 一.代码部分 二.使用和验证 1.引入头文件 2.初始化 3.使用和验证 三.可移植性 总结 前言 接触HAL库差不多两年了,一直苦于HAL库没有自带微秒级的延时,网上的前辈们给出的解决方 ...
- FreeRTOS学习(一)
1 FreeRTOS任务基础 1.1 多任务系统 在51单片机.AVR.STM32裸机编程时,我们通常都是用一个main函数里面加一个while(1)做一个大循环来完成所有的事务处理,同时在加上中断处 ...
- 正点原子FreeRTOS(上)
更多干货推荐可以去牛客网看看,他们现在的IT题库内容很丰富,属于国内做的很好的了,而且是课程+刷题+面经+求职+讨论区分享,一站式求职学习网站,最最最重要的里面的资源全部免费!!!点击进入------ ...
- STM32F4移植FreeRTOS V10.3.1
STM32F429移植FreeRTOS 一.环境 Win ...
- FreeRTOS 任务间通信,怎么实现?
关注.星标公众号,直达精彩内容 素材来源:技术让梦想更伟大 作者:李肖遥 FreeRTOS 是一个可裁剪.可剥夺型的多任务内核,十分好用,而且没有任务数限制,在此之前分析过很多了,简单来说,FreeR ...
最新文章
- 猜拳游戏c语言代码流程图,这是一个猜拳游戏的程序 大家有更好的解决方法么?...
- 怎么向tab control中加其它控件(如文本框等)
- git reset和git revert
- ​NVIDIA针对数据不充分数据集进行生成改进,大幅提高CIFAR-10数据生成
- hdu 1535 spfa
- Unable to find the ncurses libraries的解决办法
- 分布式事务Seata中的三个角色
- vue自定义组件,插槽,自定义事件
- 参数列表和数组的相互转换
- android tcpdump log分析,android 系统启动过程中加入tcpdump和logcat
- #C语言#重定义问题
- RocketMq在windows下安装
- 【原】oracle11g 客户端安装检测失败问题
- 二叉排序树和二叉平衡树
- springboot整合谷歌身份验证
- 目前有哪些好用的测试管理工具?
- php如何去重,php如何去除重复数据
- matlab无限长一维原子链,固体物理 03-03一维双原子链
- Java中的枚举类是什么?enum关键字怎么使用?
- javascript基础:元素增删改操作
热门文章
- 生活小剧场30天吸粉44w,小红书最受欢迎的笔记长这样
- Java 实验8 《抽象类与接口》
- 来了!全球三个首次5G技术实现; 辽宁省完成5G投资36.4亿元; 中兴发布白皮书; 7月国内5G手机出货1391.1万...
- Flutter无限循环滑动的PageView
- pr 调整图层缩放移动无效
- CF 1253D-Harmonious Graph-并查集+贪心
- 微信系多商户商城完整部署步骤
- 情景模拟面试真题解析
- YGG 联合创始人 Gabby Dizon 在 Neckerverse 峰会上分享边玩边赚的故事
- 图论Graph Theory:福尔福特森算法 Ford-Fulkerson