ChibiOS/HAL 9.0.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 */
89typedef enum {
90 UART_UNINIT = 0, /**< Not initialized. */
91 UART_STOP = 1, /**< Stopped. */
92 UART_READY = 2 /**< Ready. */
94
95/**
96 * @brief Transmitter state machine states.
97 */
98typedef enum {
99 UART_TX_IDLE = 0, /**< Not transmitting. */
100 UART_TX_ACTIVE = 1, /**< Transmitting. */
101 UART_TX_COMPLETE = 2 /**< Buffer complete. */
103
104/**
105 * @brief Receiver state machine states.
106 */
107typedef enum {
108 UART_RX_IDLE = 0, /**< Not receiving. */
109 UART_RX_ACTIVE = 1, /**< Receiving. */
110 UART_RX_COMPLETE = 2 /**< Buffer complete. */
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
391extern "C" {
392#endif
393 void uartInit(void);
394 void uartObjectInit(UARTDriver *uartp);
395 msg_t 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/** @} */
int32_t msg_t
Type of a message.
Definition osal.h:159
uint32_t sysinterval_t
Type of system time interval.
Definition osal.h:169
struct hal_uart_config UARTConfig
Driver configuration structure.
void uartInit(void)
UART Driver initialization.
Definition hal_uart.c:56
void uartStartSend(UARTDriver *uartp, size_t n, const void *txbuf)
Starts a transmission on the UART peripheral.
Definition hal_uart.c:164
void uartStartSendI(UARTDriver *uartp, size_t n, const void *txbuf)
Starts a transmission on the UART peripheral.
Definition hal_uart.c:189
void uartObjectInit(UARTDriver *uartp)
Initializes the standard part of a UARTDriver structure.
Definition hal_uart.c:68
uartstate_t
Driver state machine possible states.
Definition hal_uart.h:89
uartrxstate_t
Receiver state machine states.
Definition hal_uart.h:107
uarttxstate_t
Transmitter state machine states.
Definition hal_uart.h:98
void uartAcquireBus(UARTDriver *uartp)
Gains exclusive access to the UART bus.
Definition hal_uart.c:515
msg_t uartStart(UARTDriver *uartp, const UARTConfig *config)
Configures and activates the UART peripheral.
Definition hal_uart.c:98
void uartStartReceiveI(UARTDriver *uartp, size_t n, void *rxbuf)
Starts a receive operation on the UART peripheral.
Definition hal_uart.c:295
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:478
void uartReleaseBus(UARTDriver *uartp)
Releases exclusive access to the UART bus.
Definition hal_uart.c:531
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:431
void uartStop(UARTDriver *uartp)
Deactivates the UART peripheral.
Definition hal_uart.c:135
void uartStartReceive(UARTDriver *uartp, size_t n, void *rxbuf)
Starts a receive operation on the UART peripheral.
Definition hal_uart.c:270
size_t uartStopSend(UARTDriver *uartp)
Stops any ongoing transmission.
Definition hal_uart.c:212
size_t uartStopReceive(UARTDriver *uartp)
Stops any ongoing receive operation.
Definition hal_uart.c:318
size_t uartStopSendI(UARTDriver *uartp)
Stops any ongoing transmission.
Definition hal_uart.c:245
size_t uartStopReceiveI(UARTDriver *uartp)
Stops any ongoing receive operation.
Definition hal_uart.c:351
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:386
struct hal_uart_driver UARTDriver
Type of structure representing an UART driver.
@ UART_READY
Definition hal_uart.h:92
@ UART_UNINIT
Definition hal_uart.h:90
@ UART_STOP
Definition hal_uart.h:91
@ UART_RX_ACTIVE
Definition hal_uart.h:109
@ UART_RX_IDLE
Definition hal_uart.h:108
@ UART_RX_COMPLETE
Definition hal_uart.h:110
@ UART_TX_IDLE
Definition hal_uart.h:99
@ UART_TX_ACTIVE
Definition hal_uart.h:100
@ UART_TX_COMPLETE
Definition hal_uart.h:101
PLATFORM UART subsystem low level driver header.