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