Просмотр исходного кода

timer_group: using isr callback in example

morris 5 лет назад
Родитель
Сommit
face9518b2

+ 47 - 23
examples/peripherals/timer_group/README.md

@@ -1,10 +1,51 @@
-| Supported Targets | ESP32 |
-| ----------------- | ----- |
-
-# Example: timer_group
+# Example: General Purpose Timer
 
 This example uses the timer group driver to generate timer interrupts at two specified alarm intervals.
 
+## How to Use Example
+
+### Hardware Required
+
+* A development board with ESP SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.)
+* A USB cable for Power supply and programming
+
+### Build and Flash
+
+Run `idf.py -p PORT flash monitor` to build, flash and monitor the project.
+
+(To exit the serial monitor, type ``Ctrl-]``.)
+
+See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
+
+## Example Output
+
+```
+Timer Group with auto reload
+Group[0], timer[0] alarm event
+------- EVENT TIME --------
+Counter: 0x0000000000000008
+Time   : 0.00000160 s
+-------- TASK TIME --------
+Counter: 0x0000000000004ed8
+Time   : 0.00403680 s
+Timer Group without auto reload
+Group[1], timer[0] alarm event
+------- EVENT TIME --------
+Counter: 0x00000000017d7848
+Time   : 5.00000160 s
+-------- TASK TIME --------
+Counter: 0x00000000017dcb32
+Time   : 5.00424680 s
+Timer Group with auto reload
+Group[0], timer[0] alarm event
+------- EVENT TIME --------
+Counter: 0x0000000000000008
+Time   : 0.00000160 s
+-------- TASK TIME --------
+Counter: 0x0000000000004dd4
+Time   : 0.00398480 s
+```
+
 ## Functionality Overview
 
 * Two timers are configured
@@ -14,23 +55,6 @@ This example uses the timer group driver to generate timer interrupts at two spe
 * The other timer is configured to keep incrementing and is reloaded by the application each time the alarm happens
 * Alarms trigger subsequent interrupts, that is tracked with messages printed on the terminal:
 
-```
-    Example timer with auto reload
-Group[0], timer[1] alarm event
-------- EVENT TIME --------
-Counter: 0x000000000000000a
-Time   : 0.00000200 s
--------- TASK TIME --------
-Counter: 0x00000000000107ff
-Time   : 0.01351660 s
-
-    Example timer without reload
-Group[0], timer[0] alarm event
-------- EVENT TIME --------
-Counter: 0x00000000092ae316
-Time   : 30.76111800 s
--------- TASK TIME --------
-Counter: 0x00000000092bd535
-Time   : 30.77351460 s
+## Troubleshooting
 
-```
+For any technical queries, please open an [issue] (https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.

+ 69 - 97
examples/peripherals/timer_group/main/timer_group_example_main.c

@@ -1,4 +1,4 @@
-/* Timer group-hardware timer example
+/* General Purpose Timer example
 
    This example code is in the Public Domain (or CC0 licensed, at your option.)
 
@@ -7,32 +7,31 @@
    CONDITIONS OF ANY KIND, either express or implied.
 */
 #include <stdio.h>
-#include "esp_types.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
 #include "freertos/queue.h"
-#include "driver/periph_ctrl.h"
 #include "driver/timer.h"
 
-#define TIMER_DIVIDER         16  //  Hardware timer clock divider
+#define TIMER_DIVIDER         (16)  //  Hardware timer clock divider
 #define TIMER_SCALE           (TIMER_BASE_CLK / TIMER_DIVIDER)  // convert counter value to seconds
-#define TIMER_INTERVAL0_SEC   (3.4179) // sample test interval for the first timer
-#define TIMER_INTERVAL1_SEC   (5.78)   // sample test interval for the second timer
-#define TEST_WITHOUT_RELOAD   0        // testing will be done without auto reload
-#define TEST_WITH_RELOAD      1        // testing will be done with auto reload
 
-/*
- * A sample structure to pass events
- * from the timer interrupt handler to the main program.
- */
 typedef struct {
-    int type;  // the type of timer's event
     int timer_group;
     int timer_idx;
+    int alarm_interval;
+    bool auto_reload;
+} example_timer_info_t;
+
+/**
+ * @brief A sample structure to pass events from the timer ISR to task
+ *
+ */
+typedef struct {
+    example_timer_info_t info;
     uint64_t timer_counter_value;
-} timer_event_t;
+} example_timer_event_t;
 
