还剩14页未读,继续阅读
本资源只提供10页预览,全部文档请下载后查看!喜欢就下载吧,查找使用更方便
文本内容:
学习笔记FreeRTOS使用注意与相比,需要修改启动文献FreeRTOS ucOS.任务创立1包括〃这个是必须要包括的〃和FreeRTOS.h task.ho调用函数API xTaskCreateportBAS E_TY PExTaskCreate pdTASK^CODE pvTaskCodeconst signed,portCHAR*const pcName,unsignedportSHORT usStackDepth,void*pvParameters,unsigned portBASE_TYPE;uxPriority,xTaskHandle*pxCreatedTask函数指针函数名pvTaskCode描述性任务名,只是用于辅助调试可以通过pcName第行的FreeRTOSConfig.h100来变化描述名长configMAX_TASK_NAME_LEN度任务栈大小提议为的整数倍usStackDepth64任务参数,类型不用写pvParameters void*NULL任务优先级值越大优先级越高同等优先级时,uxPriority按照进行时间片轮转os heart任务句柄变化该任务优先级、删除任务等时才会xTaskHandle用到不用写NULL开始多任务
2.改为才可使用#define configUSE_MUTEXES11void Usart_Funcchar*strifxSemaphoreTakesSem,0==pdTRUEUsartPrintfUSART1,str;vTaskDelay500;UsartPrintfUSART1,0K\r\n:vTaskDelay500;xSemaphoreGivesSem;例程103临界资源104105void USARTl_Taskvoid*pvParameters106El{107while⑴108109110Usart_FuncUsart1Running\r\n;vTaskDelay10:111112113114115void USART2_Taskvoid*pvParameters116117118while⑴119120Usart_FuncUsart2Running\r\n;121vTaskDelay10;1221231241251on先调用函数,里边先获取互斥量,然后USARTl_Task Usart.Func打印一句,积极放弃控制权,此时该运行不过它获取cpu USART2_Task,不到互斥量,阻塞,然后再执行部分,执行完毕,互斥USARTl_Task give量,此时即可打印出来USART2_Task例程2void LEDl_Taskvoid*pvParameterswhile10{ifxSemaphoreTakesSem,1==pdTRUE0{Led_Blue_SetLED.ON;vlaskDelay500:Led_Blue_SetLED.OFF;vlaskDelay500:Led_Blue_SetLED.ON;vlaskDelay500:Led_Blue_SetLED.OFF;vlaskDelay500:xSemaphoreGivesSem;vlaskDelay1:132void LEDTaskvoid*pvParameters133早{134while11350{136137ifxSemaphoreTakesSem,1=={pdTRUE138El Led_Yellow_SetLED.ON;vlaskDelayf1000;139Led_Yellow_SetLED_OFF:140vTaskDelay1000:141142Led.Yellow.SetLED.ON:143vlaskDelayf1000:144Led_Yellow_SetLED.OFF;145vlaskDelay1000:146xSemaphoreGivesSem:147148149vTaskDelay⑴150151152153154}.事件标志组12-Event_Groups包括#include,,event_groups.hN申明〃事件标志组句柄仓立EventGroupHandle_t eEvent;eEvent=xEventGroupCreatef;设置〃设置标志xEventGroupSetBitseEvent,0x01;等待getBits=xEventGroupWaitBitseEvent,0x01,pdTRUE,pdTRUE,1;〃句柄-等待标志-完毕后与否清零标志-与否等待所有标志-超时时间ifgetBits0x01==0x01//...}vTaskDelaylO;册除U vEventGroupDeleteeEvent;例程81void EVENT1_Taskvoid*pvParameters820{8384EventBits_t getBits=0;88858986while19087S{getBits=xEventGroupWaitBitseEvent,0x09,pdTRUE,pdTRUE,1;91{92□t93if getBits0x09==0x099495UsartPrintfUSART1,Bit1and BitSXrXn^;96Lcdl602_Clear0x80;97Lcdl602_DisString0x80,Bit1and Bit398}99100vTaskDelay10:101//〃等待两个事件中任意一个102//getBits=xEventGroupWaitBitseEvent,0x09,pdTRUE,pdFALSE,1;103//104//if getBits0x09105//{106//UsartPrintfUSART1,Bit1and Bit3\r\nw;107//}vTaskDelay10;114void EVENT2_Taskvoid*pvParameters1150{-116117EventBits_t getBits=0;118119while1120E121122getBits=xEventGroupWaitBitseEvent,0x02,pdTRUE,pdTRUE,1:〃句柄-等待标志-完成后是否清零标志-是否等待所有标志-超时时间123124ifgetBits0x02==0x02125□UsartPrintfUSART1,wBit2\r\n*;126Lcdl602_Clear0x80;127Lcdl602ZDisString0x80,;128}129130vTaskDelay10:131132133134135137void KEY_Taskvoid*pvParameters138139portlickType uLastTickCount=xlaskGetTickCount;140141while⑴142143switch Keyboard144145114468149case KEYODOWN:150151xEventGroupSetBits eEvent,0x01:〃设置标志break;152153case KEY1DOWN:154155xEventGroupSetBits eEvent,0x02;〃设置标志break;156157case KEY2D0W:158159xEventGroupSetBits eEvent,0x08;〃设置标志break;160161162163164165vTAvTTnt.i1fr.uT.A^t.Ti rkCnunt..2D•1661671RR假如是等待和、时一定要判断bitl bit3,pdTRUE pdTRUE先发生事件,就会一直ifgetBits0x09==0x09,Bitl getBits为然后发生事件,才会触发然后标志组内部吧对应事0x01,Bit3件清零;、时,发生任意一种事件后,触发然后标志组内pdTRUE pdFALSE部吧事件清零.软件定期器13包括#include timers.h申明TimerHandle_t tl_Thdl,t2_Thdl,t3_Thdl;创立tl_Thdl=xTimerCreateTimerl,200,pdTRUE,void*1,TimerCallbackFunction_tTimer_Callback;参数定期器名,调试用到1参数定期周期2参数周期定期器;单次定期器3pdTRUE-pdFALSE-参数容许多种定期器回调同一种函数,通过辨别4TimerlDo ID参数回调函数地址5启停句柄、等待时间xTimerStarttl_Thdl,1;xTimerStoptl_Thdl,1;复位xTimerResettl_Thdl,1;重新计算定时周期到达的时间点,这个新的时间点是相对于复位定时器的那个时刻计算的,并不是第一次启动软件定时器的那个时间点图演示J这个过程,Timcrl是单次定时器,定时周期是5s Timerl运行停止前一秒按键又被按下,Timerl复面\因此前面计算的在第6s就要调用的回调函数也不会执\行了旦位以后Timerl重新计算出在系统运行到第10s的时候Timerl停止运行,也就是夏位后的第5s系统运行1s后,按键被按下以》\背光打开,Time门开始运行,Timer1计算出系统运行到第6s时定时停止,Timer2定时周期为200,定区器也就是定时器运行5s后停止时间到.调用回调函数但是Timer2是周期定时器,所以回调函数会周期性执行LCD背光关闭,1\Timerl停止运行Timer1Os Is2s3s4s5s6s7s8s9s10s Ils12s时间.内存管理14为了减少内存碎片的产生提供了一套内存分派与释放的FreeRTOS措施分派void*pvPortMallocsize_t xWantedSize释放void vPortFreevoid*pv使用措施同库的和C mallocfree库的内存分派方案的弊端c使用动态内存管理的时候FreeRTOS内核在创建任务、队列、信号量的时候会动态的申请RAM标准C库中的maHoc和斤”还是也可以实现动态内存管理,但是如下原因限制了其使用
1、在小型的嵌入式系统中其并不总是有效的
2、会占用很多的代码空间
3、它们不是线程安全的
4、具有不确定性,每次执行的时间不同
5、会导致内存碎片
6、使链接器的配置变得复杂不同的嵌入式系统对于内存分配和时间要求不同,因此一个内存分配算法可能仅作为一个应用的;集所以FreeRTOS将内存分配作为移植层的一部分,这样FreeRTOS使用者就可以使用自己的合适的内存分配方法vTaskStartSchedulerf怎样多任务切换
3.调用函数API vTaskDelayunsignedint time为多少个Time oshearto.时间片轮转例子4创立两个任务xTaskCreateUSARTl_Task,^SARTl11,256,void*strl,3,NULL;xTaskCreateUSART2_Task,“USART2256,void*str2,3,NULL;相似优先级,波特率可以设置低某些ardware_Ini tOKTThhiiss iissT aTsalds,k工2」工m mRRuxmmmiinng!g!!!!!!!!!!!!!!!Thi sThi sisT asiks2,工Ta/ns Rkulibniln gjn!!!R!xm!n!i!ng!!!!!!!!!Thi si sThilsa issk2Ta^slk1,ml RmuRnuninnngi!!n!g!!!!!!!!!IIII然后就会看到这就是时间片轮转系统心跳频率
5.在第行的源码使用FreeRTOSConfig.h97configTICK_RATE_HZ,就是假如为就是1000HZ,1ms,200200HZ,5ms有关宏portTICK_RATE_MSo
6.vTaskDelayllntil和不一样,这个函数不包括函数运行时间,而vTaskDelay包括vTaskDelayllntil例如,一种函数执行时间为A2ms,使用则再次执行这个函数至少需要等待vTaskDelaylO,12ms使用则这包括在内,以固定周期运vTaskDelayUntillO,2ms A10ms行void SENSOR_Taskvoid*pvParameters3{portTickType xLastWakeTime=xTaskGetlickCount;while1ADXL345_GetValue:Lcdl602_DisString0x80,X%
0.lf,Y%
0.If,Z%
0.lf\adGY30_GetValue:Lcdl602_DisStringOxCC,飞dLX”,gy30Info.lightVal;SHT20_GetValue:Lcdl602_DisStringOxCO,%
0.lfC,%
0.sht20Inf//vTaskDelay100;vT askDe1ayUnt i1xLastWakeTimeX100;使用措施:红圈的地方就是固定心跳周期空闲任务钩子函数
7.void vApplicationldleHookvoid需使能中第行的FreeRTOSConfig.h126configUSEJDLE_HOOKo消息队列一
8.Queue包括:#include,queue.h申明QueueHandle_t qMsg;创立个队列,每个队列个组员qMsg=xQueueCreate4,2;//42发送〃最终是超时时间xQueueSendToFrontqMsg,Value〃最终是超时时xQueueSendToBackqMsg,Value,1间〃最终是超时时间xQueueSendjqMsg,Value成功返回;失败返回pdPASS errQUEUE_FULLo注中断中的就是在函数名字后加上〃FromlSR接受xQueueReceiveqMsg,value,1〃不会删除读取的数据xQueuePeekqMsg,value,1成功返回;失败返回pdPASS errQUEUE_EMPTY注中断中的就是在函数名字后加上〃FromlSR删除vQueueDeleteqMsg;查询队列未读数据个数unsigned portBASE_TYPE count=0;count=uxQueueMessagesWaitingqMsg;例程:188void SENDl_Taskvoid*pvParameters{一189E190unsigned shortvalue=0;191192while1{193194Q switch Keyboard{case KEYODOWN:195275void REV_Taskvoid*pvParameters196197申276S{198199value=500:1==pdPASS〃发送成功200ifxQueueSend!oBacks1_Qhdl,lvalue,201〃e rrQUEUE_FULL队■202203break:204case KEY1DOWN:205value=600;206ifxQueueS end!oBacks1_Qhdl,lvalue,1==pdPASS〃发送成功907//oK^nTTPTTPTniTTlU石II条277278unsigned shortsiValue=0;279unsigned chars2Value
[4]={0,0,0,0};280while1281{282283〃调用xQueuePeek不会删除已读消息284//调用xQueueRe ce ive会删除已读消息285〃参数一致286287ifxQueueReceivesl_Qhdl,slValue,1{-==pdTRUE288UsartPrintfUSART.DEBUG,Queue1:289%d\r\n,siValue;290按键发送队列消息,接受任务接受到就显示按键是两个,这里没有截出来二值信号量
9.二值信号量可以在某个特殊的中断发生时,让任务解除阻塞,相当于让任务与中断同步这样就可以让中断事件处理量大的工作在同步任务中完成,上断服务例程中只是快速处IS理少郁份工作如此,中断处理可以说是被“推迟到一个处理任务deferred”handler”如果某个中断处理要求特别紧急,其延迟处理任务的优先级可以设为最高,以保证延迟处理任务随时都抢占系统中的其它任务这样,延迟处理任务就成为其对应的退出后第ISR一个执行的任务,在时间上紧接着执行,相当于所有的处理都在中完成一样这种ISR ISR方案在图中展现26包括:#include,,semphr.hn申明SemaphoreHandle_t sSem;仓立;//仓立二值信号量推ll sSem=xSemaphoreCreateBinary Li荐〃创立二值信号量vSemaphoreCreateBinarysSem;Give portBASE_TYPE xHigherPriorityTaskWoken=pdFALSE;xSemaphoreGiveFromlSRsSem,xHigherPriorityTaskWoken;ifxHigherPriorityTaskWoken==pdTRUE9-—中断措施xSemaphoreGivesSem;-—一般措施Take portBASE_TYPE xHigherPriorityTaskWoken=pdFALSE;xSemaphoreGiveFromlSRsSem,xHigherPriorityTaskWoken;■ifxHigherPriorityTaskWoken==pdTRUE---中断措施ifxSemaphoreTakesSem,1==pdTRUE-—一般措施删除vSemaphoreDeletesSem;例程ay y106void LCD_Taskvoid*pvParameters1070{-108109unsigned charcount=0;110111while1112B113114if xSemaphoreTakesSem,1==pdTRUE//如果take到二值信号里一在中断里give二值信号了115Lcdl602_DisString0x80,Timer:%d,count++;116117118119♦—extern xSemaphoreHandlesSem;void TIM7_IRQHandlervoid|El{portBASE_TfFE xHigherPriorityTaskWoken=pdFALSE;ifTIM.GetITStatusTIM7,TIM_IT_Update==SET0{TIM ClearlTPendingBitTIM7,TIM ITUpdate;xSemaphoreGiveFromlSR sSem,xHigherPriorityTaskWoken:二值信后里if xHigherPrioritylaskWoken==pdTRUE//如果take的任务不在运行态则S星制切换任务://portSWITCH_CONTEXT:〃这里应该加入手动切换任务,但是我没找到方法!!!!!!!!!!每隔一次任务循环Timer73sGive BinarySema,LCD Take这是中断延迟处理的例子BinarySema,,计数信号量10在图中可以看到,一个二值信号量最多只可以锁存一个中断事件在锁存的事件还未被处30理之前,如果还有中断事件发生,那么后续发生的巧断事件将会丢失如果.计数信号量代替二值信号量,那么,这种丢中断的情形将可避免一G就如同我们可以把二值信号量看作是只有一个数据单元的队列一样,计数信号量可以看作是深度大于的队列任务其实对队列中存储的具体数据并不感兴趣——其只关心队列是空还是非1空包括#include,,semphr.hH申明SemaphoreHandle_t sSem;创立:sSem=xSemaphoreCreateCounting10,0;注其他措施完全同样,只是创立是不一样的第一种参数计数容量第二个参数初值需要在中第行的FreeRTOS.h252改为才可使#define configUSE_COUNTING_SEMAPHORES01用void KEY_Taskvoid*pvParametersportTickType uLastTickCount=xTaskGetTickCount;_Bool flag=1;while1switchKeyboard例程case KEYODO W://timer give出semaCount,这里则试停止timer,blue led还会不会闪if flagLcdl602_DisString0x80,Timer StopTIM.CmdaiM,DISABLE;}_else{Lcdl602_DisString0x80,Timer StartTIM.CmdaiMT,ENABLE;}_flag=!flag;break;void LCD_Taskvoid♦pvParameters早{while1〃专门用独占cpu延时的方式,就是为了timer7能及时give出semaCount,这里好获取if xSemaphoreTakesSem,1==pdTRUE〃如果take到二值信号里一在timer7中斯里give计数信号了Led_Blue_SetLED.ON:DelayXms7500;143Led_Blue_SetLED_OFF;144DelayXms500;145146147vTaskDelay50;〃必要的timer Is一次,这个函数会花费2s,所以一直都会take到,加个这个,可以切到key任务148149}150151152IRQdefault:119extern xSemaphoreHandlesSem;120void TIM7_IRQHandlervoid121□{122123portBASE_TYPE xHigherPriorityTaskWoken=pdFALSE;3456789012124125ifTIM_GetITStatusTIM7,TIM_IT_Update==SET1260{127TIM.ClearlTPendingBitTIM7,TIM_IT_Update:128_129xSemaphoreGiveFromlSR sSem,xHigherPriorityTaskWoken//give二值信号里130if xHigherPrioritylaskWoken==pdTRUE〃如果take的任务不在运行态则强制切换任务131;//portSWITCH_CONTEXT:〃这里应该加入手动切换任务,但是我没找到方法!!!!!!!!!!132133134135按键控制启停,干的事情就是每隔去一Timer7Timer
0.5s Give种任务就是到执行一CountingSema,LED TakeCountingSema,次动作当停止时,任务会吧LED Timer7LED CountingSema到为为止Take0互斥信号量1L且斥量是一种特殊的二值信号量,用于控制在两个或多个任务间访问共享资源单词(互斥量)源于“于MUTEX MUTuExclusion\在用于互斥的场合,互斥量从概念上可看作是与共享资源关联的令牌一个任务想要合法地访问资源,其必须先成功地得到()该资源对应的令牌(成为令牌持有者)当令Take牌持有者完成资源使用,其必须马上归还()令牌只有归还了令牌,其它任务才可能Give成功持有,也才可能安全地访问该共享资源一个任务除非持有了令牌,否则不允许访问共享资源这种机制在图中展示36虽然互斥量与二值信号量之间具有很多相同的特性,但图展示的情形(互斥量用于36互斥功能)完全不同于图展示的情形(二值信号量用于同步)两者间最大的区别在于30信号量在被获得之后所发生的事情包括#include,,semphr.hH申明SemaphoreHandle_t sSem;仓立;//仓立互斥信号量sSem=xSemaphoreCreateMutex II注其他措施完全同样,只是创立是不一样的需要在中第行的FreeRTOS.h244。
个人认证
优秀文档
获得点赞 0