FreeRTOS开启tickless模式后的时间精度探究

引言

对于很多使用MCU的应用而言,功耗是一个非常重要的指标,对于使用电池供电的设备来说,降低功耗是一个非常重要的话题。一个通用的做法就是当设备空闲时,控制设备进入低功耗模式。除了关闭不在工作的外部模块以外,控制mcu进入低功耗的模式也是一个比较重要的途径。
当前时代,mcu处理能力大大增加,处理的任务复杂度也大幅度增加,在这种情况下,引入RTOS是处理复杂任务场景的一个非常优秀的解决方法。
在之前不使用用RTOS且任务相对简单的情况下,开发者可以根据任务流程,找到一个空闲的时刻,控制系统进入低功耗模式;在当前的背景下,开发者不仅希望在明确的条件下进入低功耗模式,更加希望在运行过程中,一旦发现cpu有空闲,就进入低功耗模式从而进一步降低功耗。
为了更好的解决上述的问题,许多RTOS都有低功耗机制,但是这些低功耗机制,或多或少都对RTOS的时间精度产生一定的影响。本文以FreeRTOS的tickless模式为例,探究一下在先楫hpm系列芯片上tickless模式对时间精度的影响

HPM_SDK中的tickless模式

HPM_SDK中对FreeRTOS的tickless模式做了适配,开发者只需要在工程项目CMakeLists.txt中增加set(CONFIG_FREERTOS_TICKLESS 1)并重新生成工程即可开启。

FreeRTOS的不同tick源

对于熟悉arm cortex M系列芯片的开发者可能了解,FreeRTOS使用ARM的systick模块周期性的产生中断,来驱动系统运行,我们把一个周期称为一个tick。在riscv中,也存在一个类似功能的timer,即machine timer(MCHTMR),许多riscv芯片都是用MCHTMR来产生tick。
对于arm而言,systick模块的优先级是可以配置的,默认情况下,systick的优先级比其他外设中断的优先级要低。对于riscv而言,MCHTMR和外设中断PLIC相对独立,其没有优先级的概念。在HPM系列芯片中,当开启了plic抢占功能后,处理plic中断时,有可能被mchtmr中断抢占,这是arm和riscv的区别之一。
由于很多开发者的工程是从arm下移植而来,他们希望系统tick中断的优先级不会抢占外设的中断,HPM_SDK提供了一种方式来解决这个问题:采用GPTMR来产生系统tick,并将GPTMR的中断优先级降为最低。在工程CMakeLists.txt中增加set(CONFIG_FREERTOS_TIMER_RESOURCE_GPTMR 1)即可。

使用mchtmr时tickless模式的时间精度

使用mchtmr时,在进入tickless模式前,会计算出下次唤醒时的mchtmr的值,并写入cmp寄存器。当被唤醒时,计算实际经过了多少个周期,增加系统tick数,并重新计算mchtmr下个系统时刻的值,并写入cmp寄存器。
理论分析:
由于在整个操作过程中mchtmr并没有停止运行,所以理论上开启tickless模式不会对系统的tick精度产生影响
验证方法:
只创建一个任务,任务翻转gpio的电平,并周期性睡眠。由于没有其他任务的干扰,反转gpio的间隔即可用来测量RTOS的tick精度。同时我们开启串口中断,使用串口中断来触发提前退出tickless模式。
测试用例如下:
1.串口中无数据,每次tickless均为mchtmr中断唤醒

2.串口以2ms为周期发送数据

将逻辑分析仪的数据导出为csv文件,使用excel计算每次gpio电平反转的间隔,以及统计从第一个翻转到第N个反转之间的间隔。可以得到以下的数据:

平均间隔 间隔方差 等效ppm
不开启tickless 99.99738076ms 1.09511E-10 25.92977661
mchtmr唤醒 99.99736734 9.29684E-11 26.3266
串口唤醒 99.99737484 8.85753E-08 26.25155051

由上述数据可以看出,在仅开启tickless模式时,各项数据和不开启tickless时差别不大,在存在uart中断唤醒时,tick间隔平均值几乎没有变化,间隔方差一定程度增大,最大的间隔偏移量增大,等效ppm增大,这是因为中断处理延迟了任务的执行,是符合预期的。由此可得出结论:在使用mchtmr作为系统tick源时,开启tickless并不会对系统时钟的准确性造成影响

使用gptmr作为tick源

在使用gptmr作为tick源且开启tickless模式时,hpm_sdk会选择PTMR低功耗域的Timer作为tick源。在进入tickless模式前,freeRTOS会计算下次唤醒时刻需要的count值,并写入PTMR的reload寄存器。在计算并修改reload的过程中,PTMR的counter是暂停的状态;同时在唤醒后计算经过的tick数时,PTMR的counter也是暂停的状态,由此引入了一些时间上的误差。所以为了降低这个误差,FreeRTOS提供了一个宏,每次计算时都会根据宏的值来微调,但是这个调整不能完全消除误差。从理论分析上来说,使用PTMR并开启tickless模式后,tick的准确度会受到一定影响。
理论分析:
在不进行补偿时,每次进入和退出tickless模式都会让系统时间微微的往后延长,所以理论上来说,开启tickless模式后,平均的tick间隔会增加,随着单位时间内唤醒的次数增加,系统时刻延长的越多。

验证方法:
只创建一个任务,任务翻转gpio的电平,并周期性睡眠。由于没有其他任务的干扰,反转gpio的间隔即可用来测量RTOS的tick精度。同时我们开启串口中断,使用串口中断来触发提前退出tickless模式。
测试用例如下:
1.串口中无数据,每次tickless均为gptmr reload中断唤醒

2.串口以10ms为周期发送数据

将逻辑分析仪的数据导出为csv文件,使用python脚本计算每次gpio电平反转的间隔,以及统计从第一个翻转到第N个反转之间的间隔。可以得到以下的数据:

间隔方差 间隔方差 等效ppm
不开启tickless 99.99740361ms 3.3543E-10 25.96385467
gptmr唤醒 99.99943671ms 8.23299E-10 5.632944295
串口唤醒 100.0549865ms 1.77066E-05 -549.8650217

在只开启tickless模式时,间隔略微增加了,符合预期;在开启tickless并使用uart唤醒时,间隔进一步增加,且间隔的方差明显增大,这说明使用gptmr作为tick来源时,开启tickless模式后系统的时间精度收到中断数量的影响。但是从数据中可以看出,开启uart中断后,ppm增加到了549这个数量级,换算一下就是24小时系统时间会慢47秒。在实际应用中,用户可以根据项目对时间精度的具体要求,选择使用rtc校准系统时间,或者根据实际应用,对tickless操作进行补偿,以降低系统时间的偏移。

总结

在hpm_sdk中使用FreeRTOS的tickless模式时,如果采用mchtmr作为时钟源,那么开启tickless不会对系统时间精度产生影响。使用gptmr作为时钟源时,开启tickless会影响系统时间精度,但是影响较为有限,对于系统时间敏感的应用,可以采用定期通过RTC校准的方式来获得更加准确的系统时间。

0
0

订阅

发表回复 0

Your email address will not be published. Required fields are marked *