当前位置: 首页 > news >正文

丽水做网站公司餐饮网站建设公司

丽水做网站公司,餐饮网站建设公司,网站中验证码如何做的,公司电子版简介模板一、概述 FreeRTOS提供了两个系统延时函数#xff0c;相对延时函数vTaskDelay()和绝对延时函数vTaskDelayUntil()。相对延时是指每次延时都是从任务执行函数vTaskDelay()开始#xff0c;延时指定的时间结束#xff0c;绝对延时是指每隔指定的时间#xff0c;执行一次调用vT…   一、概述 FreeRTOS提供了两个系统延时函数相对延时函数vTaskDelay()和绝对延时函数vTaskDelayUntil()。相对延时是指每次延时都是从任务执行函数vTaskDelay()开始延时指定的时间结束绝对延时是指每隔指定的时间执行一次调用vTaskDealyUntil()函数的任务换句话说就是任务以固定的频率执行。 相对延时指每次延时都是从执行函数vTaskDelay()开始直到延时指定的时间结束。绝对延时指将整个任务的运行周期看作一个整体适用于需要按照一定频率运行的任务。 为任务主体也就是任务真正要做的工作是任务函数中调用vTaskDelayUntil对任务进行延时为其他任务运行 二、相对延时函数vTaskDelay() 考虑下面的任务任务A在执行任务主体代码后调用相对延时函数vTaskDelay()进入阻塞态。系统中除了任务A外还有其他任务但是任务A的优先级最高。 void vTaskA( void * pvParameters ) { /* 阻塞500ms. 注:宏pdMS_TO_TICKS用于将毫秒转成节拍数,FreeRTOS V8.1.0及以上版本才有这个宏,如果使用低版本,可以使用 500 / portTICK_RATE_MS */ const portTickType xDelay pdMS_TO_TICKS(500); for( ;; ) { // ...// 这里为任务主体代码// .../* 调用系统延时函数,阻塞500ms */vTaskDelay( xDelay ); } } 对于这样一个任务执行过程的图示如下所示当任务A获取CPU使用权后先执行任务A的主体代码之后调用系统延时函数vTaskDelay()进入阻塞态。任务进入阻塞态后其他任务得以执行。FreeRTOS内核会周期的检查任务A的阻塞是否达到在滴答定时中断中进行解除阻塞态如果阻塞时间达到则将任务A设置为就绪态由于任务A的优先级最高会抢占CPU再次执行任务主体代码不断循环。 从图中可以看出如果执行任务A的过程中发生中断那么任务A执行的周期就会变长所以使用相对延时函数vTaskDelay()不能周期的执行任务A。 void vTaskDelay( const TickType_t xTicksToDelay ){BaseType_t xAlreadyYielded pdFALSE;/*如果延时时间为0则不会将当前任务加入延时列表. */if( xTicksToDelay ( TickType_t ) 0U ){configASSERT( uxSchedulerSuspended 0 );vTaskSuspendAll();{traceTASK_DELAY();/* 将当前任务从就绪列表中移除并根据当前系统节拍计数器值计算唤醒时间然后将任务加入延时列表 */prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );}xAlreadyYielded xTaskResumeAll();}else{mtCOVERAGE_TEST_MARKER();}/* 强制执行一次上下文切换 */if( xAlreadyYielded pdFALSE ){portYIELD_WITHIN_API();}else{mtCOVERAGE_TEST_MARKER();}} 如上述代码如果延时大于0则会将当前任务从就绪列表删除然后加入到延时列表。是调用函数prvAddCurrentTaskToDelayedList()完成这一过程的tasks.c中定义了很多局部变量其中有一个变量xTickCount定义如下所示  static volatile TickType_t xTickCount (TickType_t) 0U; 这个变量用来计数记录系统节拍中断的次数它在启动调度器时被清零在每次系统节拍时钟发生中断之后加1.相对延时函数会使用到这个变量xTickCount表示了当前的系统节拍中断次数这个值加上参数规定的延时时间以系统节拍数表示xTickToDelay就是下次唤醒任务的时间xTickCount xTicksToDelay会被记录到任务TCB中随着任务一起被挂接到延时列表。 我们直到变量xTickCount是TickType_t类型的它会溢出。在32位架构中当xTicksToDelay达到0xFFFF_FFFF后再增加就会溢出变成0.为了解决xTickCount溢出问题FreeRTOS使用了两个延时列表xDelayedTaskList1和xDelayedTaskList2并使用两个列表指针类型变量pxDelayedTaskList和pxOverflowDelayedTaskList分别指向上面的延时列表1和延时列表2在创建任务时将延时列表指针指向延时列表。顺便说一下上面的两个延时列表指针变量和两个延时列表变量都是在tasks.c中定义的静态局部变量。 如果内核判断出xTickCountxTicksToDelay溢出将当前任务挂在列表指针pxOverflowDelayedTaskList指向的列表中否则就挂接到列表指针pxDelayedTaskList指向的列表中。 每次系统节拍时钟中断中断服务函数都会检查这两个延时 列表查看延时的任务是否到期如果时间到期则将任务从延时列表中删除重新加入就绪列表。如果新加入就绪列表的任务优先级大于当前任务则会触发一次上下文切换(保护现场和恢复现场)。 else{/* Calculate the time at which the task should be woken if the event* does not occur. This may overflow but this doesnt matter, the* kernel will manage it correctly. */xTimeToWake xConstTickCount xTicksToWait;/* The list item will be inserted in wake time order. */listSET_LIST_ITEM_VALUE( ( pxCurrentTCB-xStateListItem ), xTimeToWake );if( xTimeToWake xConstTickCount ){/* Wake time has overflowed. Place this item in the overflow* list. */vListInsert( pxOverflowDelayedTaskList, ( pxCurrentTCB-xStateListItem ) );}else{/* The wake time has not overflowed, so the current block list* is used. */vListInsert( pxDelayedTaskList, ( pxCurrentTCB-xStateListItem ) );/* If the task entering the blocked state was placed at the* head of the list of blocked tasks then xNextTaskUnblockTime* needs to be updated too. */if( xTimeToWake xNextTaskUnblockTime ){xNextTaskUnblockTime xTimeToWake;}else{mtCOVERAGE_TEST_MARKER();}} 三、绝对延时函数vTaskDelayUntil()  考虑下面的任务B任务B首先调用绝对延时函数vTaskDelayUntil()进入阻塞态阻塞时间到后执行任务主体代码系统中除了任务B外还有其它任务但是任务B的优先级最高。 void vTaskB( void * pvParameters ) { static portTickType xLastWakeTime; const portTickType xFrequency pdMS_TO_TICKS(500); // 使用当前时间初始化变量xLastWakeTime ,注意这和vTaskDelay()函数不同 xLastWakeTime xTaskGetTickCount(); for( ;; ) { /* 调用系统延时函数,周期性阻塞500ms */ vTaskDelayUntil( xLastWakeTime,xFrequency ); // ...// 这里为任务主体代码,周期性执行.注意这和vTaskDelay()函数也不同// ...} } 对于这样一个任务执行过程如下图所示当任务B获取CPU使用权后先调用系统延时函数vTaskDelayUntil()使任务进入阻塞态。任务B进入阻塞态后其他任务得以执行FreeRTOS内核会周期性的检查任务A的阻塞是否达到如果阻塞时间达到则将任务A设置为就绪态由于任务B的优先级最高会抢占CPU接下来执行任务主体代码。任务主体代码执行完毕后会继续调用系统延时函数vTaskDelayUntil()使任务进入阻塞态周而复始。 从图可以看出从调用函数vTaskDelayUntil()开始每隔固定周期任务B的主体代码就会执行一次即使任务B在执行过程中发生中断也不会影响这个周期性只是会缩短其他任务的执行时间所以这个函数被称之为绝对延时函数它可以用于周期性的执行任务A的主体代码。 函数vTaskDelayUntil()是如何做到周期性的呢看下面源码 BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,const TickType_t xTimeIncrement ){TickType_t xTimeToWake;BaseType_t xAlreadyYielded, xShouldDelay pdFALSE;configASSERT( pxPreviousWakeTime );configASSERT( ( xTimeIncrement 0U ) );configASSERT( uxSchedulerSuspended 0 );vTaskSuspendAll();{/* 保存系统节拍中断次数计数器 */const TickType_t xConstTickCount xTickCount;/* 计算任务下次话u女性时间以系统节拍中断次数表示. */xTimeToWake *pxPreviousWakeTime xTimeIncrement;/* pxPreviousWakeTime中保存的是上次唤醒时间唤醒后需要一定时间执行任务主体代码如果上次唤醒时间大于当前时间说明节拍计数器溢出了*/if( xConstTickCount *pxPreviousWakeTime ){/*只有当周期性延时时间大于任务主体大妈执行时间才会将任务挂接到延时列表*/if( ( xTimeToWake *pxPreviousWakeTime ) ( xTimeToWake xConstTickCount ) ){xShouldDelay pdTRUE;}else{mtCOVERAGE_TEST_MARKER();}}else{/* 也都是保证周期性延时时间大于任务主体代码执行时间*/if( ( xTimeToWake *pxPreviousWakeTime ) || ( xTimeToWake xConstTickCount ) ){xShouldDelay pdTRUE;}else{mtCOVERAGE_TEST_MARKER();}}/* 更新唤醒时间为下一次调用本函数做准备 */*pxPreviousWakeTime xTimeToWake;if( xShouldDelay ! pdFALSE ){traceTASK_DELAY_UNTIL( xTimeToWake );/* 将本任务加入延时列表注意阻塞时间并不是以当前时间为参考因此减去了当前系统节拍中断计数器数值*/prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE );}else{mtCOVERAGE_TEST_MARKER();}}xAlreadyYielded xTaskResumeAll();/* 强制执行一次上下文切换 */if( xAlreadyYielded pdFALSE ){portYIELD_WITHIN_API();}else{mtCOVERAGE_TEST_MARKER();}return xShouldDelay;} 与相对延时函数vTaskDelay不同本函数增加了一个参数pxPreviousWakeTime用于指向一个变量变量保存上次任务解除阻塞时间。这个变量在任务开始时必须被设置成当前系统节拍中断次数此后函数vTaskDelayUntil()在内部自动更新这个变量。 由于变量xTickCount可能会溢出所以程序必须检查各种溢出情况并且要保证延时周期不得小于任务主体代码执行时间。这很好理解就是不可能出现每5ms执行一个需要20ms才能完成的任务。 如果我们以横坐标表示变量xTickCount的范围则横坐标左端为0右端为变量xTickCount所能表示的最大值在上图所示的三种情况下才可以将任务加入延时列表。如上图*pxPreviousWakeTime和xTimeToWake之间表示任务周期性延时时间*pxPreviousWakeTime和xConstTickCount之间表示任务B主体代码执行时间。 图中第一种情况处理系统节拍中断计数器xConstTickCount和唤醒时间计数器xTimeToWake溢出情况第二种情况处理唤醒时间计数器xTimeToWake溢出情况第三种情况处理常规无溢出的情况。从图中可以看出不管是溢出还是无溢出都要求在下次唤醒任务之前当前任务主体代码必须被执行完。表现在图中就是变量xTimeToWake总是大于变量xConstTickCount每溢出一次的话相当于加上一次最大值Max。 计算的唤醒时间合法后就将当前任务加入延时列表同样延时列表也有两个。每次系统节拍中断中断服务函数都会检查这两个延时列表查看延时的任务是否到期如果时间到期则将任务从延时列表中删除重新加入就绪列表。如果新加入就绪列表的任务优先级大于当前任务则会触发一次上下文切换。 四、总结 调用系统延时的任务都是最高优先级这是为了便于分析而特意为之的实际上的任务可不一定能设置为最高优先级。对于相对延时如果任务不是最高优先级则任务执行周期更不可测这个问题不大我们本来也不会使用它作为精确延时对于绝对延时函数如果任务不是最高优先级则仍然能周期性的将任务解除阻塞但是解除阻塞的任务不一定能获得CPU权限因此任务主体代码也不会总是精确周期性执行。 如果要想精确周期性执行某个任务可以使用系统节拍钩子函数vApplicationTickHook()它在系统节拍中断服务函数中被调用因此这个函数中的代码必须简洁。
http://www.pierceye.com/news/501512/

