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