【FreeRTOS】taskdelay相关问题:在gd32f450中任务周期不准
时间:2022-11-08 02:00:00
问题描述:在GD32F450中移植FreeRTOS相关参数设置如下:
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
其作用如下:
FreeRTOS根据时间片调度任务(time slicing)的方式。顾名思义,时间片将一段时间等分为多个时间段,以确保优先级最高的任务能够在每个时间段执行。同时,如果几个任务有相同的优先级,它们将轮流占用每个时间段CPU资源。每个时间片结束时,调度器都会通过周期中断(tick interrupt)执行一次,调度器将根据设置的抢占或合作模式在下一个时间段运行。
由于时间片的大小configTICK_RATE_HZ如果configTICK_RATE_HZ设置为10HZ,时间片的大小是100ms。configTICK_RATE_HZ的值由应用需求决定,通常设为100HZ(时间片大小对应10ms)。
当使用vTaskdelayUntill 当函数设置任务运行周期时,发现设置的周期数与实际时间不一致。
例如,设置10ms实际周期为12ms。实际周期比设定的周期多2ms。
其他地方暂时没有发现异常。修改上述宏定义至500后,设置4ms以上,2ms在整数倍周期中,实际时间与设定一致。
但是设定2ms周期时,实际周期为约3.11ms。
将宏定义改回1000后,设置1ms当周期相同时,实际周期约为3.11ms。
我猜,这是设定1000的原因configTICK_RATE_HZ实际周期与设定周期不一致的原因。更深层次的原因尚未分析。
-----------------------分割线-------------------------
注释任务中的函数后,无论设置如何configTICK_RATE_HZ是1000还是500。任务可以按照预定的周期调用。
由于变量xTickCount它可能会溢出,因此程序必须检测各种溢出,并确保延迟周期不得小于任务主体代码的执行时间。这很容易理解不可能每5毫秒执行一项需要20毫秒的任务。
测试任务中运行函数所需的时间为:3.11ms ,所以这里解释了为什么最小任务周期是3.11ms。
-----------------------分割线-------------------------
任务周期为3.11ms,configTICK_RATE_HZ为1000(systick为1ms)任务周期为10ms,为什么实际与设置不符?
taskENTER_CRITICAL(); ... taskEXIT_CRITICAL();
在执行任务中的函数时,将代码段放入临界保护区,以确保代码执行过程中不中断,临界保护区的作用如下:
The taskENTER_CRITICAL() and taskEXIT_CRITICAL() macros provide a basic critical section implementation that works by simply disabling interrupts, either globally, or up to a specific interrupt priority level. See the vTaskSuspendAll() API function for information on creating a critical section without disabling interrupts.
简单翻译: 宏taskENTER_CRITICAL()和宏taskEXIT_CRITICAL()提供了一个基本的临界区域,它通过简单的禁用中断来工作,无论是全局还是具体的中断优先级。vTaskSuspendAll() API函数知道如何在不禁中断的情况下创建临界区。
Critical sections must be kept very short, otherwise they will adversely affect interrupt response times. Every call to taskENTER_CRITICAL() must be closely paired with a call to taskEXIT_CRITICAL().
简单翻译:临界区域必须很短,否则会对中断响应时间产生不利影响。taskENTER_CRITICAL()每次调用必须与对方相匹配taskEXIT_CRITICAL()调用紧密配对。
由于长期中断,将整个函数段放入临界区,GD32F450的systick中断一直无法进入,导致周期延迟,这是一个非常糟糕的结果。
应尽量减少临界区的使用。
以上分析,请多多交流。