-xQueueHandle timer_queue;
+static xQueueHandle s_timer_queue;
 
 /*
  * A simple helper function to print the raw timer counter value
@@ -40,68 +39,47 @@ xQueueHandle timer_queue;
  */
 static void inline print_timer_counter(uint64_t counter_value)
 {
-    printf("Counter: 0x%08x%08x\n", (uint32_t) (counter_value >> 32),
+    printf("Counter: 0x%08x%08x\r\n", (uint32_t) (counter_value >> 32),
            (uint32_t) (counter_value));
-    printf("Time   : %.8f s\n", (double) counter_value / TIMER_SCALE);
+    printf("Time   : %.8f s\r\n", (double) counter_value / TIMER_SCALE);
 }
 
-/*
- * Timer group0 ISR handler
- *
- * Note:
- * We don't call the timer API here because they are not declared with IRAM_ATTR.
- * If we're okay with the timer irq not being serviced while SPI flash cache is disabled,
- * we can allocate this interrupt without the ESP_INTR_FLAG_IRAM flag and use the normal API.
- */
-void IRAM_ATTR timer_group0_isr(void *para)
+static bool IRAM_ATTR timer_group_isr_callback(void *args)
 {
-    timer_spinlock_take(TIMER_GROUP_0);
-    int timer_idx = (int) para;
-
-    /* Retrieve the interrupt status and the counter value
-       from the timer that reported the interrupt */
-    uint32_t timer_intr = timer_group_get_intr_status_in_isr(TIMER_GROUP_0);
-    uint64_t timer_counter_value = timer_group_get_counter_value_in_isr(TIMER_GROUP_0, timer_idx);
-
-    /* Prepare basic event data
-       that will be then sent back to the main program task */
-    timer_event_t evt;
-    evt.timer_group = 0;
-    evt.timer_idx = timer_idx;
-    evt.timer_counter_value = timer_counter_value;
-
-    /* Clear the interrupt
-       and update the alarm time for the timer with without reload */
-    if (timer_intr & TIMER_INTR_T0) {
-        evt.type = TEST_WITHOUT_RELOAD;
-        timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0);
-        timer_counter_value += (uint64_t) (TIMER_INTERVAL0_SEC * TIMER_SCALE);
-        timer_group_set_alarm_value_in_isr(TIMER_GROUP_0, timer_idx, timer_counter_value);
-    } else if (timer_intr & TIMER_INTR_T1) {
-        evt.type = TEST_WITH_RELOAD;
-        timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_1);
-    } else {
-        evt.type = -1; // not supported even type
+    BaseType_t high_task_awoken = pdFALSE;
+    example_timer_info_t *info = (example_timer_info_t *) args;
+
+    uint64_t timer_counter_value = timer_group_get_counter_value_in_isr(info->timer_group, info->timer_idx);
+
+    /* Prepare basic event data that will be then sent back to task */
+    example_timer_event_t evt = {
+        .info.timer_group = info->timer_group,
+        .info.timer_idx = info->timer_idx,
+        .info.auto_reload = info->auto_reload,
+        .info.alarm_interval = info->alarm_interval,
+        .timer_counter_value = timer_counter_value
+    };
+
+    if (!info->auto_reload) {
+        timer_counter_value += info->alarm_interval * TIMER_SCALE;
+        timer_group_set_alarm_value_in_isr(info->timer_group, info->timer_idx, timer_counter_value);
     }
 
-    /* After the alarm has been triggered
-      we need enable it again, so it is triggered the next time */
-    timer_group_enable_alarm_in_isr(TIMER_GROUP_0, timer_idx);
-
     /* Now just send the event data back to the main program task */
-    xQueueSendFromISR(timer_queue, &evt, NULL);
-    timer_spinlock_give(TIMER_GROUP_0);
+    xQueueSendFromISR(s_timer_queue, &evt, &high_task_awoken);
+
+    return high_task_awoken == pdTRUE; // return whether we need to yield at the end of ISR
 }
 
-/*
- * Initialize selected timer of the timer group 0
+/**
+ * @brief Initialize selected timer of timer group
  *
- * timer_idx - the timer number to initialize
- * auto_reload - should the timer auto reload on alarm?
- * timer_interval_sec - the interval of alarm to set
+ * @param group Timer Group number, index from 0
+ * @param timer timer ID, index from 0
+ * @param auto_reload whether auto-reload on alarm event
+ * @param timer_interval_sec interval of alarm
  */
