1 /*
2  * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 // The LL layer for UART register operations.
8 // Note that most of the register operations in this layer are non-atomic operations.
9 
10 
11 #pragma once
12 
13 #include <stdlib.h>
14 #include "hal/misc.h"
15 #include "hal/uart_types.h"
16 #include "soc/uart_reg.h"
17 #include "soc/uart_struct.h"
18 #include "soc/system_reg.h"
19 #include "soc/dport_reg.h"
20 #include "esp_attr.h"
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 // The default fifo depth
27 #define UART_LL_FIFO_DEF_LEN  (SOC_UART_FIFO_LEN)
28 // Get UART hardware instance with giving uart num
29 #define UART_LL_GET_HW(num) (((num) == 0) ? (&UART0) : (&UART1))
30 
31 #define UART_LL_MIN_WAKEUP_THRESH (3)
32 #define UART_LL_INTR_MASK         (0x7ffff) //All interrupt mask
33 
34 // Define UART interrupts
35 typedef enum {
36     UART_INTR_RXFIFO_FULL      = (0x1<<0),
37     UART_INTR_TXFIFO_EMPTY     = (0x1<<1),
38     UART_INTR_PARITY_ERR       = (0x1<<2),
39     UART_INTR_FRAM_ERR         = (0x1<<3),
40     UART_INTR_RXFIFO_OVF       = (0x1<<4),
41     UART_INTR_DSR_CHG          = (0x1<<5),
42     UART_INTR_CTS_CHG          = (0x1<<6),
43     UART_INTR_BRK_DET          = (0x1<<7),
44     UART_INTR_RXFIFO_TOUT      = (0x1<<8),
45     UART_INTR_SW_XON           = (0x1<<9),
46     UART_INTR_SW_XOFF          = (0x1<<10),
47     UART_INTR_GLITCH_DET       = (0x1<<11),
48     UART_INTR_TX_BRK_DONE      = (0x1<<12),
49     UART_INTR_TX_BRK_IDLE      = (0x1<<13),
50     UART_INTR_TX_DONE          = (0x1<<14),
51     UART_INTR_RS485_PARITY_ERR = (0x1<<15),
52     UART_INTR_RS485_FRM_ERR    = (0x1<<16),
53     UART_INTR_RS485_CLASH      = (0x1<<17),
54     UART_INTR_CMD_CHAR_DET     = (0x1<<18),
55     UART_INTR_WAKEUP           = (0x1 << 19),
56 } uart_intr_t;
57 
58 /**
59  * @brief Check if UART is enabled or disabled.
60  *
61  * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
62  *
63  * @return true: enabled; false: disabled
64  */
uart_ll_is_enabled(uint32_t uart_num)65 FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num)
66 {
67     uint32_t uart_rst_bit = ((uart_num == 0) ? DPORT_UART_RST :
68                             (uart_num == 1) ? DPORT_UART1_RST : 0);
69     uint32_t uart_en_bit  = ((uart_num == 0) ? DPORT_UART_CLK_EN :
70                             (uart_num == 1) ? DPORT_UART1_CLK_EN : 0);
71     return DPORT_REG_GET_BIT(DPORT_PERIP_RST_EN_REG, uart_rst_bit) == 0 &&
72         DPORT_REG_GET_BIT(DPORT_PERIP_CLK_EN_REG, uart_en_bit) != 0;
73 }
74 
75 /**
76  * @brief  Set the UART source clock.
77  *
78  * @param  hw Beginning address of the peripheral registers.
79  * @param  source_clk The UART source clock. The source clock can be APB clock or REF_TICK.
80  *                    If the source clock is REF_TICK, the UART can still work when the APB changes.
81  *
82  * @return None.
83  */
uart_ll_set_sclk(uart_dev_t * hw,uart_sclk_t source_clk)84 FORCE_INLINE_ATTR void uart_ll_set_sclk(uart_dev_t *hw, uart_sclk_t source_clk)
85 {
86     hw->conf0.tick_ref_always_on = (source_clk == UART_SCLK_APB) ? 1 : 0;
87 }
88 
89 /**
90  * @brief  Get the UART source clock type.
91  *
92  * @param  hw Beginning address of the peripheral registers.
93  * @param  source_clk The pointer to accept the UART source clock type.
94  *
95  * @return None.
96  */
uart_ll_get_sclk(uart_dev_t * hw,uart_sclk_t * source_clk)97 FORCE_INLINE_ATTR void uart_ll_get_sclk(uart_dev_t *hw, uart_sclk_t* source_clk)
98 {
99     *source_clk = hw->conf0.tick_ref_always_on ? UART_SCLK_APB : UART_SCLK_REF_TICK;
100 }
101 
102 /**
103  * @brief  Configure the baud-rate.
104  *
105  * @param  hw Beginning address of the peripheral registers.
106  * @param  baud The baud rate to be set. When the source clock is APB, the max baud rate is `UART_LL_BITRATE_MAX`
107  * @param  sclk_freq Frequency of the clock source of UART, in Hz.
108 
109  * @return None
110  */
uart_ll_set_baudrate(uart_dev_t * hw,uint32_t baud,uint32_t sclk_freq)111 FORCE_INLINE_ATTR void uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud, uint32_t sclk_freq)
112 {
113     uint32_t clk_div;
114 
115     clk_div = ((sclk_freq) << 4) / baud;
116     // The baud rate configuration register is divided into
117     // an integer part and a fractional part.
118     hw->clk_div.div_int = clk_div >> 4;
119     hw->clk_div.div_frag = clk_div &  0xf;
120 }
121 
122 /**
123  * @brief  Get the current baud-rate.
124  *
125  * @param  hw Beginning address of the peripheral registers.
126  * @param  sclk_freq Frequency of the clock source of UART, in Hz.
127  *
128  * @return The current baudrate
129  */
uart_ll_get_baudrate(uart_dev_t * hw,uint32_t sclk_freq)130 FORCE_INLINE_ATTR uint32_t uart_ll_get_baudrate(uart_dev_t *hw, uint32_t sclk_freq)
131 {
132     typeof(hw->clk_div) div_reg;
133     div_reg.val = hw->clk_div.val;
134     return ((sclk_freq << 4)) / ((div_reg.div_int << 4) | div_reg.div_frag);
135 }
136 
137 /**
138  * @brief  Enable the UART interrupt based on the given mask.
139  *
140  * @param  hw Beginning address of the peripheral registers.
141  * @param  mask The bitmap of the interrupts need to be enabled.
142  *
143  * @return None
144  */
uart_ll_ena_intr_mask(uart_dev_t * hw,uint32_t mask)145 FORCE_INLINE_ATTR void uart_ll_ena_intr_mask(uart_dev_t *hw, uint32_t mask)
146 {
147     hw->int_ena.val |= mask;
148 }
149 
150 /**
151  * @brief  Disable the UART interrupt based on the given mask.
152  *
153  * @param  hw Beginning address of the peripheral registers.
154  * @param  mask The bitmap of the interrupts need to be disabled.
155  *
156  * @return None
157  */
uart_ll_disable_intr_mask(uart_dev_t * hw,uint32_t mask)158 FORCE_INLINE_ATTR void uart_ll_disable_intr_mask(uart_dev_t *hw, uint32_t mask)
159 {
160     hw->int_ena.val &= (~mask);
161 }
162 
163 /**
164  * @brief  Get the UART raw interrupt status.
165  *
166  * @param  hw Beginning address of the peripheral registers.
167  *
168  * @return The UART interrupt status.
169  */
uart_ll_get_intraw_mask(uart_dev_t * hw)170 static inline uint32_t uart_ll_get_intraw_mask(uart_dev_t *hw)
171 {
172     return hw->int_raw.val;
173 }
174 
175 /**
176  * @brief  Get the UART interrupt status.
177  *
178  * @param  hw Beginning address of the peripheral registers.
179  *
180  * @return The UART interrupt status.
181  */
uart_ll_get_intsts_mask(uart_dev_t * hw)182 FORCE_INLINE_ATTR uint32_t uart_ll_get_intsts_mask(uart_dev_t *hw)
183 {
184     return hw->int_st.val;
185 }
186 
187 /**
188  * @brief  Clear the UART interrupt status based on the given mask.
189  *
190  * @param  hw Beginning address of the peripheral registers.
191  * @param  mask The bitmap of the interrupts need to be cleared.
192  *
193  * @return None
194  */
uart_ll_clr_intsts_mask(uart_dev_t * hw,uint32_t mask)195 FORCE_INLINE_ATTR void uart_ll_clr_intsts_mask(uart_dev_t *hw, uint32_t mask)
196 {
197     hw->int_clr.val = mask;
198 }
199 
200 /**
201  * @brief  Get status of enabled interrupt.
202  *
203  * @param  hw Beginning address of the peripheral registers.
204  *
205  * @return interrupt enable value
206  */
uart_ll_get_intr_ena_status(uart_dev_t * hw)207 FORCE_INLINE_ATTR uint32_t uart_ll_get_intr_ena_status(uart_dev_t *hw)
208 {
209     return hw->int_ena.val;
210 }
211 
212 /**
213  * @brief  Read the UART rxfifo.
214  *
215  * @param  hw Beginning address of the peripheral registers.
216  * @param  buf The data buffer. The buffer size should be large than 128 byts.
217  * @param  rd_len The data length needs to be read.
218  *
219  * @return None.
220  */
uart_ll_read_rxfifo(uart_dev_t * hw,uint8_t * buf,uint32_t rd_len)221 FORCE_INLINE_ATTR void uart_ll_read_rxfifo(uart_dev_t *hw, uint8_t *buf, uint32_t rd_len)
222 {
223     //Get the UART fifo addr, ESP32-S2 have 2 UART
224     uint32_t fifo_addr = (hw == &UART0) ? UART_FIFO_AHB_REG(0) : UART_FIFO_AHB_REG(1);
225     for(uint32_t i = 0; i < rd_len; i++) {
226         buf[i] = READ_PERI_REG(fifo_addr);
227     }
228 }
229 
230 /**
231  * @brief  Write byte to the UART txfifo.
232  *
233  * @param  hw Beginning address of the peripheral registers.
234  * @param  buf The data buffer.
235  * @param  wr_len The data length needs to be writen.
236  *
237  * @return None
238  */
uart_ll_write_txfifo(uart_dev_t * hw,const uint8_t * buf,uint32_t wr_len)239 FORCE_INLINE_ATTR void uart_ll_write_txfifo(uart_dev_t *hw, const uint8_t *buf, uint32_t wr_len)
240 {
241     //Get the UART fifo addr, ESP32-S2 have 2 UART
242     uint32_t fifo_addr = (hw == &UART0) ? UART_FIFO_AHB_REG(0) : UART_FIFO_AHB_REG(1);
243     for(uint32_t i = 0; i < wr_len; i++) {
244         WRITE_PERI_REG(fifo_addr, buf[i]);
245     }
246 }
247 
248 /**
249  * @brief  Reset the UART hw rxfifo.
250  *
251  * @param  hw Beginning address of the peripheral registers.
252  *
253  * @return None
254  */
uart_ll_rxfifo_rst(uart_dev_t * hw)255 FORCE_INLINE_ATTR void uart_ll_rxfifo_rst(uart_dev_t *hw)
256 {
257     hw->conf0.rxfifo_rst = 1;
258     hw->conf0.rxfifo_rst = 0;
259 }
260 
261 /**
262  * @brief  Reset the UART hw txfifo.
263  *
264  * @param  hw Beginning address of the peripheral registers.
265  *
266  * @return None
267  */
uart_ll_txfifo_rst(uart_dev_t * hw)268 FORCE_INLINE_ATTR void uart_ll_txfifo_rst(uart_dev_t *hw)
269 {
270     hw->conf0.txfifo_rst = 1;
271     hw->conf0.txfifo_rst = 0;
272 }
273 
274 /**
275  * @brief  Get the length of readable data in UART rxfifo.
276  *
277  * @param  hw Beginning address of the peripheral registers.
278  *
279  * @return The readable data length in rxfifo.
280  */
uart_ll_get_rxfifo_len(uart_dev_t * hw)281 FORCE_INLINE_ATTR uint32_t uart_ll_get_rxfifo_len(uart_dev_t *hw)
282 {
283     return hw->status.rxfifo_cnt;
284 }
285 
286 /**
287  * @brief  Get the writable data length of UART txfifo.
288  *
289  * @param  hw Beginning address of the peripheral registers.
290  *
291  * @return The data length of txfifo can be written.
292  */
uart_ll_get_txfifo_len(uart_dev_t * hw)293 FORCE_INLINE_ATTR uint32_t uart_ll_get_txfifo_len(uart_dev_t *hw)
294 {
295     return UART_LL_FIFO_DEF_LEN - hw->status.txfifo_cnt;
296 }
297 
298 /**
299  * @brief  Configure the UART stop bit.
300  *
301  * @param  hw Beginning address of the peripheral registers.
302  * @param  stop_bit The stop bit number to be set.
303  *
304  * @return None.
305  */
uart_ll_set_stop_bits(uart_dev_t * hw,uart_stop_bits_t stop_bit)306 FORCE_INLINE_ATTR void uart_ll_set_stop_bits(uart_dev_t *hw, uart_stop_bits_t stop_bit)
307 {
308     hw->conf0.stop_bit_num = stop_bit;
309 }
310 
311 /**
312  * @brief  Get the configuration of the UART stop bit.
313  *
314  * @param  hw Beginning address of the peripheral registers.
315  * @param  stop_bit The pointer to accept the stop bit configuration
316  *
317  * @return None.
318  */
uart_ll_get_stop_bits(uart_dev_t * hw,uart_stop_bits_t * stop_bit)319 FORCE_INLINE_ATTR void uart_ll_get_stop_bits(uart_dev_t *hw, uart_stop_bits_t *stop_bit)
320 {
321     *stop_bit = (uart_stop_bits_t)hw->conf0.stop_bit_num;
322 }
323 
324 /**
325  * @brief  Configure the UART parity check mode.
326  *
327  * @param  hw Beginning address of the peripheral registers.
328  * @param  parity_mode The parity check mode to be set.
329  *
330  * @return None.
331  */
uart_ll_set_parity(uart_dev_t * hw,uart_parity_t parity_mode)332 FORCE_INLINE_ATTR void uart_ll_set_parity(uart_dev_t *hw, uart_parity_t parity_mode)
333 {
334     if(parity_mode != UART_PARITY_DISABLE) {
335         hw->conf0.parity = parity_mode & 0x1;
336     }
337     hw->conf0.parity_en = (parity_mode >> 1) & 0x1;
338 }
339 
340 /**
341  * @brief  Get the UART parity check mode configuration.
342  *
343  * @param  hw Beginning address of the peripheral registers.
344  * @param  parity_mode The pointer to accept the parity check mode configuration.
345  *
346  * @return None.
347  */
uart_ll_get_parity(uart_dev_t * hw,uart_parity_t * parity_mode)348 FORCE_INLINE_ATTR void uart_ll_get_parity(uart_dev_t *hw, uart_parity_t *parity_mode)
349 {
350     if(hw->conf0.parity_en) {
351         *parity_mode = (uart_parity_t)(0x2 | hw->conf0.parity);
352     } else {
353         *parity_mode = UART_PARITY_DISABLE;
354     }
355 }
356 
357 /**
358  * @brief  Set the UART rxfifo full threshold value. When the data in rxfifo is more than the threshold value,
359  *         it will produce rxfifo_full_int_raw interrupt.
360  *
361  * @param  hw Beginning address of the peripheral registers.
362  * @param  full_thrhd The full threshold value of the rxfifo. `full_thrhd` should be less than `UART_LL_FIFO_DEF_LEN`.
363  *
364  * @return None.
365  */
uart_ll_set_rxfifo_full_thr(uart_dev_t * hw,uint16_t full_thrhd)366 FORCE_INLINE_ATTR void uart_ll_set_rxfifo_full_thr(uart_dev_t *hw, uint16_t full_thrhd)
367 {
368     hw->conf1.rxfifo_full_thrhd = full_thrhd;
369 }
370 
371 /**
372  * @brief  Set the txfifo empty threshold. when the data length in txfifo is less than threshold value,
373  *         it will produce txfifo_empty_int_raw interrupt.
374  *
375  * @param  hw Beginning address of the peripheral registers.
376  * @param  empty_thrhd The empty threshold of txfifo.
377  *
378  * @return None.
379  */
uart_ll_set_txfifo_empty_thr(uart_dev_t * hw,uint16_t empty_thrhd)380 FORCE_INLINE_ATTR void uart_ll_set_txfifo_empty_thr(uart_dev_t *hw, uint16_t empty_thrhd)
381 {
382     hw->conf1.txfifo_empty_thrhd = empty_thrhd;
383 }
384 
385 /**
386  * @brief  Set the UART rx-idle threshold value. when receiver takes more time than rx_idle_thrhd to receive a byte data,
387  *         it will produce frame end signal for uhci to stop receiving data.
388  *
389  * @param  hw Beginning address of the peripheral registers.
390  * @param  rx_idle_thr The rx-idle threshold to be set.
391  *
392  * @return None.
393  */
uart_ll_set_rx_idle_thr(uart_dev_t * hw,uint32_t rx_idle_thr)394 FORCE_INLINE_ATTR void uart_ll_set_rx_idle_thr(uart_dev_t *hw, uint32_t rx_idle_thr)
395 {
396     hw->idle_conf.rx_idle_thrhd = rx_idle_thr;
397 }
398 
399 /**
400  * @brief  Configure the duration time between transfers.
401  *
402  * @param  hw Beginning address of the peripheral registers.
403  * @param  idle_num the duration time between transfers.
404  *
405  * @return None.
406  */
uart_ll_set_tx_idle_num(uart_dev_t * hw,uint32_t idle_num)407 FORCE_INLINE_ATTR void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num)
408 {
409     hw->idle_conf.tx_idle_num = idle_num;
410 }
411 
412 /**
413  * @brief  Configure the transmiter to send break chars.
414  *
415  * @param  hw Beginning address of the peripheral registers.
416  * @param  break_num The number of the break chars need to be send.
417  *
418  * @return None.
419  */
uart_ll_tx_break(uart_dev_t * hw,uint32_t break_num)420 FORCE_INLINE_ATTR void uart_ll_tx_break(uart_dev_t *hw, uint32_t break_num)
421 {
422     if(break_num > 0) {
423         HAL_FORCE_MODIFY_U32_REG_FIELD(hw->idle_conf, tx_brk_num, break_num);
424         hw->conf0.txd_brk = 1;
425     } else {
426         hw->conf0.txd_brk = 0;
427     }
428 }
429 
430 /**
431  * @brief  Configure the UART hardware flow control.
432  *
433  * @param  hw Beginning address of the peripheral registers.
434  * @param  flow_ctrl The hw flow control configuration.
435  * @param  rx_thrs The rx flow control signal will be active if the data length in rxfifo is more than this value.
436  *
437  * @return None.
438  */
uart_ll_set_hw_flow_ctrl(uart_dev_t * hw,uart_hw_flowcontrol_t flow_ctrl,uint32_t rx_thrs)439 FORCE_INLINE_ATTR void uart_ll_set_hw_flow_ctrl(uart_dev_t *hw, uart_hw_flowcontrol_t flow_ctrl, uint32_t rx_thrs)
440 {
441     //only when UART_HW_FLOWCTRL_RTS is set , will the rx_thresh value be set.
442     if(flow_ctrl & UART_HW_FLOWCTRL_RTS) {
443         hw->mem_conf.rx_flow_thrhd = rx_thrs;
444         hw->conf1.rx_flow_en = 1;
445     } else {
446         hw->conf1.rx_flow_en = 0;
447     }
448     if(flow_ctrl & UART_HW_FLOWCTRL_CTS) {
449         hw->conf0.tx_flow_en = 1;
450     } else {
451         hw->conf0.tx_flow_en = 0;
452     }
453 }
454 
455 /**
456  * @brief  Configure the hardware flow control.
457  *
458  * @param  hw Beginning address of the peripheral registers.
459  * @param  flow_ctrl A pointer to accept the hw flow control configuration.
460  *
461  * @return None.
462  */
uart_ll_get_hw_flow_ctrl(uart_dev_t * hw,uart_hw_flowcontrol_t * flow_ctrl)463 FORCE_INLINE_ATTR void uart_ll_get_hw_flow_ctrl(uart_dev_t *hw, uart_hw_flowcontrol_t *flow_ctrl)
464 {
465     *flow_ctrl = UART_HW_FLOWCTRL_DISABLE;
466     if(hw->conf1.rx_flow_en) {
467         *flow_ctrl = (uart_hw_flowcontrol_t)((unsigned int)(*flow_ctrl) | (unsigned int)UART_HW_FLOWCTRL_RTS);
468     }
469     if(hw->conf0.tx_flow_en) {
470         *flow_ctrl = (uart_hw_flowcontrol_t)((unsigned int)(*flow_ctrl) | (unsigned int)UART_HW_FLOWCTRL_CTS);
471     }
472 }
473 
474 /**
475  * @brief  Configure the software flow control.
476  *
477  * @param  hw Beginning address of the peripheral registers.
478  * @param  flow_ctrl The UART sofware flow control settings.
479  * @param  sw_flow_ctrl_en Set true to enable software flow control, otherwise set it false.
480  *
481  * @return None.
482  */
uart_ll_set_sw_flow_ctrl(uart_dev_t * hw,uart_sw_flowctrl_t * flow_ctrl,bool sw_flow_ctrl_en)483 FORCE_INLINE_ATTR void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl_t *flow_ctrl, bool sw_flow_ctrl_en)
484 {
485     if(sw_flow_ctrl_en) {
486         hw->flow_conf.xonoff_del = 1;
487         hw->flow_conf.sw_flow_con_en = 1;
488         hw->swfc_conf1.xon_threshold = flow_ctrl->xon_thrd;
489         hw->swfc_conf0.xoff_threshold = flow_ctrl->xoff_thrd;
490         HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf1, xon_char, flow_ctrl->xon_char);
491         HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf0, xoff_char, flow_ctrl->xoff_char);
492     } else {
493         hw->flow_conf.sw_flow_con_en = 0;
494         hw->flow_conf.xonoff_del = 0;
495     }
496 }
497 
498 /**
499  * @brief  Configure the AT cmd char. When the receiver receives a continuous AT cmd char, it will produce at_cmd_char_det interrupt.
500  *
501  * @param  hw Beginning address of the peripheral registers.
502  * @param  cmd_char The AT cmd char configuration.The configuration member is:
503  *         - cmd_char The AT cmd character
504  *         - char_num The number of received AT cmd char must be equal to or greater than this value
505  *         - gap_tout The interval between each AT cmd char, when the duration is less than this value, it will not take this data as AT cmd char
506  *         - pre_idle The idle time before the first AT cmd char, when the duration is less than this value, it will not take the previous data as the last AT cmd char
507  *         - post_idle The idle time after the last AT cmd char, when the duration is less than this value, it will not take this data as the first AT cmd char
508  *
509  * @return None.
510  */
uart_ll_set_at_cmd_char(uart_dev_t * hw,uart_at_cmd_t * cmd_char)511 FORCE_INLINE_ATTR void uart_ll_set_at_cmd_char(uart_dev_t *hw, uart_at_cmd_t *cmd_char)
512 {
513     HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char, data, cmd_char->cmd_char);
514     HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char, char_num, cmd_char->char_num);
515     HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_postcnt, post_idle_num, cmd_char->post_idle);
516     HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_precnt, pre_idle_num, cmd_char->pre_idle);
517     HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_gaptout, rx_gap_tout, cmd_char->gap_tout);
518 }
519 
520 /**
521  * @brief  Set the UART data bit mode.
522  *
523  * @param  hw Beginning address of the peripheral registers.
524  * @param  data_bit The data bit mode to be set.
525  *
526  * @return None.
527  */
uart_ll_set_data_bit_num(uart_dev_t * hw,uart_word_length_t data_bit)528 FORCE_INLINE_ATTR void uart_ll_set_data_bit_num(uart_dev_t *hw, uart_word_length_t data_bit)
529 {
530     hw->conf0.bit_num = data_bit;
531 }
532 
533 /**
534  * @brief  Set the rts active level.
535  *
536  * @param  hw Beginning address of the peripheral registers.
537  * @param  level The rts active level, 0 or 1.
538  *
539  * @return None.
540  */
uart_ll_set_rts_active_level(uart_dev_t * hw,int level)541 FORCE_INLINE_ATTR void uart_ll_set_rts_active_level(uart_dev_t *hw, int level)
542 {
543     hw->conf0.sw_rts = level & 0x1;
544 }
545 
546 /**
547  * @brief  Set the dtr active level.
548  *
549  * @param  hw Beginning address of the peripheral registers.
550  * @param  level The dtr active level, 0 or 1.
551  *
552  * @return None.
553  */
uart_ll_set_dtr_active_level(uart_dev_t * hw,int level)554 FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
555 {
556     hw->conf0.sw_dtr = level & 0x1;
557 }
558 
559 /**
560  * @brief  Set the UART wakeup threshold.
561  *
562  * @param  hw Beginning address of the peripheral registers.
563  * @param  wakeup_thrd The wakeup threshold value to be set. When the input rx edge changes more than this value,
564  *         the UART will active from light sleeping mode.
565  *
566  * @return None.
567  */
uart_ll_set_wakeup_thrd(uart_dev_t * hw,uint32_t wakeup_thrd)568 FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
569 {
570     // System would wakeup when the number of positive edges of RxD signal is larger than or equal to (UART_ACTIVE_THRESHOLD+3)
571     hw->sleep_conf.active_threshold = wakeup_thrd - UART_LL_MIN_WAKEUP_THRESH;
572 }
573 
574 /**
575  * @brief  Configure the UART work in normal mode.
576  *
577  * @param  hw Beginning address of the peripheral registers.
578  *
579  * @return None.
580  */
uart_ll_set_mode_normal(uart_dev_t * hw)581 FORCE_INLINE_ATTR void uart_ll_set_mode_normal(uart_dev_t *hw)
582 {
583     hw->rs485_conf.en = 0;
584     hw->rs485_conf.tx_rx_en = 0;
585     hw->rs485_conf.rx_busy_tx_en = 0;
586     hw->conf0.irda_en = 0;
587 }
588 
589 /**
590  * @brief  Configure the UART work in rs485_app_ctrl mode.
591  *
592  * @param  hw Beginning address of the peripheral registers.
593  *
594  * @return None.
595  */
uart_ll_set_mode_rs485_app_ctrl(uart_dev_t * hw)596 FORCE_INLINE_ATTR void uart_ll_set_mode_rs485_app_ctrl(uart_dev_t *hw)
597 {
598     // Application software control, remove echo
599     hw->rs485_conf.rx_busy_tx_en = 1;
600     hw->conf0.irda_en = 0;
601     hw->conf0.sw_rts = 0;
602     hw->conf0.irda_en = 0;
603     hw->rs485_conf.en = 1;
604 }
605 
606 /**
607  * @brief  Configure the UART work in rs485_half_duplex mode.
608  *
609  * @param  hw Beginning address of the peripheral registers.
610  *
611  * @return None.
612  */
uart_ll_set_mode_rs485_half_duplex(uart_dev_t * hw)613 FORCE_INLINE_ATTR void uart_ll_set_mode_rs485_half_duplex(uart_dev_t *hw)
614 {
615     // Enable receiver, sw_rts = 1  generates low level on RTS pin
616     hw->conf0.sw_rts = 1;
617     // Must be set to 0 to automatically remove echo
618     hw->rs485_conf.tx_rx_en = 0;
619     // This is to void collision
620     hw->rs485_conf.rx_busy_tx_en = 1;
621     hw->conf0.irda_en = 0;
622     hw->rs485_conf.en = 1;
623 }
624 
625 /**
626  * @brief  Get the rs485_half_duplex mode.
627  *
628  * @param  hw Beginning address of the peripheral registers.
629  *
630  * @return True if RS485 half duplex mode enabled.
631  */
uart_ll_is_mode_rs485_half_duplex(uart_dev_t * hw)632 FORCE_INLINE_ATTR bool uart_ll_is_mode_rs485_half_duplex(uart_dev_t *hw)
633 {
634 	return (!hw->rs485_conf.rx_busy_tx_en && hw->rs485_conf.en);
635 }
636 
637 /**
638  * @brief  Configure the UART work in collision_detect mode.
639  *
640  * @param  hw Beginning address of the peripheral registers.
641  *
642  * @return None.
643  */
uart_ll_set_mode_collision_detect(uart_dev_t * hw)644 FORCE_INLINE_ATTR void uart_ll_set_mode_collision_detect(uart_dev_t *hw)
645 {
646     hw->conf0.irda_en = 0;
647     // Transmitters output signal loop back to the receivers input signal
648     hw->rs485_conf.tx_rx_en = 1 ;
649     // Transmitter should send data when the receiver is busy
650     hw->rs485_conf.rx_busy_tx_en = 1;
651     hw->conf0.sw_rts = 0;
652     hw->rs485_conf.en = 1;
653 }
654 
655 /**
656  * @brief  Configure the UART work in irda mode.
657  *
658  * @param  hw Beginning address of the peripheral registers.
659  *
660  * @return None.
661  */
uart_ll_set_mode_irda(uart_dev_t * hw)662 FORCE_INLINE_ATTR void uart_ll_set_mode_irda(uart_dev_t *hw)
663 {
664     hw->rs485_conf.en = 0;
665     hw->rs485_conf.tx_rx_en = 0;
666     hw->rs485_conf.rx_busy_tx_en = 0;
667     hw->conf0.sw_rts = 0;
668     hw->conf0.irda_en = 1;
669 }
670 
671 /**
672  * @brief  Set uart mode.
673  *
674  * @param  hw Beginning address of the peripheral registers.
675  * @param  mode The UART mode to be set.
676  *
677  * @return None.
678  */
uart_ll_set_mode(uart_dev_t * hw,uart_mode_t mode)679 FORCE_INLINE_ATTR void uart_ll_set_mode(uart_dev_t *hw, uart_mode_t mode)
680 {
681     switch (mode) {
682         default:
683         case UART_MODE_UART:
684             uart_ll_set_mode_normal(hw);
685             break;
686         case UART_MODE_RS485_COLLISION_DETECT:
687             uart_ll_set_mode_collision_detect(hw);
688             break;
689         case UART_MODE_RS485_APP_CTRL:
690             uart_ll_set_mode_rs485_app_ctrl(hw);
691             break;
692         case UART_MODE_RS485_HALF_DUPLEX:
693             uart_ll_set_mode_rs485_half_duplex(hw);
694             break;
695         case UART_MODE_IRDA:
696             uart_ll_set_mode_irda(hw);
697             break;
698     }
699 }
700 
701 /**
702  * @brief  Get the UART AT cmd char configuration.
703  *
704  * @param  hw Beginning address of the peripheral registers.
705  * @param  cmd_char The Pointer to accept value of UART AT cmd char.
706  * @param  char_num Pointer to accept the repeat number of UART AT cmd char.
707  *
708  * @return None.
709  */
uart_ll_get_at_cmd_char(uart_dev_t * hw,uint8_t * cmd_char,uint8_t * char_num)710 FORCE_INLINE_ATTR void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char, uint8_t *char_num)
711 {
712     *cmd_char = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char, data);
713     *char_num = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char, char_num);
714 }
715 
716 /**
717  * @brief  Get the UART wakeup threshold value.
718  *
719  * @param  hw Beginning address of the peripheral registers.
720  *
721  * @return The UART wakeup threshold value.
722  */
uart_ll_get_wakeup_thrd(uart_dev_t * hw)723 FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_thrd(uart_dev_t *hw)
724 {
725     return hw->sleep_conf.active_threshold + UART_LL_MIN_WAKEUP_THRESH;
726 }
727 
728 /**
729  * @brief  Get the UART data bit configuration.
730  *
731  * @param  hw Beginning address of the peripheral registers.
732  * @param  data_bit The pointer to accept the UART data bit configuration.
733  *
734  * @return The bit mode.
735  */
uart_ll_get_data_bit_num(uart_dev_t * hw,uart_word_length_t * data_bit)736 FORCE_INLINE_ATTR void uart_ll_get_data_bit_num(uart_dev_t *hw, uart_word_length_t *data_bit)
737 {
738     *data_bit = (uart_word_length_t)hw->conf0.bit_num;
739 }
740 
741 /**
742  * @brief  Check if the UART sending state machine is in the IDLE state.
743  *
744  * @param  hw Beginning address of the peripheral registers.
745  *
746  * @return True if the state machine is in the IDLE state, otherwise false is returned.
747  */
uart_ll_is_tx_idle(uart_dev_t * hw)748 FORCE_INLINE_ATTR bool uart_ll_is_tx_idle(uart_dev_t *hw)
749 {
750     return ((hw->status.txfifo_cnt == 0) && (hw->fsm_status.st_utx_out == 0));
751 }
752 
753 /**
754  * @brief  Check if the UART rts flow control is enabled.
755  *
756  * @param  hw Beginning address of the peripheral registers.
757  *
758  * @return True if hw rts flow control is enabled, otherwise false is returned.
759  */
uart_ll_is_hw_rts_en(uart_dev_t * hw)760 FORCE_INLINE_ATTR bool uart_ll_is_hw_rts_en(uart_dev_t *hw)
761 {
762     return hw->conf1.rx_flow_en;
763 }
764 
765 /**
766  * @brief  Check if the UART cts flow control is enabled.
767  *
768  * @param  hw Beginning address of the peripheral registers.
769  *
770  * @return True if hw cts flow control is enabled, otherwise false is returned.
771  */
uart_ll_is_hw_cts_en(uart_dev_t * hw)772 FORCE_INLINE_ATTR bool uart_ll_is_hw_cts_en(uart_dev_t *hw)
773 {
774     return hw->conf0.tx_flow_en;
775 }
776 
777 /**
778  * @brief Configure TX signal loop back to RX module, just for the testing purposes
779  *
780  * @param  hw Beginning address of the peripheral registers.
781  * @param  loop_back_en Set ture to enable the loop back function, else set it false.
782  *
783  * @return None
784  */
uart_ll_set_loop_back(uart_dev_t * hw,bool loop_back_en)785 FORCE_INLINE_ATTR void uart_ll_set_loop_back(uart_dev_t *hw, bool loop_back_en)
786 {
787     hw->conf0.loopback = loop_back_en;
788 }
789 
790 /**
791  * @brief  Inverse the UART signal with the given mask.
792  *
793  * @param  hw Beginning address of the peripheral registers.
794  * @param  inv_mask The UART signal bitmap needs to be inversed.
795  *         Use the ORred mask of `uart_signal_inv_t`;
796  *
797  * @return None.
798  */
uart_ll_inverse_signal(uart_dev_t * hw,uint32_t inv_mask)799 FORCE_INLINE_ATTR void uart_ll_inverse_signal(uart_dev_t *hw, uint32_t inv_mask)
800 {
801     typeof(hw->conf0) conf0_reg;
802     conf0_reg.val = hw->conf0.val;
803     conf0_reg.irda_tx_inv = (inv_mask & UART_SIGNAL_IRDA_TX_INV) ? 1 : 0;
804     conf0_reg.irda_rx_inv = (inv_mask & UART_SIGNAL_IRDA_RX_INV) ? 1 : 0;
805     conf0_reg.rxd_inv = (inv_mask & UART_SIGNAL_RXD_INV) ? 1 : 0;
806     conf0_reg.cts_inv = (inv_mask & UART_SIGNAL_CTS_INV) ? 1 : 0;
807     conf0_reg.dsr_inv = (inv_mask & UART_SIGNAL_DSR_INV) ? 1 : 0;
808     conf0_reg.txd_inv = (inv_mask & UART_SIGNAL_TXD_INV) ? 1 : 0;
809     conf0_reg.rts_inv = (inv_mask & UART_SIGNAL_RTS_INV) ? 1 : 0;
810     conf0_reg.dtr_inv = (inv_mask & UART_SIGNAL_DTR_INV) ? 1 : 0;
811     hw->conf0.val = conf0_reg.val;
812 }
813 
814 /**
815  * @brief  Configure the timeout value for receiver receiving a byte, and enable rx timeout function.
816  *
817  * @param  hw Beginning address of the peripheral registers.
818  * @param  tout_thrd The timeout value as UART bit time. The rx timeout function will be disabled if `tout_thrd == 0`.
819  *
820  * @return None.
821  */
uart_ll_set_rx_tout(uart_dev_t * hw,uint16_t tout_thrd)822 FORCE_INLINE_ATTR void uart_ll_set_rx_tout(uart_dev_t *hw, uint16_t tout_thrd)
823 {
824     uint16_t tout_val = tout_thrd;
825     if(tout_thrd > 0) {
826         hw->mem_conf.rx_tout_thrhd = tout_val;
827         hw->conf1.rx_tout_en = 1;
828     } else {
829         hw->conf1.rx_tout_en = 0;
830     }
831 }
832 
833 /**
834  * @brief  Get the timeout value for receiver receiving a byte.
835  *
836  * @param  hw Beginning address of the peripheral registers.
837  *
838  * @return tout_thr The timeout threshold value. If timeout feature is disabled returns 0.
839  */
uart_ll_get_rx_tout_thr(uart_dev_t * hw)840 FORCE_INLINE_ATTR uint16_t uart_ll_get_rx_tout_thr(uart_dev_t *hw)
841 {
842     uint16_t tout_thrd = 0;
843     if(hw->conf1.rx_tout_en > 0) {
844         tout_thrd = hw->mem_conf.rx_tout_thrhd;
845     }
846     return tout_thrd;
847 }
848 
849 /**
850  * @brief  Get UART maximum timeout threshold.
851  *
852  * @param  hw Beginning address of the peripheral registers.
853  *
854  * @return maximum timeout threshold.
855  */
uart_ll_max_tout_thrd(uart_dev_t * hw)856 FORCE_INLINE_ATTR uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw)
857 {
858     return UART_RX_TOUT_THRHD_V;
859 }
860 
861 /**
862  * @brief  Configure the auto baudrate.
863  *
864  * @param  hw Beginning address of the peripheral registers.
865  * @param  enable Boolean marking whether the auto baudrate should be enabled or not.
866  */
uart_ll_set_autobaud_en(uart_dev_t * hw,bool enable)867 FORCE_INLINE_ATTR void uart_ll_set_autobaud_en(uart_dev_t *hw, bool enable)
868 {
869     hw->auto_baud.en = enable ? 1 : 0;
870 }
871 
872 /**
873  * @brief  Get the RXD edge count.
874  *
875  * @param  hw Beginning address of the peripheral registers.
876  */
uart_ll_get_rxd_edge_cnt(uart_dev_t * hw)877 FORCE_INLINE_ATTR uint32_t uart_ll_get_rxd_edge_cnt(uart_dev_t *hw)
878 {
879     return hw->rxd_cnt.edge_cnt;
880 }
881 
882 /**
883  * @brief  Get the positive pulse minimum count.
884  *
885  * @param  hw Beginning address of the peripheral registers.
886  */
uart_ll_get_pos_pulse_cnt(uart_dev_t * hw)887 FORCE_INLINE_ATTR uint32_t uart_ll_get_pos_pulse_cnt(uart_dev_t *hw)
888 {
889     return hw->pospulse.min_cnt;
890 }
891 
892 /**
893  * @brief  Get the negative pulse minimum count.
894  *
895  * @param  hw Beginning address of the peripheral registers.
896  */
uart_ll_get_neg_pulse_cnt(uart_dev_t * hw)897 FORCE_INLINE_ATTR uint32_t uart_ll_get_neg_pulse_cnt(uart_dev_t *hw)
898 {
899     return hw->negpulse.min_cnt;
900 }
901 
902 /**
903  * @brief  Get the high pulse minimum count.
904  *
905  * @param  hw Beginning address of the peripheral registers.
906  */
uart_ll_get_high_pulse_cnt(uart_dev_t * hw)907 FORCE_INLINE_ATTR uint32_t uart_ll_get_high_pulse_cnt(uart_dev_t *hw)
908 {
909     return hw->highpulse.min_cnt;
910 }
911 
912 /**
913  * @brief  Get the low pulse minimum count.
914  *
915  * @param  hw Beginning address of the peripheral registers.
916  */
uart_ll_get_low_pulse_cnt(uart_dev_t * hw)917 FORCE_INLINE_ATTR uint32_t uart_ll_get_low_pulse_cnt(uart_dev_t *hw)
918 {
919     return hw->lowpulse.min_cnt;
920 }
921 
922 /**
923  * @brief  Force UART xoff.
924  *
925  * @param  uart_num UART port number, the max port number is (UART_NUM_MAX -1).
926  *
927  * @return None.
928  */
uart_ll_force_xoff(uart_port_t uart_num)929 FORCE_INLINE_ATTR void uart_ll_force_xoff(uart_port_t uart_num)
930 {
931     REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON);
932     REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XOFF);
933 }
934 
935 /**
936  * @brief  Force UART xon.
937  *
938  * @param  uart_num UART port number, the max port number is (UART_NUM_MAX -1).
939  *
940  * @return None.
941  */
uart_ll_force_xon(uart_port_t uart_num)942 FORCE_INLINE_ATTR void uart_ll_force_xon(uart_port_t uart_num)
943 {
944     REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XOFF);
945     REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON);
946     REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XON);
947 }
948 
949 /**
950  * @brief  Get UART finite-state machine status.
951  *
952  * @param  uart_num UART port number, the max port number is (UART_NUM_MAX -1).
953  *
954  * @return UART module FSM status.
955  */
uart_ll_get_fsm_status(uart_port_t uart_num)956 FORCE_INLINE_ATTR uint32_t uart_ll_get_fsm_status(uart_port_t uart_num)
957 {
958     return REG_GET_FIELD(UART_FSM_STATUS_REG(uart_num), UART_ST_UTX_OUT);
959 }
960 
961 /**
962  * @brief  Configure UART whether to discard when receiving wrong data
963  *
964  * @param  hw Beginning address of the peripheral registers.
965  * @param  discard true: Receiver stops storing data into FIFO when data is wrong
966  *                false: Receiver continue storing data into FIFO when data is wrong
967  */
uart_ll_discard_error_data(uart_dev_t * hw,bool discard)968 FORCE_INLINE_ATTR void uart_ll_discard_error_data(uart_dev_t *hw, bool discard)
969 {
970     hw->conf0.err_wr_mask = discard ? 1 : 0;
971 }
972 
973 #ifdef __cplusplus
974 }
975 #endif
976