timer_group_example_main.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /* Timer group-hardware timer example
  2. This example code is in the Public Domain (or CC0 licensed, at your option.)
  3. Unless required by applicable law or agreed to in writing, this
  4. software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  5. CONDITIONS OF ANY KIND, either express or implied.
  6. */
  7. #include <stdio.h>
  8. #include "esp_types.h"
  9. #include "freertos/FreeRTOS.h"
  10. #include "freertos/task.h"
  11. #include "freertos/queue.h"
  12. #include "driver/periph_ctrl.h"
  13. #include "driver/timer.h"
  14. #define TIMER_DIVIDER 16 // Hardware timer clock divider
  15. #define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) // convert counter value to seconds
  16. #define TIMER_INTERVAL0_SEC (3.4179) // sample test interval for the first timer
  17. #define TIMER_INTERVAL1_SEC (5.78) // sample test interval for the second timer
  18. #define TEST_WITHOUT_RELOAD 0 // testing will be done without auto reload
  19. #define TEST_WITH_RELOAD 1 // testing will be done with auto reload
  20. /*
  21. * A sample structure to pass events
  22. * from the timer interrupt handler to the main program.
  23. */
  24. typedef struct {
  25. int type; // the type of timer's event
  26. int timer_group;
  27. int timer_idx;
  28. uint64_t timer_counter_value;
  29. } timer_event_t;
  30. xQueueHandle timer_queue;
  31. /*
  32. * A simple helper function to print the raw timer counter value
  33. * and the counter value converted to seconds
  34. */
  35. static void inline print_timer_counter(uint64_t counter_value)
  36. {
  37. printf("Counter: 0x%08x%08x\n", (uint32_t) (counter_value >> 32),
  38. (uint32_t) (counter_value));
  39. printf("Time : %.8f s\n", (double) counter_value / TIMER_SCALE);
  40. }
  41. /*
  42. * Timer group0 ISR handler
  43. *
  44. * Note:
  45. * We don't call the timer API here because they are not declared with IRAM_ATTR.
  46. * If we're okay with the timer irq not being serviced while SPI flash cache is disabled,
  47. * we can allocate this interrupt without the ESP_INTR_FLAG_IRAM flag and use the normal API.
  48. */
  49. void IRAM_ATTR timer_group0_isr(void *para)
  50. {
  51. timer_spinlock_take(TIMER_GROUP_0);
  52. int timer_idx = (int) para;
  53. /* Retrieve the interrupt status and the counter value
  54. from the timer that reported the interrupt */
  55. uint32_t timer_intr = timer_group_get_intr_status_in_isr(TIMER_GROUP_0);
  56. uint64_t timer_counter_value = timer_group_get_counter_value_in_isr(TIMER_GROUP_0, timer_idx);
  57. /* Prepare basic event data
  58. that will be then sent back to the main program task */
  59. timer_event_t evt;
  60. evt.timer_group = 0;
  61. evt.timer_idx = timer_idx;
  62. evt.timer_counter_value = timer_counter_value;
  63. /* Clear the interrupt
  64. and update the alarm time for the timer with without reload */
  65. if (timer_intr & TIMER_INTR_T0) {
  66. evt.type = TEST_WITHOUT_RELOAD;
  67. timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0);
  68. timer_counter_value += (uint64_t) (TIMER_INTERVAL0_SEC * TIMER_SCALE);
  69. timer_group_set_alarm_value_in_isr(TIMER_GROUP_0, timer_idx, timer_counter_value);
  70. } else if (timer_intr & TIMER_INTR_T1) {
  71. evt.type = TEST_WITH_RELOAD;
  72. timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_1);
  73. } else {
  74. evt.type = -1; // not supported even type
  75. }
  76. /* After the alarm has been triggered
  77. we need enable it again, so it is triggered the next time */
  78. timer_group_enable_alarm_in_isr(TIMER_GROUP_0, timer_idx);
  79. /* Now just send the event data back to the main program task */
  80. xQueueSendFromISR(timer_queue, &evt, NULL);
  81. timer_spinlock_give(TIMER_GROUP_0);
  82. }
  83. /*
  84. * Initialize selected timer of the timer group 0
  85. *
  86. * timer_idx - the timer number to initialize
  87. * auto_reload - should the timer auto reload on alarm?
  88. * timer_interval_sec - the interval of alarm to set
  89. */
  90. static void example_tg0_timer_init(int timer_idx,
  91. bool auto_reload, double timer_interval_sec)
  92. {
  93. /* Select and initialize basic parameters of the timer */
  94. timer_config_t config = {
  95. .divider = TIMER_DIVIDER,
  96. .counter_dir = TIMER_COUNT_UP,
  97. .counter_en = TIMER_PAUSE,
  98. .alarm_en = TIMER_ALARM_EN,
  99. .auto_reload = auto_reload,
  100. }; // default clock source is APB
  101. timer_init(TIMER_GROUP_0, timer_idx, &config);
  102. /* Timer's counter will initially start from value below.
  103. Also, if auto_reload is set, this value will be automatically reload on alarm */
  104. timer_set_counter_value(TIMER_GROUP_0, timer_idx, 0x00000000ULL);
  105. /* Configure the alarm value and the interrupt on alarm. */
  106. timer_set_alarm_value(TIMER_GROUP_0, timer_idx, timer_interval_sec * TIMER_SCALE);
  107. timer_enable_intr(TIMER_GROUP_0, timer_idx);
  108. timer_isr_register(TIMER_GROUP_0, timer_idx, timer_group0_isr,
  109. (void *) timer_idx, ESP_INTR_FLAG_IRAM, NULL);
  110. timer_start(TIMER_GROUP_0, timer_idx);
  111. }
  112. /*
  113. * The main task of this example program
  114. */
  115. static void timer_example_evt_task(void *arg)
  116. {
  117. while (1) {
  118. timer_event_t evt;
  119. xQueueReceive(timer_queue, &evt, portMAX_DELAY);
  120. /* Print information that the timer reported an event */
  121. if (evt.type == TEST_WITHOUT_RELOAD) {
  122. printf("\n Example timer without reload\n");
  123. } else if (evt.type == TEST_WITH_RELOAD) {
  124. printf("\n Example timer with auto reload\n");
  125. } else {
  126. printf("\n UNKNOWN EVENT TYPE\n");
  127. }
  128. printf("Group[%d], timer[%d] alarm event\n", evt.timer_group, evt.timer_idx);
  129. /* Print the timer values passed by event */
  130. printf("------- EVENT TIME --------\n");
  131. print_timer_counter(evt.timer_counter_value);
  132. /* Print the timer values as visible by this task */
  133. printf("-------- TASK TIME --------\n");
  134. uint64_t task_counter_value;
  135. timer_get_counter_value(evt.timer_group, evt.timer_idx, &task_counter_value);
  136. print_timer_counter(task_counter_value);
  137. }
  138. }
  139. /*
  140. * In this example, we will test hardware timer0 and timer1 of timer group0.
  141. */
  142. void app_main(void)
  143. {
  144. timer_queue = xQueueCreate(10, sizeof(timer_event_t));
  145. example_tg0_timer_init(TIMER_0, TEST_WITHOUT_RELOAD, TIMER_INTERVAL0_SEC);
  146. example_tg0_timer_init(TIMER_1, TEST_WITH_RELOAD, TIMER_INTERVAL1_SEC);
  147. xTaskCreate(timer_example_evt_task, "timer_evt_task", 2048, NULL, 5, NULL);
  148. }