uart_wakeup.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /*
  2. * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Unlicense OR CC0-1.0
  5. */
  6. #include "freertos/FreeRTOS.h"
  7. #include "freertos/task.h"
  8. #include "esp_check.h"
  9. #include "esp_sleep.h"
  10. #include "soc/uart_pins.h"
  11. #include "driver/uart.h"
  12. #include "driver/gpio.h"
  13. #include "sdkconfig.h"
  14. #define EXAMPLE_UART_NUM 0
  15. /* Notice that ESP32 has to use the iomux input to configure uart as wakeup source
  16. * Please use 'UxRXD_GPIO_NUM' as uart rx pin. No limitation to the other target */
  17. #define EXAMPLE_UART_TX_IO_NUM U0TXD_GPIO_NUM
  18. #define EXAMPLE_UART_RX_IO_NUM U0RXD_GPIO_NUM
  19. #define EXAMPLE_UART_WAKEUP_THRESHOLD 3
  20. #define EXAMPLE_READ_BUF_SIZE 1024
  21. #define EXAMPLE_UART_BUF_SIZE (EXAMPLE_READ_BUF_SIZE * 2)
  22. static const char *TAG = "uart_wakeup";
  23. static QueueHandle_t uart_evt_que = NULL;
  24. static void uart_wakeup_task(void *arg)
  25. {
  26. uart_event_t event;
  27. if (uart_evt_que == NULL) {
  28. ESP_LOGE(TAG, "uart_evt_que is NULL");
  29. abort();
  30. }
  31. uint8_t* dtmp = (uint8_t*) malloc(EXAMPLE_READ_BUF_SIZE);
  32. while(1) {
  33. // Waiting for UART event.
  34. if(xQueueReceive(uart_evt_que, (void * )&event, (TickType_t)portMAX_DELAY)) {
  35. ESP_LOGI(TAG, "uart%d recved event:%d", EXAMPLE_UART_NUM, event.type);
  36. switch(event.type) {
  37. case UART_DATA:
  38. ESP_LOGI(TAG, "[UART DATA]: %d", event.size);
  39. uart_read_bytes(EXAMPLE_UART_NUM, dtmp, event.size, portMAX_DELAY);
  40. ESP_LOGI(TAG, "[DATA EVT]:");
  41. uart_write_bytes(EXAMPLE_UART_NUM, (const char *)dtmp, event.size);
  42. break;
  43. // Event of HW FIFO overflow detected
  44. case UART_FIFO_OVF:
  45. ESP_LOGI(TAG, "hw fifo overflow");
  46. // If fifo overflow happened, you should consider adding flow control for your application.
  47. // The ISR has already reset the rx FIFO,
  48. // As an example, we directly flush the rx buffer here in order to read more data.
  49. uart_flush_input(EXAMPLE_UART_NUM);
  50. xQueueReset(uart_evt_que);
  51. break;
  52. // Event of UART ring buffer full
  53. case UART_BUFFER_FULL:
  54. ESP_LOGI(TAG, "ring buffer full");
  55. // If buffer full happened, you should consider encreasing your buffer size
  56. // As an example, we directly flush the rx buffer here in order to read more data.
  57. uart_flush_input(EXAMPLE_UART_NUM);
  58. xQueueReset(uart_evt_que);
  59. break;
  60. // Event of UART RX break detected
  61. case UART_BREAK:
  62. ESP_LOGI(TAG, "uart rx break");
  63. break;
  64. // Event of UART parity check error
  65. case UART_PARITY_ERR:
  66. ESP_LOGI(TAG, "uart parity error");
  67. break;
  68. // Event of UART frame error
  69. case UART_FRAME_ERR:
  70. ESP_LOGI(TAG, "uart frame error");
  71. break;
  72. // ESP32 can wakeup by uart but there is no wake up interrupt
  73. #if SOC_UART_SUPPORT_WAKEUP_INT
  74. // Event of waking up by UART
  75. case UART_WAKEUP:
  76. ESP_LOGI(TAG, "uart wakeup");
  77. break;
  78. #endif
  79. default:
  80. ESP_LOGI(TAG, "uart event type: %d", event.type);
  81. break;
  82. }
  83. }
  84. }
  85. free(dtmp);
  86. vTaskDelete(NULL);
  87. }
  88. static esp_err_t uart_initialization(void)
  89. {
  90. uart_config_t uart_cfg = {
  91. .baud_rate = CONFIG_ESP_CONSOLE_UART_BAUDRATE,
  92. .data_bits = UART_DATA_8_BITS,
  93. .parity = UART_PARITY_DISABLE,
  94. .stop_bits = UART_STOP_BITS_1,
  95. .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
  96. .source_clk = UART_SCLK_DEFAULT,
  97. };
  98. //Install UART driver, and get the queue.
  99. ESP_RETURN_ON_ERROR(uart_driver_install(EXAMPLE_UART_NUM, EXAMPLE_UART_BUF_SIZE, EXAMPLE_UART_BUF_SIZE, 20, &uart_evt_que, 0),
  100. TAG, "Install uart failed");
  101. if (EXAMPLE_UART_NUM == CONFIG_ESP_CONSOLE_UART_NUM) {
  102. /* temp fix for uart garbled output, can be removed when IDF-5683 done */
  103. ESP_RETURN_ON_ERROR(uart_wait_tx_idle_polling(EXAMPLE_UART_NUM), TAG, "Wait uart tx done failed");
  104. }
  105. ESP_RETURN_ON_ERROR(uart_param_config(EXAMPLE_UART_NUM, &uart_cfg), TAG, "Configure uart param failed");
  106. ESP_RETURN_ON_ERROR(uart_set_pin(EXAMPLE_UART_NUM, EXAMPLE_UART_TX_IO_NUM, EXAMPLE_UART_RX_IO_NUM, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE),
  107. TAG, "Configure uart gpio pins failed");
  108. return ESP_OK;
  109. }
  110. static esp_err_t uart_wakeup_config(void)
  111. {
  112. /* UART will wakeup the chip up from light sleep if the edges that RX pin received has reached the threshold
  113. * Besides, the Rx pin need extra configuration to enable it can work during light sleep */
  114. ESP_RETURN_ON_ERROR(gpio_sleep_set_direction(EXAMPLE_UART_RX_IO_NUM, GPIO_MODE_INPUT), TAG, "Set uart sleep gpio failed");
  115. ESP_RETURN_ON_ERROR(gpio_sleep_set_pull_mode(EXAMPLE_UART_RX_IO_NUM, GPIO_PULLUP_ONLY), TAG, "Set uart sleep gpio failed");
  116. ESP_RETURN_ON_ERROR(uart_set_wakeup_threshold(EXAMPLE_UART_NUM, EXAMPLE_UART_WAKEUP_THRESHOLD),
  117. TAG, "Set uart wakeup threshold failed");
  118. /* Only uart0 and uart1 (if has) support to be configured as wakeup source */
  119. ESP_RETURN_ON_ERROR(esp_sleep_enable_uart_wakeup(EXAMPLE_UART_NUM),
  120. TAG, "Configure uart as wakeup source failed");
  121. return ESP_OK;
  122. }
  123. esp_err_t example_register_uart_wakeup(void)
  124. {
  125. /* Initialize uart1 */
  126. ESP_RETURN_ON_ERROR(uart_initialization(), TAG, "Initialize uart%d failed", EXAMPLE_UART_NUM);
  127. /* Enable wakeup from uart */
  128. ESP_RETURN_ON_ERROR(uart_wakeup_config(), TAG, "Configure uart as wakeup source failed");
  129. xTaskCreate(uart_wakeup_task, "uart_wakeup_task", 4096, NULL, 5, NULL);
  130. ESP_LOGI(TAG, "uart wakeup source is ready");
  131. return ESP_OK;
  132. }