@[toc]

在这里插入图片描述

空闲线程的运行时间分析

原因

  • 开启TICKLESS模式后,在PreSleepProcessingPostSleepProcessing中打印ulExpectedIdleTime变量,即空闲时间.输出如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-56thy2v3-1684831702598)(TICKLESS.assets/image-20230523161450180.png)]

  • 代码如下
1
2
3
4
5
6
7
8
9
void PreSleepProcessing(uint32_t *ulExpectedIdleTime)
{
log_i("ulExpectedIdleTime %lu", *ulExpectedIdleTime);
}

void PostSleepProcessing(uint32_t *ulExpectedIdleTime)
{

}

分析

  • 为什么是349tick进入一次空闲线程?
  • 分析FREERTOS源码,在portTASK_FUNCTION函数中调用接口,写入空闲时间值
  • 在赋值后打印变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
{
vTaskSuspendAll();
{
configASSERT( xNextTaskUnblockTime >= xTickCount );
xExpectedIdleTime = prvGetExpectedIdleTime();
//这里打印一下时间
printf("xExpectedIdleTime = %lu", xExpectedIdleTime);

if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
{
traceLOW_POWER_IDLE_BEGIN();
portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
traceLOW_POWER_IDLE_END();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
( void ) xTaskResumeAll();
}

输出如下

1
2
xExpectedIdleTime = FFFF FD23
I/NO_TAG [ms:0000000732] ulExpectedIdleTime 349
  • 空闲执行时间没问题,传入函数后有问题.

  • 进入vPortSuppressTicksAndSleep分析,找到如下代码

1
2
3
4
5
6
/* Make sure the SysTick reload value does not overflow the counter. */
/*确保 SysTick 重载值不会溢出计数器。*/
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
{
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
}

查找变量xMaximumPossibleSuppressedTicks赋值

1
2
3
4
5
6
/* The systick is a 24-bit counter. */
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
/* 48MHZ / 1000hz调度频率 */
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
/*xMaximumPossibleSuppressedTicks = 0xffffffU / 48000 ≈ 349 */
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;

结论

  • 当线程全部阻塞时,空闲线程时间实际预计的解除阻塞时间 - 当前运行时间.
  • 但是在进入TICKLESS后,为了确保 SysTick 重载值不会溢出计数器.所以限制了TICKLESS的低功耗休眠时间.
  • 所以进入TICKLESS的最大时间为0XFFFFFF / (系统时钟 / 调度频率),在本机中为349.