FreeRTOS的时间管理
最近需要将在Linux上的代码移植到FreeRTOS上,许多系统函数运行不了,其中就包括gettimeofday,以及使用定时器的不同。
FreeRTOS添加计时器
首先,FreeRTOS的系统时钟节拍可以在配置文件 FreeRTOSConfig.h 里面设置:
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )//配置系统时钟1KHz,即 1ms
在FreeRTOS中,系统时钟节拍的特点就是周期性中断,既然要产生中断那就需要定时器,所以在这里就是使用了一个24位的定时器,采用向下计数的方式,然后可以产生周期性的中断。
xTaskGetTickCount
TickType_t xTaskGetTickCount( void )
该函数用于获取系统当前运行的时钟节拍数。
注意:此函数用于在任务代码里面调用,如果在中断服务程序里面调用的话,需要使用函数 xTaskGetTickCountFromISR ,这两个函数切不可混用。
xTimerCreate
TimerHandle_t xTimerCreate( const char * const pcTimerName, // 名称,内核中不使用它,仅用于调试 const TickType_t xTimerPeriodInTicks, // 时长 tick const UBaseType_t uxAutoReload, // 设置为pdTRUE表示该定时器为自动重载定时器,设置为pdFALSE该定时器为一次性定时器 void * const pvTimerID, // 每个软件定时器都有一个ID值,由应用程序决定它的用途。pvTimerID表示该定时器ID的初始值 TimerCallbackFunction_t pxCallbackFunction ) // 回调函数指针
该函数用来创建一个定时器。
xTimerStart
#define xTimerStart( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) )
//
软件定时器打包命令与发送
BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, // 定时器的句柄
const BaseType_t xCommandID,
const TickType_t xOptionalValue,
BaseType_t * const pxHigherPriorityTaskWoken,
const TickType_t xTicksToWait )
该函数用于启动处于休眠态的软件定时器,或重置(重新启动)处于运行态的软件定时器。 xTimerStop() 用于停止处于运行态的软件计时器。 可以在启动调度程序之前调用 xTimerStart() ,但该操作会在调度程序启动之前启动定时器。
注意:不能在中断函数中调用 xTimerStart() ,中断安全版为 xTimerStartFromISR() 。
添加定时器样例
static void timer_1000ms_handler(TimerHandle_t xTimer) { // (void)signum; (void)xTimer; loop_time = 0; } static int timer_init(void) { TimerHandle_t xTimer = xTimerCreate("MyTimer", pdMS_TO_TICKS(1000), pdTRUE, 0, timer_1000ms_handler); if (xTimer != NULL) { xTimerStart(xTimer, 0); } else { perror("timer_settime failed"); return errno; } return 0; } int main(void) { timer_init();
vTaskStartScheduler();
while (1) {
} return 0; }
vTaskDelay
void vTaskDelay( const TickType_t xTicksToDelay )
该函数用于task的延时,就是交出CPU一段时间,FreeRTOS延时的单位是tick,就是调度的基本单位,而不是毫秒。
使用方式:
while(1) { //执行操作... vTaskDelay(1000 / portTICK_RATE_MS);//1000ms后重新执行操作 // or vTaskDelay(pdMS_TO_TICKS(1000)); }
FreeRTOS的gettimeofday平替
gettimeofday介绍
#include<sys/time.h> int gettimeofday(struct timeval *tv,struct timezone *tz )
在Linux平台上,使用函数该函数来得到精确时间。将得到的结果放入 struct timeval *tv 中,其结构为:
struct timeval{ long tv_sec; // 秒 long tv_usec; // 微秒 };
然而在FreeRTOS中并不提供该函数。
使用xTaskGetTickCount平替
xTaskGetTickCount 函数返回的是当前系统的tick计数值,通过乘以 portTICK_PERIOD_MS (每个tick的毫秒数)可以得到以毫秒为单位的时间。
void getCurrentTime() { TickType_t ticks = xTaskGetTickCount(); uint32_t milliseconds = ticks * portTICK_PERIOD_MS; // 根据需要进行时间戳转换和处理 // ... // 打印当前时间示例 printf("Current Time: %lu ms\n", milliseconds); }