]> granicus.if.org Git - esp-idf/commitdiff
uart: add support for REF_TICK
authorIvan Grokhotkov <ivan@espressif.com>
Mon, 21 Aug 2017 14:30:23 +0000 (22:30 +0800)
committerIvan Grokhotkov <ivan@espressif.com>
Wed, 18 Oct 2017 06:19:20 +0000 (14:19 +0800)
components/driver/include/driver/uart.h
components/driver/uart.c
components/esp32/cpu_start.c
components/soc/esp32/include/soc/soc.h

index 6c17fd65665d3f6ed117e8821c2eb48e03fa2c98..a4227b3481725c0c65e4b8e6f0700064f12687fa 100644 (file)
@@ -106,7 +106,8 @@ typedef struct {
     uart_parity_t parity;               /*!< UART parity mode*/
     uart_stop_bits_t stop_bits;         /*!< UART stop bits*/
     uart_hw_flowcontrol_t flow_ctrl;    /*!< UART HW flow control mode (cts/rts)*/
-    uint8_t rx_flow_ctrl_thresh ;       /*!< UART HW RTS threshold*/
+    uint8_t rx_flow_ctrl_thresh;        /*!< UART HW RTS threshold*/
+    bool use_ref_tick;                  /*!< Set to true if UART should be clocked from REF_TICK */
 } uart_config_t;
 
 /**
index 1d4503e97ad66539e8bcdd935af04d65669fed5d..300a19ce8b3ad7d43814f32d180da797005e1ebd 100644 (file)
@@ -18,6 +18,7 @@
 #include "esp_intr_alloc.h"
 #include "esp_log.h"
 #include "esp_err.h"
+#include "esp_clk.h"
 #include "malloc.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/semphr.h"
@@ -172,13 +173,25 @@ esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode)
 esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baud_rate)
 {
     UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
-    UART_CHECK((baud_rate <= UART_BITRATE_MAX), "baud_rate error", ESP_FAIL);
-    uint32_t clk_div = (((UART_CLK_FREQ) << 4) / baud_rate);
+    esp_err_t ret = ESP_OK;
     UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
-    UART[uart_num]->clk_div.div_int = clk_div >> 4;
-    UART[uart_num]->clk_div.div_frag = clk_div & 0xf;
+    int uart_clk_freq;
+    if (UART[uart_num]->conf0.tick_ref_always_on == 0) {
+        /* this UART has been configured to use REF_TICK */
+        uart_clk_freq = REF_CLK_FREQ;
+    } else {
+        uart_clk_freq = esp_clk_apb_freq();
+    }
+    uint32_t clk_div = (((uart_clk_freq) << 4) / baud_rate);
+    if (clk_div < 16) {
+        /* baud rate is too high for this clock frequency */
+        ret = ESP_ERR_INVALID_ARG;
+    } else {
+        UART[uart_num]->clk_div.div_int = clk_div >> 4;
+        UART[uart_num]->clk_div.div_frag = clk_div & 0xf;
+    }
     UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
-    return ESP_OK;
+    return ret;
 }
 
 esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate)
@@ -468,17 +481,18 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf
     } else if(uart_num == UART_NUM_2) {
         periph_module_enable(PERIPH_UART2_MODULE);
     }
-    r=uart_set_hw_flow_ctrl(uart_num, uart_config->flow_ctrl, uart_config->rx_flow_ctrl_thresh);
-    if (r!=ESP_OK) return r;
-    r=uart_set_baudrate(uart_num, uart_config->baud_rate);
-    if (r!=ESP_OK) return r;
-
-    UART[uart_num]->conf0.val = (
-        (uart_config->parity << UART_PARITY_S)
-            | (uart_config->data_bits << UART_BIT_NUM_S)
-            | ((uart_config->flow_ctrl & UART_HW_FLOWCTRL_CTS) ? UART_TX_FLOW_EN : 0x0)
-            | UART_TICK_REF_ALWAYS_ON_M);
-    r=uart_set_stop_bits(uart_num, uart_config->stop_bits);
+    r = uart_set_hw_flow_ctrl(uart_num, uart_config->flow_ctrl, uart_config->rx_flow_ctrl_thresh);
+    if (r != ESP_OK) return r;
+
+    UART[uart_num]->conf0.val =
+          (uart_config->parity << UART_PARITY_S)
+        | (uart_config->data_bits << UART_BIT_NUM_S)
+        | ((uart_config->flow_ctrl & UART_HW_FLOWCTRL_CTS) ? UART_TX_FLOW_EN : 0x0)
+        | (uart_config->use_ref_tick ? 0 : UART_TICK_REF_ALWAYS_ON_M);
+
+    r = uart_set_baudrate(uart_num, uart_config->baud_rate);
+    if (r != ESP_OK) return r;
+    r = uart_set_stop_bits(uart_num, uart_config->stop_bits);
     return r;
 }
 
index 4a56143cfd11ea7df432b2b1b7e3e9e8027b65e4..c839c14dde3c3ecdaeb047dba9f0641a2d5678e9 100644 (file)
@@ -289,9 +289,18 @@ void start_cpu0_default(void)
     esp_clk_init();
     esp_perip_clk_init();
     intr_matrix_clear();
+
 #ifndef CONFIG_CONSOLE_UART_NONE
-    uart_div_modify(CONFIG_CONSOLE_UART_NUM, (rtc_clk_apb_freq_get() << 4) / CONFIG_CONSOLE_UART_BAUDRATE);
-#endif
+#ifdef CONFIG_PM_ENABLE
+    const int uart_clk_freq = REF_CLK_FREQ;
+    /* When DFS is enabled, use REFTICK as UART clock source */
+    CLEAR_PERI_REG_MASK(UART_CONF0_REG(CONFIG_CONSOLE_UART_NUM), UART_TICK_REF_ALWAYS_ON);
+#else
+    const int uart_clk_freq = APB_CLK_FREQ;
+#endif // CONFIG_PM_DFS_ENABLE
+    uart_div_modify(CONFIG_CONSOLE_UART_NUM, (uart_clk_freq << 4) / CONFIG_CONSOLE_UART_BAUDRATE);
+#endif // CONFIG_CONSOLE_UART_NONE
+
 #if CONFIG_BROWNOUT_DET
     esp_brownout_init();
 #endif
index 0e633821fdb6aa36cca330344d0bed38eb9d6208..d402262df937a35126d9051670bddf0d352a2662 100644 (file)
 #define  CPU_CLK_FREQ_ROM                            APB_CLK_FREQ_ROM
 #define  CPU_CLK_FREQ                                APB_CLK_FREQ
 #define  APB_CLK_FREQ                                ( 80*1000000 )       //unit: Hz
+#define  REF_CLK_FREQ                                ( 1000000 )
 #define  UART_CLK_FREQ                               APB_CLK_FREQ
 #define  WDT_CLK_FREQ                                APB_CLK_FREQ
 #define  TIMER_CLK_FREQ                              (80000000>>4) //80MHz divided by 16