ChibiOS/HAL  6.1.0
hal_uart.h
Go to the documentation of this file.
1 /*
2  ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 */
16 
17 /**
18  * @file hal_uart.h
19  * @brief UART Driver macros and structures.
20  *
21  * @addtogroup UART
22  * @{
23  */
24 
25 #ifndef HAL_UART_H
26 #define HAL_UART_H
27 
28 #if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__)
29 
30 /*===========================================================================*/
31 /* Driver constants. */
32 /*===========================================================================*/
33 
34 /**
35  * @name UART status flags
36  * @{
37  */
38 #define UART_NO_ERROR 0 /**< @brief No pending conditions. */
39 #define UART_PARITY_ERROR 4 /**< @brief Parity error happened. */
40 #define UART_FRAMING_ERROR 8 /**< @brief Framing error happened. */
41 #define UART_OVERRUN_ERROR 16 /**< @brief Overflow happened. */
42 #define UART_NOISE_ERROR 32 /**< @brief Noise on the line. */
43 #define UART_BREAK_DETECTED 64 /**< @brief Break detected. */
44 /** @} */
45 
46 /**
47  * @name UART error conditions
48  * @{
49  */
50 #define UART_ERR_NOT_ACTIVE (size_t)-1
51 /** @} */
52 
53 /*===========================================================================*/
54 /* Driver pre-compile time settings. */
55 /*===========================================================================*/
56 
57 /**
58  * @name UART configuration options
59  * @{
60  */
61 /**
62  * @brief Enables synchronous APIs.
63  * @note Disabling this option saves both code and data space.
64  */
65 #if !defined(UART_USE_WAIT) || defined(__DOXYGEN__)
66 #define UART_USE_WAIT FALSE
67 #endif
68 
69 /**
70  * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs.
71  * @note Disabling this option saves both code and data space.
72  */
73 #if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
74 #define UART_USE_MUTUAL_EXCLUSION FALSE
75 #endif
76 /** @} */
77 
78 /*===========================================================================*/
79 /* Derived constants and error checks. */
80 /*===========================================================================*/
81 
82 /*===========================================================================*/
83 /* Driver data structures and types. */
84 /*===========================================================================*/
85 
86 /**
87  * @brief Driver state machine possible states.
88  */
89 typedef enum {
90  UART_UNINIT = 0, /**< Not initialized. */
91  UART_STOP = 1, /**< Stopped. */
92  UART_READY = 2 /**< Ready. */
93 } uartstate_t;
94 
95 /**
96  * @brief Transmitter state machine states.
97  */
98 typedef enum {
99  UART_TX_IDLE = 0, /**< Not transmitting. */
100  UART_TX_ACTIVE = 1, /**< Transmitting. */
101  UART_TX_COMPLETE = 2 /**< Buffer complete. */
102 } uarttxstate_t;
103 
104 /**
105  * @brief Receiver state machine states.
106  */
107 typedef enum {
108  UART_RX_IDLE = 0, /**< Not receiving. */
109  UART_RX_ACTIVE = 1, /**< Receiving. */
110  UART_RX_COMPLETE = 2 /**< Buffer complete. */
111 } uartrxstate_t;
112 
113 #include "hal_uart_lld.h"
114 
115 /*===========================================================================*/
116 /* Driver macros. */
117 /*===========================================================================*/
118 
119 /**
120  * @name Low level driver helper macros
121  * @{
122  */
123 #if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
124 /**
125  * @brief Wakes up the waiting thread in case of early TX complete.
126  *
127  * @param[in] uartp pointer to the @p UARTDriver object
128  *
129  * @notapi
130  */
131 #define _uart_wakeup_tx1_isr(uartp) { \
132  if ((uartp)->early == true) { \
133  osalSysLockFromISR(); \
134  osalThreadResumeI(&(uartp)->threadtx, MSG_OK); \
135  osalSysUnlockFromISR(); \
136  } \
137 }
138 #else /* !UART_USE_WAIT */
139 #define _uart_wakeup_tx1_isr(uartp)
140 #endif /* !UART_USE_WAIT */
141 
142 #if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
143 /**
144  * @brief Wakes up the waiting thread in case of late TX complete.
145  *
146  * @param[in] uartp pointer to the @p UARTDriver object
147  *
148  * @notapi
149  */
150 #define _uart_wakeup_tx2_isr(uartp) { \
151  if ((uartp)->early == false) { \
152  osalSysLockFromISR(); \
153  osalThreadResumeI(&(uartp)->threadtx, MSG_OK); \
154  osalSysUnlockFromISR(); \
155  } \
156 }
157 #else /* !UART_USE_WAIT */
158 #define _uart_wakeup_tx2_isr(uartp)
159 #endif /* !UART_USE_WAIT */
160 
161 #if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
162 /**
163  * @brief Wakes up the waiting thread in case of RX complete.
164  *
165  * @param[in] uartp pointer to the @p UARTDriver object
166  *
167  * @notapi
168  */
169 #define _uart_wakeup_rx_complete_isr(uartp) { \
170  osalSysLockFromISR(); \
171  osalThreadResumeI(&(uartp)->threadrx, MSG_OK); \
172  osalSysUnlockFromISR(); \
173 }
174 #else /* !UART_USE_WAIT */
175 #define _uart_wakeup_rx_complete_isr(uartp)
176 #endif /* !UART_USE_WAIT */
177 
178 #if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
179 /**
180  * @brief Wakes up the waiting thread in case of RX error.
181  *
182  * @param[in] uartp pointer to the @p UARTDriver object
183  *
184  * @notapi
185  */
186 #define _uart_wakeup_rx_error_isr(uartp) { \
187  osalSysLockFromISR(); \
188  osalThreadResumeI(&(uartp)->threadrx, MSG_RESET); \
189  osalSysUnlockFromISR(); \
190 }
191 #else /* !UART_USE_WAIT */
192 #define _uart_wakeup_rx_error_isr(uartp)
193 #endif /* !UART_USE_WAIT */
194 
195 #if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
196 /**
197  * @brief Wakes up the waiting thread in case of RX character match.
198  *
199  * @param[in] uartp pointer to the @p UARTDriver object
200  *
201  * @notapi
202  */
203 #define _uart_wakeup_rx_cm_isr(uartp) { \
204  osalSysLockFromISR(); \
205  osalThreadResumeI(&(uartp)->threadrx, MSG_TIMEOUT); \
206  osalSysUnlockFromISR(); \
207 }
208 #else /* !UART_USE_WAIT */
209 #define _uart_wakeup_rx_cm_isr(uartp)
210 #endif /* !UART_USE_WAIT */
211 
212 #if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
213 /**
214  * @brief Wakes up the waiting thread in case of RX timeout.
215  *
216  * @param[in] uartp pointer to the @p UARTDriver object
217  *
218  * @notapi
219  */
220 #define _uart_wakeup_rx_timeout_isr(uartp) { \
221  osalSysLockFromISR(); \
222  osalThreadResumeI(&(uartp)->threadrx, MSG_TIMEOUT); \
223  osalSysUnlockFromISR(); \
224 }
225 #else /* !UART_USE_WAIT */
226 #define _uart_wakeup_rx_timeout_isr(uartp)
227 #endif /* !UART_USE_WAIT */
228 
229 /**
230  * @brief Common ISR code for early TX.
231  * @details This code handles the portable part of the ISR code:
232  * - Callback invocation.
233  * - Waiting thread wakeup, if any.
234  * - Driver state transitions.
235  * .
236  * @note This macro is meant to be used in the low level drivers
237  * implementation only.
238  *
239  * @param[in] uartp pointer to the @p UARTDriver object
240  *
241  * @notapi
242  */
243 #define _uart_tx1_isr_code(uartp) { \
244  (uartp)->txstate = UART_TX_COMPLETE; \
245  if ((uartp)->config->txend1_cb != NULL) { \
246  (uartp)->config->txend1_cb(uartp); \
247  } \
248  if ((uartp)->txstate == UART_TX_COMPLETE) { \
249  (uartp)->txstate = UART_TX_IDLE; \
250  } \
251  _uart_wakeup_tx1_isr(uartp); \
252 }
253 
254 /**
255  * @brief Common ISR code for late TX.
256  * @details This code handles the portable part of the ISR code:
257  * - Callback invocation.
258  * - Waiting thread wakeup, if any.
259  * - Driver state transitions.
260  * .
261  * @note This macro is meant to be used in the low level drivers
262  * implementation only.
263  *
264  * @param[in] uartp pointer to the @p UARTDriver object
265  *
266  * @notapi
267  */
268 #define _uart_tx2_isr_code(uartp) { \
269  if ((uartp)->config->txend2_cb != NULL) { \
270  (uartp)->config->txend2_cb(uartp); \
271  } \
272  _uart_wakeup_tx2_isr(uartp); \
273 }
274 
275 /**
276  * @brief Common ISR code for RX complete.
277  * @details This code handles the portable part of the ISR code:
278  * - Callback invocation.
279  * - Waiting thread wakeup, if any.
280  * - Driver state transitions.
281  * .
282  * @note This macro is meant to be used in the low level drivers
283  * implementation only.
284  *
285  * @param[in] uartp pointer to the @p UARTDriver object
286  *
287  * @notapi
288  */
289 #define _uart_rx_complete_isr_code(uartp) { \
290  (uartp)->rxstate = UART_RX_COMPLETE; \
291  if ((uartp)->config->rxend_cb != NULL) { \
292  (uartp)->config->rxend_cb(uartp); \
293  } \
294  if ((uartp)->rxstate == UART_RX_COMPLETE) { \
295  (uartp)->rxstate = UART_RX_IDLE; \
296  uart_enter_rx_idle_loop(uartp); \
297  } \
298  _uart_wakeup_rx_complete_isr(uartp); \
299 }
300 
301 /**
302  * @brief Common ISR code for RX error.
303  * @details This code handles the portable part of the ISR code:
304  * - Callback invocation.
305  * - Waiting thread wakeup, if any.
306  * - Driver state transitions.
307  * .
308  * @note This macro is meant to be used in the low level drivers
309  * implementation only.
310  *
311  * @param[in] uartp pointer to the @p UARTDriver object
312  * @param[in] errors mask of errors to be reported
313  *
314  * @notapi
315  */
316 #define _uart_rx_error_isr_code(uartp, errors) { \
317  if ((uartp)->config->rxerr_cb != NULL) { \
318  (uartp)->config->rxerr_cb(uartp, errors); \
319  } \
320  _uart_wakeup_rx_error_isr(uartp); \
321 }
322 
323 /**
324  * @brief Common ISR code for RX on idle.
325  * @details This code handles the portable part of the ISR code:
326  * - Callback invocation.
327  * - Waiting thread wakeup, if any.
328  * - Driver state transitions.
329  * .
330  * @note This macro is meant to be used in the low level drivers
331  * implementation only.
332  *
333  * @param[in] uartp pointer to the @p UARTDriver object
334  *
335  * @notapi
336  */
337 #define _uart_rx_idle_code(uartp) { \
338  if ((uartp)->config->rxchar_cb != NULL) \
339  (uartp)->config->rxchar_cb(uartp, (uartp)->rxbuf); \
340 }
341 
342 /**
343  * @brief Timeout ISR code for receiver.
344  * @details This code handles the portable part of the ISR code:
345  * - Callback invocation.
346  * - Waiting thread wakeup, if any.
347  * - Driver state transitions.
348  * .
349  * @note This macro is meant to be used in the low level drivers
350  * implementation only.
351  *
352  * @param[in] uartp pointer to the @p UARTDriver object
353  *
354  * @notapi
355  */
356 #define _uart_timeout_isr_code(uartp) { \
357  if ((uartp)->config->timeout_cb != NULL) { \
358  (uartp)->config->timeout_cb(uartp); \
359  } \
360  _uart_wakeup_rx_timeout_isr(uartp); \
361 }
362 
363 /**
364  * @brief Character match ISR code for receiver.
365  * @details This code handles the portable part of the ISR code:
366  * - Callback invocation.
367  * - Waiting thread wakeup, if any.
368  * - Driver state transitions.
369  * .
370  * @note This macro is meant to be used in the low level drivers
371  * implementation only.
372  *
373  * @param[in] uartp pointer to the @p UARTDriver object
374  *
375  * @notapi
376  */
377 #define _uart_rx_char_match_isr_code(uartp) { \
378  if ((uartp)->config->rx_cm_cb != NULL) { \
379  (uartp)->config->rx_cm_cb(uartp); \
380  } \
381  _uart_wakeup_rx_cm_isr(uartp); \
382 }
383 
384 /** @} */
385 
386 /*===========================================================================*/
387 /* External declarations. */
388 /*===========================================================================*/
389 
390 #ifdef __cplusplus
391 extern "C" {
392 #endif
393  void uartInit(void);
394  void uartObjectInit(UARTDriver *uartp);
395  void uartStart(UARTDriver *uartp, const UARTConfig *config);
396  void uartStop(UARTDriver *uartp);
397  void uartStartSend(UARTDriver *uartp, size_t n, const void *txbuf);
398  void uartStartSendI(UARTDriver *uartp, size_t n, const void *txbuf);
399  size_t uartStopSend(UARTDriver *uartp);
400  size_t uartStopSendI(UARTDriver *uartp);
401  void uartStartReceive(UARTDriver *uartp, size_t n, void *rxbuf);
402  void uartStartReceiveI(UARTDriver *uartp, size_t n, void *rxbuf);
403  size_t uartStopReceive(UARTDriver *uartp);
404  size_t uartStopReceiveI(UARTDriver *uartp);
405 #if UART_USE_WAIT == TRUE
406  msg_t uartSendTimeout(UARTDriver *uartp, size_t *np,
407  const void *txbuf, sysinterval_t timeout);
408  msg_t uartSendFullTimeout(UARTDriver *uartp, size_t *np,
409  const void *txbuf, sysinterval_t timeout);
410  msg_t uartReceiveTimeout(UARTDriver *uartp, size_t *np,
411  void *rxbuf, sysinterval_t timeout);
412 #endif
413 #if UART_USE_MUTUAL_EXCLUSION == TRUE
414  void uartAcquireBus(UARTDriver *uartp);
415  void uartReleaseBus(UARTDriver *uartp);
416 #endif
417 #ifdef __cplusplus
418 }
419 #endif
420 
421 #endif /* HAL_USE_UART == TRUE */
422 
423 #endif /* HAL_UART_H */
424 
425 /** @} */
PLATFORM UART subsystem low level driver header.
void uartStartSend(UARTDriver *uartp, size_t n, const void *txbuf)
Starts a transmission on the UART peripheral.
Definition: hal_uart.c:147
size_t uartStopReceive(UARTDriver *uartp)
Stops any ongoing receive operation.
Definition: hal_uart.c:301
void uartInit(void)
UART Driver initialization.
Definition: hal_uart.c:56
size_t uartStopSendI(UARTDriver *uartp)
Stops any ongoing transmission.
Definition: hal_uart.c:228
void uartStop(UARTDriver *uartp)
Deactivates the UART peripheral.
Definition: hal_uart.c:118
msg_t uartSendTimeout(UARTDriver *uartp, size_t *np, const void *txbuf, sysinterval_t timeout)
Performs a transmission on the UART peripheral.
Definition: hal_uart.c:369
size_t uartStopReceiveI(UARTDriver *uartp)
Stops any ongoing receive operation.
Definition: hal_uart.c:334
uartstate_t
Driver state machine possible states.
Definition: hal_uart.h:89
size_t uartStopSend(UARTDriver *uartp)
Stops any ongoing transmission.
Definition: hal_uart.c:195
msg_t uartReceiveTimeout(UARTDriver *uartp, size_t *np, void *rxbuf, sysinterval_t timeout)
Performs a receive operation on the UART peripheral.
Definition: hal_uart.c:461
int32_t msg_t
Type of a message.
Definition: osal.h:160
uarttxstate_t
Transmitter state machine states.
Definition: hal_uart.h:98
void uartStartSendI(UARTDriver *uartp, size_t n, const void *txbuf)
Starts a transmission on the UART peripheral.
Definition: hal_uart.c:172
void uartStartReceiveI(UARTDriver *uartp, size_t n, void *rxbuf)
Starts a receive operation on the UART peripheral.
Definition: hal_uart.c:278
void uartReleaseBus(UARTDriver *uartp)
Releases exclusive access to the UART bus.
Definition: hal_uart.c:514
void uartAcquireBus(UARTDriver *uartp)
Gains exclusive access to the UART bus.
Definition: hal_uart.c:498
void uartStartReceive(UARTDriver *uartp, size_t n, void *rxbuf)
Starts a receive operation on the UART peripheral.
Definition: hal_uart.c:253
uartrxstate_t
Receiver state machine states.
Definition: hal_uart.h:107
uint32_t sysinterval_t
Type of system time interval.
Definition: osal.h:170
void uartStart(UARTDriver *uartp, const UARTConfig *config)
Configures and activates the UART peripheral.
Definition: hal_uart.c:97
Driver configuration structure.
Definition: hal_uart_lld.h:100
void uartObjectInit(UARTDriver *uartp)
Initializes the standard part of a UARTDriver structure.
Definition: hal_uart.c:68
Structure representing an UART driver.
Definition: hal_uart_lld.h:129
msg_t uartSendFullTimeout(UARTDriver *uartp, size_t *np, const void *txbuf, sysinterval_t timeout)
Performs a transmission on the UART peripheral.
Definition: hal_uart.c:414