Программирование ARM FreeRTOS xTimerCreate Tue, April 23 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

FreeRTOS xTimerCreate Печать
Добавил(а) microsin   

Создает новый программный таймер и возвратит дескриптор (handle), по которому к этому таймеру можно будет обращаться.

TimerHandle_t xTimerCreate (const char * const pcTimerName,
                            const TickType_t xTimerPeriod,
                            const UBaseType_t uxAutoReload,
                            void * const pvTimerID,
                            TimerCallbackFunction_t pxCallbackFunction);

Чтобы эта функция была доступна:

1. Обе опции configUSE_TIMERS и configSUPPORT_DYNAMIC_ALLOCATION должны быть установлены в 1 файле FreeRTOSConfig.h (configSUPPORT_DYNAMIC_ALLOCATION можно также оставить без определения, в таком случае его значение по умолчанию будет 1).

2. К сборке должен быть подключен модуль FreeRTOS/Source/timers.c.

xTimerCreate и xTimerCreateStatic. Каждый программный таймер требует небольшое количество RAM, в котором хранится состояние таймера. Если таймер создается вызовом xTimerCreate(), то эта RAM автоматически выделяется из кучи FreeRTOS. Если программый таймер создан функцией xTimerCreateStatic(), то RAM для этой цели предоставляется программистом в дополнительном последнем параметре функции. RAM в таком случае выделяется статически, во время компиляции. Для дополнительной информации по различиям выделения памяти динамически (из кучи) и статически (в момент компиляции) см. документацию [2].

Таймеры после создания находятся в неактивном состоянии. Функции xTimerStart(), xTimerReset(), xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() и xTimerChangePeriodFromISR() могут использоваться для перевода таймера в активное состояние.

Параметры xTimerCreate:

pcTimerName Удобочитаемый текст, который в целях отладки указывается для описания таймера. Ни для каких других целей этот параметр не нужен. Ядро RTOS обращается к таймеру только по его дескриптору, и никогда по имени.

xTimerPeriod Период таймера в тиках RTOS. Может использоваться макрос pdMS_TO_TICKS(), чтобы преобразовать длительность в миллисекунды в количество тиков. Например, если таймер должен сработать через 100 тиков, то просто установите xTimerPeriod в начение 100. Или если таймер должен сработать через 500 мс, то установите xTimerPeriod в значение pdMS_TO_TICKS(500). Макрос pdMS_TO_TICKS() может использоваться только если configTICK_RATE_HZ меньше или равен 1000. Период таймера в тиках должен быть больше 0.

uxAutoReload Если этот параметр установлен в pdTRUE, то таймер будет сам срабатывать периодически с интервалом xTimerPeriod. Если uxAutoReload установлен в pdFALSE, то таймер после запуска сработает однократно, и останется в неактивном состоянии.

pvTimerID Идентификатор, который назначается созданному таймеру. Обычно этот идентификатор может использоваться в общей callback-функции таймера, чтобы идентифицировать, какой из таймеров сработал, или этот идентификатор может использоваться в функциях vTimerSetTimerID() и pvTimerGetTimerID() для сохранения значения между вызовами callback-функции таймера.

pxCallbackFunction Это функция, которая будет вызвана при срабатывании таймера. У callback-функций должен быть прототип, определенный типом TimerCallbackFunction_t:

void vCallbackFunction (TimerHandle_t xTimer);

Возвращаемое значение: если таймер был успешно создан, то будет возвращен дескриптор (handle) для нового созданного таймера. Если таймер не может быть создан из-за недостатка памяти в куче FreeRTOS, чтобы выделить структуры для таймера, то будет возвращено значение NULL.

Пример использования:

#define NUM_TIMERS 5
 
/* Массив для хранения дескрипторов созданных таймеров. */
TimerHandle_t xTimers [NUM_TIMERS];
 
/* Определение callback-функции, которая будет использоваться несколькими
   экземплярами таймеров. Эта функция только подсчитывает количество
   срабатываний таймера, и остановит таймер, как только он сработает
   10 раз. Счетчик срабатываний сохраняется как ID таймера. */
void vTimerCallback (TimerHandle_t xTimer)
{
   const uint32_t ulMaxExpiryCountBeforeStopping = 10;
   uint32_t ulCount;
 
   /* Опциональная проверка, что параметр pxTimer не NULL. */
   configASSERT(xTimer);
 
   /* Количество раз, которое сработал таймер, сохраняется в ID таймера.
      Получим этот счетчик. */
   ulCount = (uint32_t)pvTimerGetTimerID(xTimer);
 
   /* Инкремент счетчика, затем его проверка, достиг ли он значения
      ulMaxExpiryCountBeforeStopping. */
   ulCount++;
 
   /* Если таймер сработал 10 раз, остановим его. */
   if(ulCount >= ulMaxExpiryCountBeforeStopping)
   {
      /* Не используйте время блокировки, если вызываете API-функцию
         таймера из callback-функции таймера, так как это может
         вызвать самоблокировку (deadlock)! */
      xTimerStop( xTimer, 0 );
   }
   else
   {
      /* Сохранение увеличенного счетчика обратно в поле ID таймера,
         чтобы его можно было прочитать при следующем срабатывании
         таймера. */
      vTimerSetTimerID( xTimer, ( void * ) ulCount );
   }
}
 
void main (void)
{
   long x;
 
   /* При старте создается несколько таймеров. Запуск таймеров
      перед запуском планировщика RTOS будет означать, что таймеры
      начнут работать сразу после запуска планировщика. */
   for(x = 0; x < NUM_TIMERS; x++)
   {
      xTimers[x] = xTimerCreate(
                     "Timer", // это просто произвольный текст, который
                              // ядро RTOS не использует
                     (100 * x) + 100, // Время периода таймера в тиках,
                                      // которое должно быть > 0.
                     pdTRUE,  // Таймеры перезапустят себя автоматически,
                              // когда истечет период.
                     (void *)0, // ID таймера, используемый в качестве
                                // счетчика срабатываний, инициализируется
                                // нулем.
                     vTimerCallback   // Функция, запускаемая при
                                      // срабатывании таймера.
                   );
 
      if(xTimers[x] == NULL)
      {
         /* Таймер не был создан. */
      }
      else
      {
         /* Запуск таймера. Время блокировки не указано, и даже если бы оно
            было, то оно будет проигнорировано, потому что планировщик RTOS
            еще не запущен. */
         if(xTimerStart(xTimers[x], 0) != pdPASS)
         {
            /* Таймер не был установлен в состояние Active. */
         }
      }
   }
 
   /* ...
      Создайте здесь задачи приложения (tasks).
      ... */
 
   /* Запуск планировщика RTOS запустит таймеры, которые уже были установлены
      в активное состояние. */
   vTaskStartScheduler();
 
   /* До этого места выполнение кода никогда не дойдет. */
   for( ;; );
}

[Ссылки]

1. xTimerCreate site:freertos.org.
2. FreeRTOS: плюсы и минусы статического и динамического выделения памяти.
3FreeRTOS: программные таймеры.

 

Добавить комментарий


Защитный код
Обновить

Top of Page