freertos入门分享

FreeRTOS提供的功能包括:任务管理、时间管理、信号量、消息队列、内存管理。与平台有关的文件包含在portable文件夹中,主要是port.c, portmacro.h两个文件。平台无关的文件主要是:list.c(基本链表结构), queue.c(包括消息队列,信号量的实现), croutine.c,tasks.c(任务管理,时间管理)。可以参考http://blog.csdn.net/augusdi/article/details/9947547 对freertos有一个初步认识。下面就几个常用的“知识点”跟大家进行交流分享。

(1)任务管理

知识点1:任务函数xtaskcreate(函数名,任务名((const char *)"example_demo"),栈空间大小,传入任务函数的parma,任务句柄(使用改变任务函数优先级或者删除,Vtaskdelete(null)表示删除自己));

知识点2:任务只要四种状态:

阻塞态: block或者unblock的状态,等待某个事件发生,(一般是定时或者同步事件)

挂起态: 也就是vTaskSuspend() 、vTaskResume()/vTaskResumeFromISR()切换;

就绪态: 等待被执行

running态: 运行起来了

知识点3:在多任务管理机制上,操作系统可以分为抢占式和协作式两种。协作式操作系统是任务主动释放CPU后,切换到下一个任务。任务切换的时机完全取决于正在运行的任务。

知识点4:taskYIELD() 当同优先级的多个任务存在时,每个task都是不会睡眠的不停的执行自己,当每个task觉得自己占用cpu的时间已经差不多的时候,就会调用taskYIELD(),主动让出cpu,让同优先级的其他task获得cpu,因为没有其他优先级的task,所以调度器不会切换优先级,而是采用轮转调度策略,运行同优先级的就绪运行队列链表中调用taskYIELD()函数的当前task的下一个task.

taskYIELD()调用也是主动放弃剩余时间片,放弃对cpu的占用。

(2)队列管理

xQueue= xQueueCreate(5(队列深度),sizeof(long)(数据单元长度));

队列举例,dueros会根据不同场景播放不同的数据,在之前存储播放条件时,可以将播放条件按照1,2,3....进行排放,将事件标号send到队列中,等最后主要播放时,xQueueReceive一直等待有数据压入队列后,再进行播放。

int message;

tone_queue = xQueueCreate(5, sizeof(int));

if (pdTRUE == xQueueReceive(tone_queue, &message,portMAX_DELAY)) {

}else{

printf("Queue receive failed!");

}

int msg = (int)tone;

if(pdPASS != xQueueSend(tone_queue, &msg, 0)){

DUER_LOGE("Could not send to tone queue");

}

 

(3)信号量

信号量的使用和等待拿货一个道理,while(xSemaphoreTake(sem,portMAX_DELAY) != pdTRUE) {

printf("[%s] , (%p) failed, retry\n",pcTaskGetTaskName(NULL), sem);

}

货到了就可以直接走了,但是如果等待的时间portMAX_DELAY太久了,失去耐性就走了;xSemaphoreTake不能在 ISR 中调用,因为 ISR 不能调用可能导致阻塞的函数

xSemaphoreGive(sem);就是给你的货到了,你可以拿货走人;

信号量分为二值信号量(同步信号量)和计数信号量;二值信号量,相当于只有 1 个数据单元的队列。一个二值信号量最多只可以锁存一个中断事件:在锁存的事件还未被处理之前,如果还有中断事件发生,后续发生的中断事件将会丢失。计数信号量,可以看作深度大于 1 的队列;二值信号量,相当于只有 1 个数据单元的队列。

计数信号量可以理解为有几车货物,在gpio_sema =xSemaphoreCreateCounting(300(最大计数为300), 0(从0开始计数)); ,也就是说要申请一个可以容纳300-0=300的货仓去拿货;二值信号量vSemaphoreCreateBinary(sema)申请去个只有一车的小货仓去拿货即可。可以参考:https://www.cnblogs.com/yangguang-it/p/7211598.html

任务获取“二值信号量”后不再归还,区别于“互斥量”。互斥量平时我们所说的加锁,一种特殊的二值信号量,实际中加锁/解锁过程就是xSemaphoreTakexSemaphoreGive的过程,只是获取信号量的时间设置为无限大,没有时间限制一直阻塞,所以互斥量的使用好比是钥匙,谁拿到了钥匙才可以解锁。

 

/************************ mutex manage************************/

void *platform_mutex_init(void)

{

pthread_mutex_t mutex;

sys_mutex_new(&mutex);

return (void *)mutex;

}

 