相关文章:

  • 阿里云增加网站wordpress前台后台都空白
  • 做网站商城要注册什么公司建行官网官网网站吗
  • 国外做meta分析的网站wordpress 下载文件插件
  • 济南城市建设集团网站陕西网
  • 专业的网站设计制作怎么建正规网站
  • 用安卓做网站php网站开发系统
  • 58同城网站建设的不足网站前台代码
  • 网站建设销售人员培训教程长兴县建设局网站
  • 用vue框架做的pc端网站wordpress改造论坛
  • 大庆建设网站首页中国寰球工程有限公司网站设计
  • 免费搭建贴吧系统网站js做网站框架
  • 泰安如何选择网站建设网盘 商业网站建设案例课程 下载
  • 可信赖的邵阳网站建设动漫设计属于什么大类
  • 西安网站排名优化网站设计用什么软件实现
  • 网站注册页面模板html5教程百度云
  • 深圳装饰公司前十强佛山seo优化电话
  • 广东阳春市建设局网站做手机网站的重要性
  • 设置网站的关键词自己做网站有什么用
  • 做那个网站比较好百度百科优化排名
  • 好发信息网站建设新闻今天最新消息
  • 邮件服务器是不是网站服务器河南住房和城乡建设网站
  • 微网站管理平台网站连锁店查询怎么做
  • 网域高科学校网站管理系统企业融资以什么为基础
  • 百度网站改版工具提高网站安全性
  • 科技网站推荐南宁百度seo
  • 设计婚纱网站wordpress主题制作全过程新手必看
  • 郑州网站seo厂家上海制作网页的公司有哪些
  • 网站修改关键词不收录vps 可以做多个网站吗
  • 营销外包网站App加网站什么做
  • 网页设计网站制作视频教程重庆是哪个省份