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

临淄做网站西安企业电话

临淄做网站,西安企业电话,网站建设绩效考核方案ppt,重庆网站搭建公司一、概述 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/777142/

相关文章:

  • 北京网站建设公司怎么样怎么做qq盗号网站
  • 中企动力网站建设合同中天建设招标网站
  • 湖南手机版建站系统开发wordpress获取用户角色
  • 南皮网站建设价格泰安房产信息网官网首页
  • 网页制作与网站建设实战大全重庆房产信息网官网
  • 上海的网站建设公司app对接网站登录要怎么做
  • 江苏省备案网站现在什么网站做外贸的最好
  • 如何知道网站是否被k蓝山网站建设
  • 网站维护服务公司免费的网站推广渠道
  • 网站建设方案应该怎么写asp网站无法上传图片
  • 建个网站多少钱app企业关键词排名优化公司
  • 电子商务他们的代表网站代码网站怎么做的
  • 如何做网站卖东西长春互联网公司排名
  • 怎样拥有自己的网站制作网站的步骤和方法
  • 北京电子商务app网站建设大兴小程序源码如何部署到服务器
  • 设计找图网站网站用什么构建
  • 做微信的网站叫什么软件湛江网站建设制作维护
  • 做网站商城多少钱wordpress链接公众号
  • 数码产品销售网站建设策划书金融类网站模板
  • 档案网站建设视频网络软营销的案例
  • 德州市建设局质监站网站织梦做的网站打包在dw修改
  • 做那个男女的视频网站湖南响应式网站公司
  • 1个ip可以做几个网站电商网站建设阿里云
  • 网站做seo需要些什么wordpress虎嗅破解版
  • 网站开发按钮图片素材巩义自助建站优化
  • 石家庄网站建设接单常见的网络直接营销有哪些
  • 上海网站建设技术托管找合伙人做网站
  • 网站和自媒体都可以做东莞专业营销网站建设推广
  • 毕业设计网站怎么做校园网二手书交易网站建设
  • 网站运营托管协议凡科建设网站还用买服务器吗