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

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.
 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
 ## Functionality Overview
 
 
 * Two timers are configured
 * 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
 * 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:
 * 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.)
    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.
    CONDITIONS OF ANY KIND, either express or implied.
 */
 */
 #include <stdio.h>
 #include <stdio.h>
-#include "esp_types.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
 #include "freertos/task.h"
 #include "freertos/queue.h"
 #include "freertos/queue.h"
-#include "driver/periph_ctrl.h"
 #include "driver/timer.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_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 {
 typedef struct {
-    int type;  // the type of timer's event
     int timer_group;
     int timer_group;
     int timer_idx;
     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;
     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
  * 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)
 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));
            (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 */
     /* 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 */
     /* Select and initialize basic parameters of the timer */
     timer_config_t config = {
     timer_config_t config = {
@@ -111,39 +89,44 @@ static void example_tg0_timer_init(int timer_idx,
         .alarm_en = TIMER_ALARM_EN,
         .alarm_en = TIMER_ALARM_EN,
         .auto_reload = auto_reload,
         .auto_reload = auto_reload,
     }; // default clock source is APB
     }; // 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.
     /* Timer's counter will initially start from value below.
        Also, if auto_reload is set, this value will be automatically reload on alarm */
        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. */
     /* 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) {
     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 */
         /* 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 {
         } 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 */
         /* Print the timer values passed by event */
         printf("------- EVENT TIME --------\n");
         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 */
         /* Print the timer values as visible by this task */
         printf("-------- TASK TIME --------\n");
         printf("-------- TASK TIME --------\n");
         uint64_t task_counter_value;
         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);
         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);
-}