-static void example_tg0_timer_init(int timer_idx,
-                                   bool auto_reload, double timer_interval_sec)
+static void example_tg_timer_init(int group, int timer, bool auto_reload, int timer_interval_sec)
 {
     /* Select and initialize basic parameters of the timer */
     timer_config_t config = {
@@ -111,39 +89,44 @@ static void example_tg0_timer_init(int timer_idx,
         .alarm_en = TIMER_ALARM_EN,
         .auto_reload = auto_reload,
     }; // default clock source is APB
-    timer_init(TIMER_GROUP_0, timer_idx, &config);
+    timer_init(group, timer, &config);
 
     /* Timer's counter will initially start from value below.
        Also, if auto_reload is set, this value will be automatically reload on alarm */
-    timer_set_counter_value(TIMER_GROUP_0, timer_idx, 0x00000000ULL);
+    timer_set_counter_value(group, timer, 0);
 
     /* Configure the alarm value and the interrupt on alarm. */
-    timer_set_alarm_value(TIMER_GROUP_0, timer_idx, timer_interval_sec * TIMER_SCALE);
-    timer_enable_intr(TIMER_GROUP_0, timer_idx);
-    timer_isr_register(TIMER_GROUP_0, timer_idx, timer_group0_isr,
-                       (void *) timer_idx, ESP_INTR_FLAG_IRAM, NULL);
+    timer_set_alarm_value(group, timer, timer_interval_sec * TIMER_SCALE);
+    timer_enable_intr(group, timer);
 
-    timer_start(TIMER_GROUP_0, timer_idx);
+    example_timer_info_t *timer_info = calloc(1, sizeof(example_timer_info_t));
+    timer_info->timer_group = group;
+    timer_info->timer_idx = timer;
+    timer_info->auto_reload = auto_reload;
+    timer_info->alarm_interval = timer_interval_sec;
+    timer_isr_callback_add(group, timer, timer_group_isr_callback, timer_info, 0);
+
+    timer_start(group, timer);
 }
 
-/*
- * The main task of this example program
- */
-static void timer_example_evt_task(void *arg)
+void app_main(void)
 {
+    s_timer_queue = xQueueCreate(10, sizeof(example_timer_event_t));
+
+    example_tg_timer_init(TIMER_GROUP_0, TIMER_0, true, 3);
+    example_tg_timer_init(TIMER_GROUP_1, TIMER_0, false, 5);
+
     while (1) {
-        timer_event_t evt;
-        xQueueReceive(timer_queue, &evt, portMAX_DELAY);
+        example_timer_event_t evt;
+        xQueueReceive(s_timer_queue, &evt, portMAX_DELAY);
 
         /* Print information that the timer reported an event */
-        if (evt.type == TEST_WITHOUT_RELOAD) {
-            printf("\n    Example timer without reload\n");
-        } else if (evt.type == TEST_WITH_RELOAD) {
-            printf("\n    Example timer with auto reload\n");
+        if (evt.info.auto_reload) {
+            printf("Timer Group with auto reload\n");
         } else {
-            printf("\n    UNKNOWN EVENT TYPE\n");
+            printf("Timer Group without auto reload\n");
         }
-        printf("Group[%d], timer[%d] alarm event\n", evt.timer_group, evt.timer_idx);
+        printf("Group[%d], timer[%d] alarm event\n", evt.info.timer_group, evt.info.timer_idx);
 
         /* Print the timer values passed by event */
         printf("------- EVENT TIME --------\n");
@@ -152,18 +135,7 @@ static void timer_example_evt_task(void *arg)
         /* Print the timer values as visible by this task */
         printf("-------- TASK TIME --------\n");
         uint64_t task_counter_value;
-        timer_get_counter_value(evt.timer_group, evt.timer_idx, &task_counter_value);
+        timer_get_counter_value(evt.info.timer_group, evt.info.timer_idx, &task_counter_value);
         print_timer_counter(task_counter_value);
     }
 }
-
-/*
- * In this example, we will test hardware timer0 and timer1 of timer group0.
- */
-void app_main(void)
-{
-    timer_queue = xQueueCreate(10, sizeof(timer_event_t));
-    example_tg0_timer_init(TIMER_0, TEST_WITHOUT_RELOAD, TIMER_INTERVAL0_SEC);
-    example_tg0_timer_init(TIMER_1, TEST_WITH_RELOAD,    TIMER_INTERVAL1_SEC);
-    xTaskCreate(timer_example_evt_task, "timer_evt_task", 2048, NULL, 5, NULL);
-}