FreeRTOS通过相对延时函数分析系统时钟配置

1、我是将Free RTOS移植到了HC32F460上,整体的移植和STM32大同小异,需要注意的是系统时钟不一致,系统定时器中断函数的处理需要注意。void vTaskDelay的源码如下:

void vTaskDelay( const TickType_t xTicksToDelay )
{
BaseType_t xAlreadyYielded = pdFALSE;

	/* A delay time of zero just forces a reschedule. */
	if( xTicksToDelay > ( TickType_t ) 0U )
	{
		configASSERT( uxSchedulerSuspended == 0 );
		vTaskSuspendAll();
		{
			traceTASK_DELAY();

			/* A task that is removed from the event list while the
			scheduler is suspended will not get placed in the ready
			list or removed from the blocked list until the scheduler
			is resumed.

			This task cannot be in an event list as it is the currently
			executing task. */
			prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
		}
		xAlreadyYielded = xTaskResumeAll();
	}
	else
	{
		mtCOVERAGE_TEST_MARKER();
	}

	/* Force a reschedule if xTaskResumeAll has not already done so, we may
	have put ourselves to sleep. */
	if( xAlreadyYielded == pdFALSE )
	{
		portYIELD_WITHIN_API();
	}
	else
	{
		mtCOVERAGE_TEST_MARKER();
	}
}

2、这是延时函数源码,具体就不说了,网上很多。大概就是系统定时器作为延时函数的时间来源,例如延时100ms。那么vTaskDelay(100);,系统定时器的Tick就是RTOS的心脏, 程序中一个Tick是1ms,具体为啥是1ms,一会具体说说。
RTOS的延时和l裸机的延时最大的区别就是榨干CPU,延时的过程中也可以找优先级最高的任务运行,避免死等,最次也有一个空闲任务运行。由此我想到了裸机的延时函数,我之前的裸机延时函数也是系统定时器写的,如果延时期间有高优先级的任务也会优先执行,避免死等,因为系统定时器的优先级是最低的,和RTOS的最大区别就是RTOS都是以任务的形式执行,而逻辑是按照程序的顺序执行,那么实时性就没有RTOS好。

3、具体说说不同单片机型号对应Free RTOS的一个Tick是怎么算出来的。FreeRTOSconfig.h中有如下配置:

#define configCPU_CLOCK_HZ 						  (SystemCoreClock)
#define configTICK_RATE_HZ						  (( TickType_t )1000)

configCPU_CLOCK_HZ 是单片机主频即FCLK,stm32F03 72M。 我的主频目前是100M。
configTICK_RATE_HZ 这个宏定义就是规定了一个Tick的周期,具体怎么规定的,往下看:

在**vPortSetupTimerInterrupt()**函数中

void vPortSetupTimerInterrupt( void )
{
	/* Calculate the constants required to configure the tick interrupt. */
	#if configUSE_TICKLESS_IDLE == 1
	{
		ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
		xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / u     	lTimerCountsForOneTick;
		ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
	}
	#endif /* configUSE_TICKLESS_IDLE */

portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;

这句话就是精髓!

ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );

这句话类似裸机里的

SysTick_Config(SystemCoreClock / 100000))函数。目的是将SysTick 重装载数值寄存器赋值,也就是

load = 100M/1000 = 100000;
TINT=VALUELOAD * TDEC中断= VALUELOAD/CLKAHB TINT = 100000 / 100 M= 1000us = 1ms
那么就计算出一个Tick为 1ms ,vTaskDelay(100) 就是延时100ms。

写到这我想各位应该明白了。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值