timer_group_example_main.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /*
  2. * SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: CC0-1.0
  5. */
  6. #include <stdio.h>
  7. #include "freertos/FreeRTOS.h"
  8. #include "freertos/task.h"
  9. #include "freertos/queue.h"
  10. #include "driver/timer.h"
  11. #include "esp_log.h"
  12. #define TIMER_RESOLUTION_HZ 1000000 // 1MHz resolution
  13. #define TIMER_ALARM_PERIOD_S 0.5 // Alarm period 0.5s
  14. static const char *TAG = "example";
  15. /**
  16. * @brief A sample structure to pass events from the timer ISR to task
  17. */
  18. typedef struct {
  19. uint64_t timer_count_value;
  20. } example_timer_event_t;
  21. /**
  22. * @brief Timer user data, will be pass to timer alarm callback
  23. */
  24. typedef struct {
  25. xQueueHandle user_queue;
  26. int timer_group;
  27. int timer_idx;
  28. int alarm_value;
  29. bool auto_reload;
  30. } example_timer_user_data_t;
  31. static bool IRAM_ATTR timer_group_isr_callback(void *args)
  32. {
  33. BaseType_t high_task_awoken = pdFALSE;
  34. example_timer_user_data_t *user_data = (example_timer_user_data_t *) args;
  35. // fetch current count value
  36. uint64_t timer_count_value = timer_group_get_counter_value_in_isr(user_data->timer_group, user_data->timer_idx);
  37. example_timer_event_t evt = {
  38. .timer_count_value = timer_count_value,
  39. };
  40. // set new alarm value if necessary
  41. if (!user_data->auto_reload) {
  42. user_data->alarm_value += TIMER_ALARM_PERIOD_S * TIMER_RESOLUTION_HZ;
  43. timer_group_set_alarm_value_in_isr(user_data->timer_group, user_data->timer_idx, user_data->alarm_value);
  44. }
  45. // Send the event data back to the main program task
  46. xQueueSendFromISR(user_data->user_queue, &evt, &high_task_awoken);
  47. return high_task_awoken == pdTRUE; // return whether a task switch is needed
  48. }
  49. static void example_tg_timer_init(example_timer_user_data_t *user_data)
  50. {
  51. int group = user_data->timer_group;
  52. int timer = user_data->timer_idx;
  53. timer_config_t config = {
  54. .clk_src = TIMER_SRC_CLK_APB,
  55. .divider = APB_CLK_FREQ / TIMER_RESOLUTION_HZ,
  56. .counter_dir = TIMER_COUNT_UP,
  57. .counter_en = TIMER_PAUSE,
  58. .alarm_en = TIMER_ALARM_EN,
  59. .auto_reload = user_data->auto_reload,
  60. };
  61. ESP_ERROR_CHECK(timer_init(group, timer, &config));
  62. // For the timer counter to a initial value
  63. ESP_ERROR_CHECK(timer_set_counter_value(group, timer, 0));
  64. // Set alarm value and enable alarm interrupt
  65. ESP_ERROR_CHECK(timer_set_alarm_value(group, timer, user_data->alarm_value));
  66. ESP_ERROR_CHECK(timer_enable_intr(group, timer));
  67. // Hook interrupt callback
  68. ESP_ERROR_CHECK(timer_isr_callback_add(group, timer, timer_group_isr_callback, user_data, 0));
  69. // Start timer
  70. ESP_ERROR_CHECK(timer_start(group, timer));
  71. }
  72. static void example_tg_timer_deinit(int group, int timer)
  73. {
  74. ESP_ERROR_CHECK(timer_isr_callback_remove(group, timer));
  75. ESP_ERROR_CHECK(timer_deinit(group, timer));
  76. }
  77. void app_main(void)
  78. {
  79. example_timer_user_data_t *user_data = calloc(1, sizeof(example_timer_user_data_t));
  80. assert(user_data);
  81. user_data->user_queue = xQueueCreate(10, sizeof(example_timer_event_t));
  82. assert(user_data->user_queue);
  83. user_data->timer_group = 0;
  84. user_data->timer_idx = 0;
  85. user_data->alarm_value = TIMER_ALARM_PERIOD_S * TIMER_RESOLUTION_HZ;
  86. ESP_LOGI(TAG, "Init timer with auto-reload");
  87. user_data->auto_reload = true;
  88. example_tg_timer_init(user_data);
  89. example_timer_event_t evt;
  90. uint32_t test_count = 4;
  91. while (test_count--) {
  92. xQueueReceive(user_data->user_queue, &evt, portMAX_DELAY);
  93. ESP_LOGI(TAG, "Timer auto reloaded, count value in ISR: %llu", evt.timer_count_value);
  94. }
  95. example_tg_timer_deinit(user_data->timer_group, user_data->timer_idx);
  96. ESP_LOGI(TAG, "Init timer without auto-reload");
  97. user_data->auto_reload = false;
  98. example_tg_timer_init(user_data);
  99. test_count = 4;
  100. while (test_count--) {
  101. xQueueReceive(user_data->user_queue, &evt, portMAX_DELAY);
  102. ESP_LOGI(TAG, "Timer alarmed at %llu", evt.timer_count_value);
  103. }
  104. example_tg_timer_deinit(user_data->timer_group, user_data->timer_idx);
  105. vQueueDelete(user_data->user_queue);
  106. free(user_data);
  107. }