void platform_mutex_lock(void *mutex)

{

/*

while(xSemaphoreTake(mutex, portMAX_DELAY) != pdTRUE){

printf("[%s] platform_mutex_lock(%p) failed,retry\n", pcTaskGetTaskName(NULL), mutex);

}

*/

sys_mutex_lock(&mutex);

}

 

void platform_mutex_unlock(void *mutex)

{

sys_mutex_unlock(&mutex);

// xSemaphoreGive(mutex);

}

 

void platform_mutex_destroy(void *mutex)

{

/*

if(mutex != NULL)

vSemaphoreDelete(mutex);

 

mutex = NULL;

*/

sys_mutex_free(&mutex);

}

 

(4)资源管理

访问一个被多任务共享或任务与中断共享的资源时,采用“互斥”保证数据在任何时候都保持一致。

   互斥方法:基本临界区、挂起调度器、互斥量、守护任务

知识点1:基本临界区taskENTER_CRITICAL() / taskEXIT_CRITICAL()

taskENTER_CRITICAL() 到taskEXIT_CRITICAL()之间的代码为基本临界区,保护代码区间不被其他任务或中断打断。会把中断全部关掉,或是关掉优先级在configMAX_SYSCAL_INTERRUPT_PRIORITY及以下的中断。临界区必须只具有很短的时间,否则会影响中断响应时间。

知识点2:挂起调度器vTaskSuspendAll(挂起)/ vTaskResumeAll(唤醒)

调度器挂起时,上下文切换请求也被挂起,直到调度器被唤醒后才会得到执行。停止上下文切换,此时不关中断。调度器挂起时,不能调用 API 函数。

知识点3:互斥量,前面已经介绍,这里说一下互斥量的使用时要避免死锁;

死锁还是举个例子说明,比如说任务 A 和任务 B 都需要获得互斥量 X 和互斥量 Y以完成各自的工作;A 获得 X,B 获得 Y;A 阻塞在 Y 上,B 阻塞在 X 上;A 和 B 都不能执行。自行画个草图就可明白。

         避免死锁的最好方法是官方给出的是在设计阶段就考虑到这种潜在风险,换言之,黑瞎子捧刺猬,碰到棘手事,没招,写code时自求多福吧。

知识点4:守护任务,用的较少,自行百度吧。

心跳钩子函数vApplicationTickHook(或称回调函数)由内核在每次心跳中断时调用。要挂接一个心跳钩子函数,需要做以下配置:设置 FreeRTOSConfig.h 中的常量 configUSE_TICK_HOOK 为 1。心跳钩子函数在系统心跳中断的上下文上执行,所以必须保证非常短小,适度占用栈空间,并且不要调用任何名字不带后缀”FromISR”的 FreeRTOS API 函数。

(5) tickless低功耗模式

仅从字母上看这个字母就是表示滴答时钟节拍停止运行的情况;我们都知道,当用户任务都被挂起或者阻塞时,最低优先级的空闲任务会得到执行。为了实现低功耗最优设计,我们还不能直接把睡眠或者停机模式直接放在空闲任务就可以了。 进入空闲任务后,首先要计算可以执行低功耗的最大时间(下一个要执行的高优先级任务还剩多少时间);然后就是把低功耗的唤醒时间设置为这个求出的时间,到时间后系统会从低功耗模式被唤醒,继续执行多任务。这个就是所谓的 tickless 模式。

只需要configUSE_TICKLESS_IDLE 为 1 即可。 如果配置此参数为 2,那么用户可以自定义 tickless 低功耗模式的实现。 当用户将宏定义configUSE_TICKLESS_IDLE配置为 1 且系统运行满足以下两个条件时,

系统内核会自动的调用低功耗宏定义函数portSUPPRESS_TICKS_AND_SLEEP()

1)当前空闲任务正在运行,所有其它的任务处在挂起状态或者阻塞状态。

2)当系统可运行于低功耗模式的时钟节拍数大于等于用户配置 configEXPECTED_IDLE_TIME_BEFORE_SLEEP(一般是100ms)的大小,系统才可以进入到低功耗模式。

有时公司设计可能是默认是都打开的,将tickless默认是加锁关闭,释放tickless的锁才会启动tickless。

   学习FreeRTOS中文实用教程.pdf时整理了一份ppt,可以

http://download.csdn.net/download/qq_36974328/10263733 进行下载,请大家参考。

参考资料:官网https://www.freertos.orgFreeRTOS中文实用教程.pdf

有什么问题,也可发邮件至347685880@qq.com进行交流探讨。



  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值