史上最全的FreeRTOS资料Word格式文档下载.docx
- 文档编号:22866594
- 上传时间:2023-02-05
- 格式:DOCX
- 页数:125
- 大小:286.55KB
史上最全的FreeRTOS资料Word格式文档下载.docx
《史上最全的FreeRTOS资料Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《史上最全的FreeRTOS资料Word格式文档下载.docx(125页珍藏版)》请在冰豆网上搜索。
4.利用限制
减少RAM占用率的代价确实是利用联合程序上有严格限制。
联合程序综述
在联合程序之间共享堆栈将占用少得多的RAM。
联合操作使得重入不再是问题。
非常容易移植的架构。
相对其他联合程序有完全的优先级关系,但是可以被任务占先如果混合使用的时候。
需要仔细考虑堆栈。
API调用时有限制。
只能在联合程序之间使用联合操作。
任务
任务状态
一个任务能够是以下几种状态中的一种:
∙运行
正在执行的任务确实是处于运行状态,它占用了处置器。
∙就绪
就绪的任务是那些能够执行(没有被阻塞或暂停),可是因为其他相同或更高优先级任务正在运行造成尚未运行的任务。
∙阻塞
当一个任务等待临时事件或外部事件时它确实是处于阻塞状态。
例如,任务挪用vTaskDelay(),它将被阻塞(置为阻塞状态)直到超过延不时刻-一个临时事件。
任务也能够阻塞等待队列和信号事件。
阻塞状态的任务一样有一个超不时刻,超时后任务将解锁。
阻塞的任务可不能参与调度。
∙暂停(挂起)
暂停状态的任务也不参与调度。
任务只有在挪用API函数vTaskSuspend()和xTaskResume()时才会进入或退出暂停状态。
它不能指定超不时刻。
有效的任务状态转换
任务优先级
每一个任务将分派一个从0到(configMAX_PRIORITIES-1)的优先级。
configMAX_PRIORITIES在文件中概念,configMAX_PRIORITIES参数值越大,FreeRTOS占用的RAM就越多。
低优先级任务利用较小的数字,缺省的空闲优先级tskIDLE_PRIORITY概念为0。
调度器保证处于就绪或运行状态的任务分派处处置器时刻,高优先级任务先分派。
换句话说,处置器时刻老是分派给能够运行的最高优先级任务。
执行任务
一个任务有下面的结构形式:
voidvATaskFunction(void*pvParameters)
{
for(;
;
)
--Taskapplicationcodehere.--
}
类型pdTASK_CODE概念为返回值是void的函数,并利用void指针作为唯一的参数。
所有的任务函数都是那个类型,能够传递任意类型的参数到任务-在中进行了演示。
任务函数应当从不返回,因此它通常执行一个持续的循环,参考RTOS的例子。
任务由函数xTaskCreate()创建,利用vTaskDelete()删除。
创建任务TaskCreationMacros
能够利用portTASK_FUNCTION和portTASK_FUNCTION_PROTO宏概念任务函数。
这些宏许诺编译器别离添加特定语法到函数概念和声明。
这些只有在移植时利用特点声明时利用(目前只在PIC18fedC)。
上面函数声明能够写为下面形式:
voidvATaskFunction(void*pvParameters);
或,
portTASK_FUNCTION_PROTO(vATaskFunction,pvParameters);
一样上面的函数能够写为:
portTASK_FUNCTION(vATaskFunction,pvParameters)
空闲任务
空闲任务在调度器启动时自动创建。
空闲任务负责清理已删除的任务利用的内存,因此挪用vTaskDelete()函数来保证空闲任务分派处处置时刻。
此刻能够利用可视化工具检查微操纵器分派给空闲任务的时刻。
当空闲任务没有利用其他函数,如此在其他任何条件下能够不分派处处置器时刻。
系统其他任务能够共享空闲任务的优先级(tskIDLE_PRIORITY).
空闲任务钩子
一个空闲任务钩子确实是在每次空闲任务运行时挪用的函数。
若是你希望一个函数以空闲任务优先级运行,有两个方式:
1.在空闲任务钩子实现。
必需始终有一个任务预备好运行,在钩子函数中不能挪用任何可能引发任务阻塞的API函数(例如vTaskDelay(),它许诺联合程序阻塞钩子函数)。
2.创建空闲优先级任务执行的功能。
这是更灵活的方式可是需要更多的RAM。
更多内容参考末节中利用空闲钩子部份。
创建空闲钩子:
1.在中设置configUSE_IDLE_HOOK为1。
2.概念下面类型的函数:
voidvApplicationIdleHook(void);
通常利用空闲钩子的用法确实是简单的将处置器进入节能模式。
联合程序[]
Co-RoutineStates
一个联合程序能够以下面的状态中的一种存在:
当一个联合程序正在执行时它确实是处于运行状态,它就占用了处置器。
就绪状态的联合程序是那些能够执行(没有被阻塞)可是尚未被执行的程序。
一个联合程序可能处于就绪状态是因为:
1.另外一个相同或高优先级的联合程序正处于运行状态,或
2.一个任务处于运行状态-这只会在系统同时利用了任务和联合程序时发生。
若是一个联合程序正处于临时等待或等待外部事件,它确实是处于阻塞状态。
例如,联合程序挪用crDELAY()它就会被阻塞(放入到阻塞状态)直抵达到延不时刻-一个临时事件。
被阻塞的联合程序可不能被调度。
目前没有联合程序等价于任务的暂停状态,那个特点将在以后的版本中加入。
有效的联合程序状态转换
联合程序属性
每一个联合程序被分派一个从0到(configMAX_CO_ROUTINE_PRIORITIES-1)的优先级。
configMAX_CO_ROUTINE_PRIORITIES在中概念并在大体系统中设置。
configMAX_CO_ROUTINE_PRIORITIES的数值越大FreeRTOS消耗的RAM越多。
低优先级联合程序利用小数值。
联合程序优先级只针对其他联合程序,任务的优先级老是高于联合程序。
执行联合程序
联合程序利用下面的结构:
voidvACoRoutineFunction(xCoRoutineHandlexHandle,unsignedportBASE_TYPEuxIndex)
crSTART(xHandle);
--Co-routineapplicationcodehere.--
crEND();
类型crCOROUTINE_CODE概念为返回值为void的函数,利用xCoRoutineHandle和一个索引值作为参数。
所有执行一个联合程序的函数都是那个类型(如上面所示)。
挪用xCoRoutineCreate()创建联合程序。
要点说明:
∙所有联合程序函数必需以挪用crSTART()开始。
∙因此联合程序函数必需以挪用crEND()终止。
∙联合程序函数从不返回,一般是执行一个不断的循环。
∙许多联合程序能够从一个单一联合程序函数创建。
uxIndex参数提供区分这些联合函数的方式下面给出一个例子。
调度联合程序
联合程序由反复挪用vCoRoutineSchedule()进行调度,挪用vCoRoutineSchedule()的最正确位置是在空闲任务钩子中。
这是因为即便你的系统只利用联合程序,当调度开始后仍将自动创建空闲任务。
参考下面的例子。
混合任务和联合程序
从空闲任务调度联合程序就很容易在同一个系统中混合利用任务和联合程序。
如此只有在没有比空闲任务优先级更高的任务运行时联合程序才会执行,查看下面的例子。
另外ARMCortex-M3和PC演例如子中演示了那个方式。
限制和约束
联合程序和任务相较来讲,优势是RAM占用率更低,可是联合程序相较任务来讲加倍复杂和有更多限制。
∙共享堆栈
当联合程序阻塞时,它的堆栈再也不继续维持。
这意味着变量的数值极可能会丢失。
为了解决那个问题,一个需要维持参数的变量必需声明为静态变量,例如:
staticcharc='
a'
.
c='
b'
.thenmakeablockingcall...
crDELAY(xHandle,10);
.cwillonlybeguaranteedtostill
共享堆栈的另外一个后果是挪用API函数引发联合程序阻塞只可能是联合程序本身-而不是从联合程序中挪用函数。
例如:
vACalledFunction();
voidvACalledFunction(void)
快速例子
那个快速例子演示了联合程序的利用。
1.创建一个简单的联合程序闪动一个LED
下面代码概念了一个简单的联合程序,除周期性改变LED外什么也不做。
voidvFlashCoRoutine(xCoRoutineHandlexHandle,unsignedportBASE_TYPEuxIndex)
vParTestToggleLED(0);
确实是如此!
2.调度联合程序
联合程序由反复挪用vCoRoutineSchedule()进行调度。
最正确的位置是在空闲任务中放置空闲任务钩子。
第一保证中的宏configUSE_IDLE_HOOK设置为1,然后在空闲任务钩子中写入:
voidvApplicationIdleHook(void)
vCoRoutineSchedule(void);
或,若是空闲任务没有执行其他任何函数,更有效率的做法是在循环中挪用vCoRoutineSchedule():
3.创建联合程序并启动调度
联合程序能够在main()中创建:
#include"
"
#definePRIORITY_00
voidmain(void)
xCoRoutineCreate(vFlashCoRoutine,PRIORITY_0,0);
vTaskStartScheduler();
4.扩展例子:
利用索引参数
此刻假定咱们希望从同一个函数中创建8个如此的联合程序。
每一个联合程序将以不同速度闪动一个不同的LED。
索引参数能够用于在联合程序之间进行区分。
这次咱们将创建8个联合程序并给每一个指定不同的索引值。
#defineNUM_COROUTINES8
inti;
for(i=0;
i<
NUM_COROUTINES;
i++)
xCoRoutineCreate(vFlashCoRoutine,PRIORITY_0,i);
同时扩展联合程序函数,使得每一个利用不同的速度显示LED。
constintiFlashRates[NUM_COROUTINES]={10,20,30,40,50,60,70,80};
constintiLEDToFlash[NUM_COROUTINES]={0,1,2,3,4,5,6,7}
uxIndexisusedtoindexinto
Aseachco-routinewascreatedwith
crDELAY(xHandle,iFlashRate[uxIndex]);
AgainuxIndexisusedasanarrayindex,
vParTestToggleLED(iLEDToFlash[uxIndex]);
例子演示程序
下载的演示程序中包括两个利用联合程序的文件:
1.
那个文件功能上等同于标准的演示文件,可是利用了联合程序取代了任务。
另外,因为只是为了用于演示目的,没有在联合程序中直接改变LED(犹如上面的快速例子那样),需要改变LED的数量放入到高优先级的联合程序队列中。
2.
演示了从中断到联合程序互换数据。
利用一个节拍钩子函数作为数据源。
PC和ARMCortex-M3的演示程序已经预先配置好利用这些相同的联合程序文件,能够作为参考。
其他的演示程序只利用了任务,可是能够很容易的依照下面步骤转换为联合程序。
主若是利用替换:
1.在中设置configUSE_CO_ROUTINES和configUSE_IDLE_HOOK为1.
2.在IDE项目或项目的makefile(与利用的演示程序有关):
i.替换文件FreeRTOS/Demo/Common/Minimal/为FreeRTOS/Demo/Common/Minimal/.
ii.添加文件FreeRTOS/Source/.
3.在:
i.包括头文件,它概念了联合程序的宏和函数声明。
ii.替换包括的头文件为.
iii.删除创建flash任务的函数挪用vStartLEDFlashTasks()....
iv....并替换为创建flash联合程序vStartFlashCoRoutines(n),那个地址n是需要创建联合程序的数量。
每一个联合程序以不同的速度操纵一个不同的LED。
v.添加空闲钩子函数调度联合程序:
vi.voidvApplicationIdleHook(void)
vii.{
viii.vCoRoutineSchedule(void);
ix.}
若是main()已经包括了一个空闲钩子,那么简单的添加vCoRoutineSchedule()函数挪用即可。
4.用flash联合程序替换flash任务意味着至少减少分派了两个堆栈和更少用于调度器的堆空间。
若是你的项目的RAM不足以包括那么在中减少portTOTAL_HEAP_SPACE为(2*portMINIMAL_STACK_SIZE).
任务间通信Inter-taskCommunication
[]
提供:
∙
∙,和更多
队列
队列是内部通信的要紧形式。
它能够用于在任务和任务之间和任务和中断之间发送消息。
在大多数情形下利用线程平安FIFO(先进先出)缓存,新数据放在队列的最后,尽管数据也能够放在前面。
队列能够包括固定大小的'
项目'
-每一个项目的大小和队列能够保留项目的最大数量在创建队列时就已经概念了。
项目以复制而不是引用的方式放入队列,因此最好使放入队列项目的大小成为最小。
以复制的方式放入队列能够使你的系统设计极大的简化,因为两个任务可不能同时访问数据。
队列帮忙你治理所有的互斥问题。
若是你希望在队列中利用大的项目,可能最好用插入队列指针-可是如此做必需注意要确保你的系统明肯概念任务和/或中断是数据的"
因此者"
。
队列API函数能够指定阻塞的时刻。
阻塞时刻代表任务进入阻塞状态或等待队列中数据时(当任务读取队列可是队列是空的时候)的最大'
节拍'
数,或等待队列空间变成能够利用(当任务需要写数据到队列,可是队列已满时)。
当一个以上任务在同一个队列中被阻塞时,高优先级的任务先解除阻塞。
查看用户文档中末节中与队列相关的API函数列表。
搜索FreeRTOS/Demo/Common/Minimal文件夹下的文件能够发觉多个这种用法的例子。
注意中断里不能利用不是用"
FromISR"
终止的API函数。
写入和读取队列。
在那个例子中队列保留5个项目,而且从不变满。
二进制信号灯
二进制信号灯同时用于互斥和同步的目的。
二进制信号灯和互斥超级相似,可是有一些细微的不同:
互斥包括优先级继承机制,而二级制信号没有。
这使得二进制信号灯用于同步更方便(在任务之间或任务与中断之间),而互斥用在简单的相互排斥更好。
在如何用互斥作为相互排斥的机制中二进制信号灯用法,那个子章节只说明利用二进制信号灯进行同步。
信号灯API函数能够指定阻塞的时刻。
阻塞时刻代表任务因为等待获取信号灯而进入阻塞状态的最大'
数。
若是超过一个以上的任务因为同一个信号灯被阻塞,那么在信号灯能够利历时高优先级的任务先解除阻塞。
将一个二进制信号灯看做为队列,它只能保留一个项目,那个队列只能是空的或是满的(二进制)。
利用队列的任务和中断不关切队列保留了什么-它们只关系队列是空的仍是满的。
那个机制能够用于同步任务和中断。
考虑如此一个情形,任务利用一个外设,轮询外设将浪费CPU资源,并阻止了其他任务的运行。
因此最好是任务将大部份时刻用于阻塞状态(许诺其他任务运行),只有真正需要操作时才去轮询。
这确实是在'
试图'
取得信号时利用二进制信号灯进行任务阻塞,而一个中断效劳程序用于外设,当需要利用外设时'
给出'
信号。
任务老是'
获取'
信号(从队列读取直到队列为空),可是从不'
中断效劳程序老是'
信号(写入队列直到队列变满)而从不获取。
源代码的文档中清楚的说明了那个方式。
能够利用任务的优先级保证及时的外设效劳-有效的产生'
不同的中断'
方式。
另外一种方式是利用队列代替信号,在中断效劳程序中捕捉外设的数据并通过队列发送给任务。
当队列的数据能够利用后任务解除阻塞,从队列读取数据后,进行数据处置。
第二种方式许诺中断程序尽可能的短,通过post处置而不是发生在一个任务中。
参考用户文档的末节中关于信号灯的API函数。
搜索FreeRTOS/Demo/Common/Minimal文件夹下的文件能够取得很多这种用法的例子。
注意中断里不能利用不是以"
利用信号灯同步任务和中断。
中断只'
信号,而任务只'
计数信号灯
正如二进制信号灯能够以为长度是1的队列,计数信号灯能够看成是长度大于1的队列。
一样,用户的信号不是对队列数据的数值感爱好-只需要看队列是不是空的。
计数信号灯典型用于两个方面:
1.计数事件。
在那个情形下利用一个事件处置程序将在每次事件发生时'
信号(增加信号计数值),同时每次处置事件时处置任务将'
取得'
信号(减少信号计数值)。
因此计数值是事件发生次数和处置次数的差,信号创建时,那个计数值是0。
2.资源治理。
在那个情形下,计数值代表可用的资源数。
为了取得一个资源的操纵,任务必需先取得信号-减少信号的计数值。
当计数值达到0,代表没有剩余的自由资源。
当任务利用完资源后,需要'
返还'
信号-增加信号计数值。
在这种方式下信号创建时的计数值等于最大计数值。
参考末节查看相关的API函数。
搜索FreeRTOS/Demo/Common/Minimal文件夹下的文件能够查看关于这种用法的例子。
注意中断里不能利用不以"
互斥
互斥是包括优先级继承机制的。
关于同步(在任务之间或任务与中断之间)来讲二进制信号灯是更好的选择,互斥关于简单的相互排斥更方便(mutex确实是'
MUT'
ual'
EX'
clusion).
当用于相互排斥时,互斥就像是资
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 史上最全 FreeRTOS 资料