1 /*
2  * Copyright (c) 2006-2022, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2022-08-04     tangzz98     first version
9  *
10  */
11 
12 #include <rtthread.h>
13 #include <rtdevice.h>
14 #include "driver/uart.h"
15 #include "hal/uart_hal.h"
16 #include "sdkconfig.h"
17 
18 #ifdef RT_USING_SERIAL_V1
19 
20 #ifdef CONFIG_UART_ISR_IN_IRAM
21 #define UART_ISR_ATTR     IRAM_ATTR
22 #else
23 #define UART_ISR_ATTR
24 #endif
25 
26 uart_hal_context_t hal[] = {
27     {
28         .dev = &UART0,
29     },
30     {
31         .dev = &UART1,
32     },
33 };
34 
35 static struct rt_serial_device _serial;
36 
mcu_uart_rx_intr_handler(void * param)37 static void mcu_uart_rx_intr_handler(void *param)
38 {
39     uint32_t uart_intr_status;
40     struct rt_serial_device *serial;
41     uart_port_t port;
42     rt_interrupt_enter();
43     serial = (struct rt_serial_device *)param;
44     port = (uart_port_t)serial->parent.user_data;
45     uart_intr_status = uart_hal_get_intsts_mask(&hal[port]);
46     if (uart_intr_status != 0)
47     {
48         if (uart_intr_status & UART_INTR_RXFIFO_FULL)
49         {
50             rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
51         }
52         uart_hal_clr_intsts_mask(&hal[port], uart_intr_status);
53     }
54     rt_interrupt_leave();
55 }
56 
mcu_uart_configure(struct rt_serial_device * serial,struct serial_configure * cfg)57 static rt_err_t mcu_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
58 {
59     return RT_EOK;
60 }
61 
mcu_uart_control(struct rt_serial_device * serial,int cmd,void * arg)62 static rt_err_t mcu_uart_control(struct rt_serial_device *serial, int cmd, void *arg)
63 {
64     return RT_EOK;
65 }
66 
mcu_uart_putc(struct rt_serial_device * serial,char c)67 static int mcu_uart_putc(struct rt_serial_device *serial, char c)
68 {
69     uart_port_t port = (uart_port_t)serial->parent.user_data;
70     uint32_t write_size = 0;
71     do
72     {
73         uart_hal_write_txfifo(&hal[port], (const uint8_t *)&c, 1, &write_size);
74     } while (write_size == 0);
75 
76     return 1;
77 }
78 
mcu_uart_getc(struct rt_serial_device * serial)79 static int mcu_uart_getc(struct rt_serial_device *serial)
80 {
81     uart_port_t port = (uart_port_t)serial->parent.user_data;
82     uint8_t c;
83     int len = uart_hal_get_rxfifo_len(&hal[port]);
84     if (len == 0)
85     {
86         return -1;
87     }
88     else
89     {
90         len = 1;
91         uart_hal_read_rxfifo(&hal[port], &c, &len);
92         return (int)c;
93     }
94 }
95 
96 static const struct rt_uart_ops _uart_ops =
97 {
98     mcu_uart_configure,
99     mcu_uart_control,
100     mcu_uart_putc,
101     mcu_uart_getc,
102     RT_NULL,
103 };
104 
rt_hw_uart_init(void)105 int rt_hw_uart_init(void)
106 {
107     uart_intr_config_t uart_intr = {
108         .intr_enable_mask = UART_INTR_RXFIFO_FULL,
109         .rxfifo_full_thresh = 1,
110     };
111     struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
112     uart_config_t uart_config = {
113         .baud_rate = BAUD_RATE_115200,
114         .data_bits = UART_DATA_8_BITS,
115         .parity    = UART_PARITY_DISABLE,
116         .stop_bits = UART_STOP_BITS_1,
117         .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
118         .source_clk = UART_SCLK_APB,
119     };
120     int intr_alloc_flags = 0;
121 
122 #if CONFIG_UART_ISR_IN_IRAM
123     intr_alloc_flags = ESP_INTR_FLAG_IRAM;
124 #endif
125 
126     ESP_ERROR_CHECK(uart_param_config(RT_BSP_UART_PORT, &uart_config));
127     ESP_ERROR_CHECK(uart_set_pin(RT_BSP_UART_PORT, RT_BSP_UART_TX_PIN, RT_BSP_UART_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
128     ESP_ERROR_CHECK(esp_intr_alloc(uart_periph_signal[RT_BSP_UART_PORT].irq, intr_alloc_flags, mcu_uart_rx_intr_handler, (void *)&_serial, NULL));
129     ESP_ERROR_CHECK(uart_intr_config(RT_BSP_UART_PORT, &uart_intr));
130     _serial.ops = &_uart_ops;
131     _serial.config = config;
132 
133     return rt_hw_serial_register(&_serial, "uart", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, (void *)RT_BSP_UART_PORT);
134 }
135 INIT_BOARD_EXPORT(rt_hw_uart_init);
136 
137 #endif /* RT_USING_SERIAL_V1 */
138