1 /*
2 * Copyright (c) 2021 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #ifndef HPM_UART_DRV_H
9 #define HPM_UART_DRV_H
10 #include "hpm_common.h"
11 #include "hpm_uart_regs.h"
12
13 /**
14 *
15 * @brief UART driver APIs
16 * @defgroup uart_interface UART driver APIs
17 * @ingroup io_interfaces
18 * @{
19 */
20
21 /**
22 * @brief UART status
23 */
24 enum {
25 status_uart_no_suitable_baudrate_parameter_found = MAKE_STATUS(status_group_uart, 1),
26 };
27
28 /* @brief Parity */
29 typedef enum parity {
30 parity_none = 0,
31 parity_odd,
32 parity_even,
33 parity_always_1,
34 parity_always_0,
35 } parity_setting_t;
36
37 /* @brief Stop bits */
38 typedef enum num_of_stop_bits {
39 stop_bits_1 = 0,
40 stop_bits_1_5,
41 stop_bits_2,
42 } num_of_stop_bits_t;
43
44 /* @brief Word length */
45 typedef enum word_length {
46 word_length_5_bits = 0,
47 word_length_6_bits,
48 word_length_7_bits,
49 word_length_8_bits,
50 } word_length_t;
51
52 /* @brief UART fifo trigger levels */
53 typedef enum uart_fifo_trg_lvl {
54 uart_rx_fifo_trg_not_empty = 0,
55 uart_rx_fifo_trg_gt_one_quarter = 1,
56 uart_rx_fifo_trg_gt_half = 2,
57 uart_rx_fifo_trg_gt_three_quarters = 3,
58
59 uart_tx_fifo_trg_not_full = 0,
60 uart_tx_fifo_trg_lt_three_quarters = 1,
61 uart_tx_fifo_trg_lt_half = 2,
62 uart_tx_fifo_trg_lt_one_quarter = 3,
63 } uart_fifo_trg_lvl_t;
64
65 /* @brief UART signals */
66 typedef enum uart_signal {
67 uart_signal_rts = UART_MCR_RTS_MASK,
68 } uart_signal_t;
69
70 /* @brief UART signal levels */
71 typedef enum uart_signal_level {
72 uart_signal_level_high,
73 uart_signal_level_low,
74 } uart_signal_level_t;
75
76 /* @brief UART modem status */
77 typedef enum uart_modem_stat {
78 uart_modem_stat_cts = UART_MSR_CTS_MASK,
79 uart_modem_stat_dcts_changed = UART_MSR_DCTS_MASK,
80 } uart_modem_stat_t;
81
82 /* @brief UART interrupt enable masks */
83 typedef enum uart_intr_enable {
84 uart_intr_rx_data_avail_or_timeout = UART_IER_ERBI_MASK,
85 uart_intr_tx_slot_avail = UART_IER_ETHEI_MASK,
86 uart_intr_rx_line_stat = UART_IER_ELSI_MASK,
87 uart_intr_modem_stat = UART_IER_EMSI_MASK,
88 } uart_intr_enable_t;
89
90 /* @brief UART interrupt IDs */
91 typedef enum uart_intr_id {
92 uart_intr_id_modem_stat = 0x0,
93 uart_intr_id_tx_slot_avail = 0x2,
94 uart_intr_id_rx_data_avail = 0x4,
95 uart_intr_id_rx_line_stat = 0x6,
96 uart_intr_id_rx_timeout = 0xc,
97 } uart_intr_id_t;
98
99 /* @brief UART status */
100 typedef enum uart_stat {
101 uart_stat_data_ready = UART_LSR_DR_MASK,
102 uart_stat_overrun_error = UART_LSR_OE_MASK,
103 uart_stat_parity_error = UART_LSR_PE_MASK,
104 uart_stat_framing_error = UART_LSR_FE_MASK,
105 uart_stat_line_break = UART_LSR_LBREAK_MASK,
106 uart_stat_tx_slot_avail = UART_LSR_THRE_MASK,
107 uart_stat_transmitter_empty = UART_LSR_TEMT_MASK,
108 uart_stat_rx_fifo_error = UART_LSR_ERRF_MASK,
109 } uart_stat_t;
110
111 /**
112 * @brief UART modem config
113 */
114 typedef struct uart_modem_config {
115 bool auto_flow_ctrl_en; /**< Auto flow control enable flag */
116 bool loop_back_en; /**< Loop back enable flag */
117 bool set_rts_high; /**< Set signal RTS level high flag */
118 } uart_modem_config_t;
119
120 /**
121 * @brief UART config
122 */
123 typedef struct hpm_uart_config {
124 uint32_t src_freq_in_hz; /**< Source clock frequency in Hz */
125 uint32_t baudrate; /**< Baudrate */
126 uint8_t num_of_stop_bits; /**< Number of stop bits */
127 uint8_t word_length; /**< Word length */
128 uint8_t parity; /**< Parity */
129 uint8_t tx_fifo_level; /**< TX Fifo level */
130 uint8_t rx_fifo_level; /**< RX Fifo level */
131 bool dma_enable; /**< DMA Enable flag */
132 bool fifo_enable; /**< Fifo Enable flag */
133 uart_modem_config_t modem_config; /**< Modem config */
134 } uart_config_t;
135
136 #ifdef __cplusplus
137 extern "C" {
138 #endif
139
140 /**
141 * @brief Get fifo size
142 *
143 * @param ptr UART base address
144 * @retval size of Fifo
145 */
uart_get_fifo_size(UART_Type * ptr)146 static inline uint8_t uart_get_fifo_size(UART_Type *ptr)
147 {
148 return 16 << ((ptr->CFG & UART_CFG_FIFOSIZE_MASK) >> UART_CFG_FIFOSIZE_SHIFT);
149 }
150
151 /**
152 * @brief Reset TX Fifo
153 *
154 * @param ptr UART base address
155 */
uart_reset_tx_fifo(UART_Type * ptr)156 static inline void uart_reset_tx_fifo(UART_Type *ptr)
157 {
158 if (ptr->FCR & UART_FCR_FIFOE_MASK) {
159 ptr->FCR |= UART_FCR_TFIFORST_MASK;
160 }
161 }
162
163 /**
164 * @brief Reset RX Fifo
165 *
166 * @param ptr UART base address
167 */
uart_reset_rx_fifo(UART_Type * ptr)168 static inline void uart_reset_rx_fifo(UART_Type *ptr)
169 {
170 if (ptr->FCR & UART_FCR_FIFOE_MASK) {
171 ptr->FCR |= UART_FCR_RFIFORST_MASK;
172 }
173 }
174
175 /**
176 * @brief Reset both TX and RX Fifo
177 *
178 * @param ptr UART base address
179 */
uart_reset_all_fifo(UART_Type * ptr)180 static inline void uart_reset_all_fifo(UART_Type *ptr)
181 {
182 if (ptr->FCR & UART_FCR_FIFOE_MASK) {
183 ptr->FCR |= UART_FCR_RFIFORST_MASK | UART_FCR_TFIFORST_MASK;
184 }
185 }
186
187 /**
188 * @brief Enable modem loopback
189 *
190 * @param ptr UART base address
191 */
uart_modem_enable_loopback(UART_Type * ptr)192 static inline void uart_modem_enable_loopback(UART_Type *ptr)
193 {
194 ptr->MCR |= UART_MCR_LOOP_MASK;
195 }
196
197 /**
198 * @brief Disable modem loopback
199 *
200 * @param ptr UART base address
201 */
uart_modem_disable_loopback(UART_Type * ptr)202 static inline void uart_modem_disable_loopback(UART_Type *ptr)
203 {
204 ptr->MCR &= ~UART_MCR_LOOP_MASK;
205 }
206
207 /**
208 * @brief Disable modem auto flow control
209 *
210 * @param ptr UART base address
211 */
212
uart_modem_disable_auto_flow_control(UART_Type * ptr)213 static inline void uart_modem_disable_auto_flow_control(UART_Type *ptr)
214 {
215 ptr->MCR &= ~UART_MCR_AFE_MASK;
216 }
217
218 /**
219 * @brief Enable modem auto flow control
220 *
221 * @param ptr UART base address
222 */
uart_modem_enable_auto_flow_control(UART_Type * ptr)223 static inline void uart_modem_enable_auto_flow_control(UART_Type *ptr)
224 {
225 ptr->MCR |= UART_MCR_AFE_MASK;
226 }
227
228 /**
229 * @brief Configure modem
230 *
231 * @param ptr UART base address
232 * @param config Pointer to modem config struct
233 */
uart_modem_config(UART_Type * ptr,uart_modem_config_t * config)234 static inline void uart_modem_config(UART_Type *ptr, uart_modem_config_t *config)
235 {
236 ptr->MCR = UART_MCR_AFE_SET(config->auto_flow_ctrl_en)
237 | UART_MCR_LOOP_SET(config->loop_back_en)
238 | UART_MCR_RTS_SET(!config->set_rts_high);
239 }
240
241 /**
242 * @brief Get modem status
243 *
244 * @param ptr UART base address
245 * @retval Current modem status
246 */
uart_get_modem_status(UART_Type * ptr)247 static inline uint8_t uart_get_modem_status(UART_Type *ptr)
248 {
249 return ptr->MSR;
250 }
251
252
253 /**
254 * @brief Check modem status with given mask
255 *
256 * @param ptr UART base address
257 * @param mask Status mask value to be checked against
258 * @retval true if any bit in given mask is set
259 * @retval false if none of any bit in given mask is set
260 */
uart_check_modem_status(UART_Type * ptr,uart_modem_stat_t mask)261 static inline bool uart_check_modem_status(UART_Type *ptr, uart_modem_stat_t mask)
262 {
263 return (ptr->MSR & mask);
264 }
265
266 /**
267 * @brief Disable IRQ with mask
268 *
269 * @param ptr UART base address
270 * @param irq_mask IRQ mask value to be disabled
271 */
uart_disable_irq(UART_Type * ptr,uart_intr_enable_t irq_mask)272 static inline void uart_disable_irq(UART_Type *ptr, uart_intr_enable_t irq_mask)
273 {
274 ptr->IER &= ~irq_mask;
275 }
276
277 /**
278 * @brief Enable IRQ with mask
279 *
280 * @param ptr UART base address
281 * @param irq_mask IRQ mask value to be enabled
282 */
uart_enable_irq(UART_Type * ptr,uart_intr_enable_t irq_mask)283 static inline void uart_enable_irq(UART_Type *ptr, uart_intr_enable_t irq_mask)
284 {
285 ptr->IER |= irq_mask;
286 }
287
288 /**
289 * @brief Get Enabled IRQ
290 *
291 * @param ptr UART base address
292 * @return enabled irq
293 */
uart_get_enabled_irq(UART_Type * ptr)294 static inline uint32_t uart_get_enabled_irq(UART_Type *ptr)
295 {
296 return ptr->IER;
297 }
298
299 /**
300 * @brief Get interrupt identification
301 *
302 * @param ptr UART base address
303 * @retval interrupt id
304 */
uart_get_irq_id(UART_Type * ptr)305 static inline uint8_t uart_get_irq_id(UART_Type *ptr)
306 {
307 return (ptr->IIR & UART_IIR_INTRID_MASK);
308 }
309
310 /**
311 * @brief Get status
312 *
313 * @param ptr UART base address
314 * @retval current status
315 */
uart_get_status(UART_Type * ptr)316 static inline uint8_t uart_get_status(UART_Type *ptr)
317 {
318 return ptr->LSR;
319 }
320
321 /**
322 * @brief Check uart status according to the given status mask
323 *
324 * @param ptr UART base address
325 * @param mask Status mask value to be checked against
326 * @retval true if any bit in given mask is set
327 * @retval false if none of any bit in given mask is set
328 */
uart_check_status(UART_Type * ptr,uart_stat_t mask)329 static inline bool uart_check_status(UART_Type *ptr, uart_stat_t mask)
330 {
331 return (ptr->LSR & mask);
332 }
333
334 /**
335 * @brief Get default config
336 *
337 * @param ptr UART base address
338 * @param config Pointer to the buffer to save default values
339 */
340 void uart_default_config(UART_Type *ptr, uart_config_t *config);
341
342 /**
343 * @brief Initialization
344 *
345 * @param ptr UART base address
346 * @param config Pointer to config struct
347 * @retval status_success only if it succeeds
348 */
349 hpm_stat_t uart_init(UART_Type *ptr, uart_config_t *config);
350
351 /**
352 * @brief Send one byte
353 *
354 * @param ptr UART base address
355 * @param c Byte to be sent
356 * @retval status_success only if it succeeds
357 */
358 hpm_stat_t uart_send_byte(UART_Type *ptr, uint8_t c);
359
360 /**
361 * @brief Receive one byte
362 *
363 * @param ptr UART base address
364 * @param c Pointer to buffer to save the byte received on UART
365 * @retval status_success only if it succeeds
366 */
367 hpm_stat_t uart_receive_byte(UART_Type *ptr, uint8_t *c);
368
369 /**
370 * @brief Set uart signal output level
371 *
372 * @param ptr UART base address
373 * @param signal Target signal
374 * @param level Target signal level
375 */
376 void uart_set_signal_level(UART_Type *ptr,
377 uart_signal_t signal,
378 uart_signal_level_t level);
379
380 /**
381 * @brief Flush sending buffer/fifo
382 *
383 * @param ptr UART base address
384 * @retval status_success only if it succeeds
385 */
386 hpm_stat_t uart_flush(UART_Type *ptr);
387
388 /**
389 * @brief Receive bytes blocking
390 *
391 * @param ptr UART base address
392 * @param buf Pointer to the buffer to save received data
393 * @param size_in_byte Size in byte to be sent
394 * @retval status_success only if it succeeds
395 */
396 hpm_stat_t uart_receive_data(UART_Type *ptr, uint8_t *buf, uint32_t size_in_byte);
397
398 /**
399 * @brief Send bytes blocking
400 *
401 * @param ptr UART base address
402 * @param buf Pointer to the buffer to be sent
403 * @param size_in_byte Size in byte to be sent
404 * @retval status_success only if it succeeds
405 */
406 hpm_stat_t uart_send_data(UART_Type *ptr, uint8_t *buf, uint32_t size_in_byte);
407
408
409 /**
410 * @brief Sets UART baudrate.
411 *
412 * This function configures the UART module baud rate. This function is used to update
413 * the UART module baud rate after the UART module is initialized by the uart_init.
414 *
415 * @param ptr UART base address
416 * @param baudrate UART baudrate to be set
417 * @param src_clock_hz UART clock source frequency in Hz.
418 * @retval status_uart_no_suitable_baudrate_parameter_found Baudrate is not supported in the current clock source
419 * @retval status_success Set baudrate succeeded.
420 */
421 hpm_stat_t uart_set_baudrate(UART_Type *ptr, uint32_t baudrate, uint32_t src_clock_hz);
422
423 #ifdef __cplusplus
424 }
425 #endif
426 /**
427 * @}
428 */
429
430 #endif /* HPM_UART_DRV_H */
431