Improved UART driver.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8479 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
Giovanni Di Sirio 2015-11-13 12:33:18 +00:00
parent 4fb6d9644e
commit f098e079d0
9 changed files with 483 additions and 62 deletions

View File

@ -270,13 +270,13 @@ extern "C" {
const void *txbuf, void *rxbuf);
void spiStartSend(SPIDriver *spip, size_t n, const void *txbuf);
void spiStartReceive(SPIDriver *spip, size_t n, void *rxbuf);
#if SPI_USE_WAIT
#if SPI_USE_WAIT == TRUE
void spiIgnore(SPIDriver *spip, size_t n);
void spiExchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf);
void spiSend(SPIDriver *spip, size_t n, const void *txbuf);
void spiReceive(SPIDriver *spip, size_t n, void *rxbuf);
#endif
#if SPI_USE_MUTUAL_EXCLUSION
#if SPI_USE_MUTUAL_EXCLUSION == TRUE
void spiAcquireBus(SPIDriver *spip);
void spiReleaseBus(SPIDriver *spip);
#endif

View File

@ -47,6 +47,27 @@
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name UART configuration options
* @{
*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__)
#define UART_USE_WAIT TRUE
#endif
/**
* @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define UART_USE_MUTUAL_EXCLUSION TRUE
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
@ -88,6 +109,196 @@ typedef enum {
/* Driver macros. */
/*===========================================================================*/
/**
* @name Low level driver helper macros
* @{
*/
#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
/**
* @brief Wakes up the waiting thread in case of early TX complete.
*
* @param[in] uartp pointer to the @p UARTDriver object
*
* @notapi
*/
#define _uart_wakeup_tx1_isr(uartp) { \
if ((uartp)->early == true) { \
osalSysLockFromISR(); \
osalThreadResumeI(&(uartp)->threadtx, MSG_OK); \
osalSysUnlockFromISR(); \
} \
}
#else /* !UART_USE_WAIT */
#define _uart_wakeup_tx1_isr(uartp)
#endif /* !UART_USE_WAIT */
#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
/**
* @brief Wakes up the waiting thread in case of late TX complete.
*
* @param[in] uartp pointer to the @p UARTDriver object
*
* @notapi
*/
#define _uart_wakeup_tx2_isr(uartp) { \
if ((uartp)->early == false) { \
osalSysLockFromISR(); \
osalThreadResumeI(&(uartp)->threadtx, MSG_OK); \
osalSysUnlockFromISR(); \
} \
}
#else /* !UART_USE_WAIT */
#define _uart_wakeup_tx2_isr(uartp)
#endif /* !UART_USE_WAIT */
#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
/**
* @brief Wakes up the waiting thread in case of RX complete.
*
* @param[in] uartp pointer to the @p UARTDriver object
*
* @notapi
*/
#define _uart_wakeup_rx_complete_isr(uartp) { \
osalSysLockFromISR(); \
osalThreadResumeI(&(uartp)->threadrx, MSG_OK); \
osalSysUnlockFromISR(); \
}
#else /* !UART_USE_WAIT */
#define _uart_wakeup_rx_complete_isr(uartp)
#endif /* !UART_USE_WAIT */
#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
/**
* @brief Wakes up the waiting thread in case of RX error.
*
* @param[in] uartp pointer to the @p UARTDriver object
*
* @notapi
*/
#define _uart_wakeup_rx_error_isr(uartp) { \
osalSysLockFromISR(); \
osalThreadResumeI(&(uartp)->threadrx, MSG_RESET); \
osalSysUnlockFromISR(); \
}
#else /* !UART_USE_WAIT */
#define _uart_wakeup_rx_error_isr(uartp)
#endif /* !UART_USE_WAIT */
/**
* @brief Common ISR code for early TX.
* @details This code handles the portable part of the ISR code:
* - Callback invocation.
* - Waiting thread wakeup, if any.
* - Driver state transitions.
* .
* @note This macro is meant to be used in the low level drivers
* implementation only.
*
* @param[in] uartp pointer to the @p UARTDriver object
*
* @notapi
*/
#define _uart_tx1_isr_code(uartp) { \
(uartp)->txstate = UART_TX_COMPLETE; \
if ((uartp)->config->txend1_cb != NULL) { \
(uartp)->config->txend1_cb(uartp); \
} \
if ((uartp)->txstate == UART_TX_COMPLETE) { \
(uartp)->txstate = UART_TX_IDLE; \
} \
_uart_wakeup_tx1_isr(uartp); \
}
/**
* @brief Common ISR code for late TX.
* @details This code handles the portable part of the ISR code:
* - Callback invocation.
* - Waiting thread wakeup, if any.
* - Driver state transitions.
* .
* @note This macro is meant to be used in the low level drivers
* implementation only.
*
* @param[in] uartp pointer to the @p UARTDriver object
*
* @notapi
*/
#define _uart_tx2_isr_code(uartp) { \
if ((uartp)->config->txend2_cb != NULL) { \
(uartp)->config->txend2_cb(uartp); \
} \
_uart_wakeup_tx2_isr(uartp); \
}
/**
* @brief Common ISR code for RX complete.
* @details This code handles the portable part of the ISR code:
* - Callback invocation.
* - Waiting thread wakeup, if any.
* - Driver state transitions.
* .
* @note This macro is meant to be used in the low level drivers
* implementation only.
*
* @param[in] uartp pointer to the @p UARTDriver object
*
* @notapi
*/
#define _uart_rx_complete_isr_code(uartp) { \
(uartp)->rxstate = UART_RX_COMPLETE; \
if ((uartp)->config->rxend_cb != NULL) { \
(uartp)->config->rxend_cb(uartp); \
} \
if ((uartp)->rxstate == UART_RX_COMPLETE) { \
(uartp)->rxstate = UART_RX_IDLE; \
uart_enter_rx_idle_loop(uartp); \
} \
_uart_wakeup_rx_complete_isr(uartp); \
}
/**
* @brief Common ISR code for RX error.
* @details This code handles the portable part of the ISR code:
* - Callback invocation.
* - Waiting thread wakeup, if any.
* - Driver state transitions.
* .
* @note This macro is meant to be used in the low level drivers
* implementation only.
*
* @param[in] uartp pointer to the @p UARTDriver object
*
* @notapi
*/
#define _uart_rx_error_isr_code(uartp, errors) { \
if ((uartp)->config->rxerr_cb != NULL) { \
(uartp)->config->rxerr_cb(uartp, errors); \
} \
_uart_wakeup_rx_error_isr(uartp); \
}
/**
* @brief Common ISR code for RX on idle.
* @details This code handles the portable part of the ISR code:
* - Callback invocation.
* - Waiting thread wakeup, if any.
* - Driver state transitions.
* .
* @note This macro is meant to be used in the low level drivers
* implementation only.
*
* @param[in] uartp pointer to the @p UARTDriver object
*
* @notapi
*/
#define _uart_rx_idle_code(uartp) { \
if ((uartp)->config->rxchar_cb != NULL) \
(uartp)->config->rxchar_cb(uartp, (uartp)->rxbuf); \
}
/** @} */
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
@ -107,6 +318,18 @@ extern "C" {
void uartStartReceiveI(UARTDriver *uartp, size_t n, void *rxbuf);
size_t uartStopReceive(UARTDriver *uartp);
size_t uartStopReceiveI(UARTDriver *uartp);
#if UART_USE_WAIT == TRUE
msg_t uartSendTimeout(UARTDriver *uartp, size_t *np,
const void *txbuf, systime_t time);
msg_t uartSendFullTimeout(UARTDriver *uartp, size_t *np,
const void *txbuf, systime_t time);
msg_t uartReceiveTimeout(UARTDriver *uartp, size_t *np,
void *rxbuf, systime_t time);
#endif
#if UART_USE_MUTUAL_EXCLUSION == TRUE
void uartAcquireBus(UARTDriver *uartp);
void uartReleaseBus(UARTDriver *uartp);
#endif
#ifdef __cplusplus
}
#endif

View File

@ -156,7 +156,7 @@ static uartflags_t translate_errors(uint16_t sr) {
*
* @param[in] uartp pointer to the @p UARTDriver object
*/
static void set_rx_idle_loop(UARTDriver *uartp) {
static void uart_enter_rx_idle_loop(UARTDriver *uartp) {
uint32_t mode;
/* RX DMA channel preparation, if the char callback is defined then the
@ -229,7 +229,7 @@ static void usart_start(UARTDriver *uartp) {
u->CR1 = uartp->config->cr1 | cr1;
/* Starting the receiver idle loop.*/
set_rx_idle_loop(uartp);
uart_enter_rx_idle_loop(uartp);
}
/**
@ -252,23 +252,13 @@ static void uart_lld_serve_rx_end_irq(UARTDriver *uartp, uint32_t flags) {
if (uartp->rxstate == UART_RX_IDLE) {
/* Receiver in idle state, a callback is generated, if enabled, for each
received character and then the driver stays in the same state.*/
if (uartp->config->rxchar_cb != NULL)
uartp->config->rxchar_cb(uartp, uartp->rxbuf);
_uart_rx_idle_code(uartp);
}
else {
/* Receiver in active state, a callback is generated, if enabled, after
a completed transfer.*/
dmaStreamDisable(uartp->dmarx);
uartp->rxstate = UART_RX_COMPLETE;
if (uartp->config->rxend_cb != NULL)
uartp->config->rxend_cb(uartp);
/* If the callback didn't explicitly change state then the receiver
automatically returns to the idle state.*/
if (uartp->rxstate == UART_RX_COMPLETE) {
uartp->rxstate = UART_RX_IDLE;
set_rx_idle_loop(uartp);
}
_uart_rx_complete_isr_code(uartp);
}
}
@ -292,14 +282,7 @@ static void uart_lld_serve_tx_end_irq(UARTDriver *uartp, uint32_t flags) {
dmaStreamDisable(uartp->dmatx);
/* A callback is generated, if enabled, after a completed transfer.*/
uartp->txstate = UART_TX_COMPLETE;
if (uartp->config->txend1_cb != NULL)
uartp->config->txend1_cb(uartp);
/* If the callback didn't explicitly change state then the transmitter
automatically returns to the idle state.*/
if (uartp->txstate == UART_TX_COMPLETE)
uartp->txstate = UART_TX_IDLE;
_uart_wakeup_tx1_isr(uartp);
}
/**
@ -318,8 +301,7 @@ static void serve_usart_irq(UARTDriver *uartp) {
if (sr & (USART_SR_LBD | USART_SR_ORE | USART_SR_NE |
USART_SR_FE | USART_SR_PE)) {
u->SR = ~USART_SR_LBD;
if (uartp->config->rxerr_cb != NULL)
uartp->config->rxerr_cb(uartp, translate_errors(sr));
_uart_rx_error_isr_code(uartp, translate_errors(sr));
}
if ((sr & USART_SR_TC) && (cr1 & USART_CR1_TCIE)) {
@ -328,8 +310,7 @@ static void serve_usart_irq(UARTDriver *uartp) {
u->CR1 = cr1 & ~USART_CR1_TCIE;
/* End of transmission, a callback is generated.*/
if (uartp->config->txend2_cb != NULL)
uartp->config->txend2_cb(uartp);
_uart_wakeup_tx2_isr(uartp);
}
}
@ -820,7 +801,7 @@ size_t uart_lld_stop_receive(UARTDriver *uartp) {
dmaStreamDisable(uartp->dmarx);
n = dmaStreamGetTransactionSize(uartp->dmarx);
set_rx_idle_loop(uartp);
uart_enter_rx_idle_loop(uartp);
return n;
}

View File

@ -524,6 +524,26 @@ struct UARTDriver {
* @brief Current configuration data.
*/
const UARTConfig *config;
#if UART_USE_WAIT || defined(__DOXYGEN__)
/**
* @brief Synchronization flag for transmit operations.
*/
bool early;
/**
* @brief Waiting thread on RX.
*/
thread_reference_t threadrx;
/**
* @brief Waiting thread on TX.
*/
thread_reference_t threadtx;
#endif /* UART_USE_WAIT */
#if UART_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
/**
* @brief Mutex protecting the peripheral.
*/
mutex_t mutex;
#endif /* UART_USE_MUTUAL_EXCLUSION */
#if defined(UART_DRIVER_EXT_FIELDS)
UART_DRIVER_EXT_FIELDS
#endif

View File

@ -179,7 +179,7 @@ static uartflags_t translate_errors(uint32_t isr) {
*
* @param[in] uartp pointer to the @p UARTDriver object
*/
static void set_rx_idle_loop(UARTDriver *uartp) {
static void uart_enter_rx_idle_loop(UARTDriver *uartp) {
uint32_t mode;
/* RX DMA channel preparation, if the char callback is defined then the
@ -243,7 +243,7 @@ static void usart_start(UARTDriver *uartp) {
u->CR1 = uartp->config->cr1 | cr1;
/* Starting the receiver idle loop.*/
set_rx_idle_loop(uartp);
uart_enter_rx_idle_loop(uartp);
}
/**
@ -266,23 +266,13 @@ static void uart_lld_serve_rx_end_irq(UARTDriver *uartp, uint32_t flags) {
if (uartp->rxstate == UART_RX_IDLE) {
/* Receiver in idle state, a callback is generated, if enabled, for each
received character and then the driver stays in the same state.*/
if (uartp->config->rxchar_cb != NULL)
uartp->config->rxchar_cb(uartp, uartp->rxbuf);
_uart_rx_idle_code(uartp);
}
else {
/* Receiver in active state, a callback is generated, if enabled, after
a completed transfer.*/
dmaStreamDisable(uartp->dmarx);
uartp->rxstate = UART_RX_COMPLETE;
if (uartp->config->rxend_cb != NULL)
uartp->config->rxend_cb(uartp);
/* If the callback didn't explicitly change state then the receiver
automatically returns to the idle state.*/
if (uartp->rxstate == UART_RX_COMPLETE) {
uartp->rxstate = UART_RX_IDLE;
set_rx_idle_loop(uartp);
}
_uart_rx_complete_isr_code(uartp);
}
}
@ -306,14 +296,7 @@ static void uart_lld_serve_tx_end_irq(UARTDriver *uartp, uint32_t flags) {
dmaStreamDisable(uartp->dmatx);
/* A callback is generated, if enabled, after a completed transfer.*/
uartp->txstate = UART_TX_COMPLETE;
if (uartp->config->txend1_cb != NULL)
uartp->config->txend1_cb(uartp);
/* If the callback didn't explicitly change state then the transmitter
automatically returns to the idle state.*/
if (uartp->txstate == UART_TX_COMPLETE)
uartp->txstate = UART_TX_IDLE;
_uart_wakeup_tx1_isr(uartp);
}
/**
@ -332,8 +315,7 @@ static void serve_usart_irq(UARTDriver *uartp) {
if (isr & (USART_ISR_LBDF | USART_ISR_ORE | USART_ISR_NE |
USART_ISR_FE | USART_ISR_PE)) {
if (uartp->config->rxerr_cb != NULL)
uartp->config->rxerr_cb(uartp, translate_errors(isr));
_uart_rx_error_isr_code(uartp, translate_errors(isr));
}
if ((isr & USART_ISR_TC) && (cr1 & USART_CR1_TCIE)) {
@ -341,8 +323,7 @@ static void serve_usart_irq(UARTDriver *uartp) {
u->CR1 = cr1 & ~USART_CR1_TCIE;
/* End of transmission, a callback is generated.*/
if (uartp->config->txend2_cb != NULL)
uartp->config->txend2_cb(uartp);
_uart_wakeup_tx2_isr(uartp);
}
}
@ -940,7 +921,7 @@ size_t uart_lld_stop_receive(UARTDriver *uartp) {
dmaStreamDisable(uartp->dmarx);
n = dmaStreamGetTransactionSize(uartp->dmarx);
set_rx_idle_loop(uartp);
uart_enter_rx_idle_loop(uartp);
return n;
}

View File

@ -623,6 +623,26 @@ struct UARTDriver {
* @brief Current configuration data.
*/
const UARTConfig *config;
#if UART_USE_WAIT || defined(__DOXYGEN__)
/**
* @brief Synchronization flag for transmit operations.
*/
bool early;
/**
* @brief Waiting thread on RX.
*/
thread_reference_t threadrx;
/**
* @brief Waiting thread on TX.
*/
thread_reference_t threadtx;
#endif /* UART_USE_WAIT */
#if UART_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
/**
* @brief Mutex protecting the peripheral.
*/
mutex_t mutex;
#endif /* UART_USE_MUTUAL_EXCLUSION */
#if defined(UART_DRIVER_EXT_FIELDS)
UART_DRIVER_EXT_FIELDS
#endif

View File

@ -67,10 +67,19 @@ void uartInit(void) {
*/
void uartObjectInit(UARTDriver *uartp) {
uartp->state = UART_STOP;
uartp->txstate = UART_TX_IDLE;
uartp->rxstate = UART_RX_IDLE;
uartp->config = NULL;
uartp->state = UART_STOP;
uartp->txstate = UART_TX_IDLE;
uartp->rxstate = UART_RX_IDLE;
uartp->config = NULL;
#if UART_USE_WAIT || defined(__DOXYGEN__)
uartp->early = false;
uartp->threadrx = NULL;
uartp->threadtx = NULL;
#endif /* UART_USE_WAIT */
#if UART_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
osalMutexObjectInit(&uartp->mutex);
#endif /* UART_USE_MUTUAL_EXCLUSION */
/* Optional, user-defined initializer.*/
#if defined(UART_DRIVER_EXT_INIT_HOOK)
UART_DRIVER_EXT_INIT_HOOK(uartp);
@ -233,7 +242,7 @@ size_t uartStopSendI(UARTDriver *uartp) {
* or equal to 8 bits else it is organized as uint16_t arrays.
*
* @param[in] uartp pointer to the @p UARTDriver object
* @param[in] n number of data frames to send
* @param[in] n number of data frames to receive
* @param[in] rxbuf the pointer to the receive buffer
*
* @api
@ -258,7 +267,7 @@ void uartStartReceive(UARTDriver *uartp, size_t n, void *rxbuf) {
* @note This function has to be invoked from a lock zone.
*
* @param[in] uartp pointer to the @p UARTDriver object
* @param[in] n number of data frames to send
* @param[in] n number of data frames to receive
* @param[out] rxbuf the pointer to the receive buffer
*
* @iclass
@ -333,6 +342,172 @@ size_t uartStopReceiveI(UARTDriver *uartp) {
return 0;
}
#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
/**
* @brief Performs a transmission on the UART peripheral.
* @note The function returns when the specified number of frames have been
* sent to the UART or on timeout.
* @note The buffers are organized as uint8_t arrays for data sizes below
* or equal to 8 bits else it is organized as uint16_t arrays.
*
* @param[in] uartp pointer to the @p UARTDriver object
* @param[in,out] np number of data frames to transmit, on exit the number
* of frames actually transmitted
* @param[in] txbuf the pointer to the transmit buffer
* @return The operation status.
* @retval MSG_OK if the operation completed successfully.
* @retval MSG_TIMEOUT if the operation timed out.
*
* @api
*/
msg_t uartSendTimeout(UARTDriver *uartp, size_t *np,
const void *txbuf, systime_t time) {
msg_t msg;
osalDbgCheck((uartp != NULL) && (*np > 0U) && (txbuf != NULL));
osalSysLock();
osalDbgAssert(uartp->state == UART_READY, "is active");
osalDbgAssert(uartp->txstate != UART_TX_ACTIVE, "tx active");
/* Transmission start.*/
uartp->early = true;
uart_lld_start_send(uartp, *np, txbuf);
uartp->txstate = UART_TX_ACTIVE;
/* Waiting for result.*/
msg = osalThreadSuspendTimeoutS(&uartp->threadtx, time);
if (msg != MSG_OK) {
*np = uartStopSendI(uartp);
}
osalSysUnlock();
return msg;
}
/**
* @brief Performs a transmission on the UART peripheral.
* @note The function returns when the specified number of frames have been
* physically transmitted or on timeout.
* @note The buffers are organized as uint8_t arrays for data sizes below
* or equal to 8 bits else it is organized as uint16_t arrays.
*
* @param[in] uartp pointer to the @p UARTDriver object
* @param[in,out] np number of data frames to transmit, on exit the number
* of frames actually transmitted
* @param[in] txbuf the pointer to the transmit buffer
* @return The operation status.
* @retval MSG_OK if the operation completed successfully.
* @retval MSG_TIMEOUT if the operation timed out.
*
* @api
*/
msg_t uartSendFullTimeout(UARTDriver *uartp, size_t *np,
const void *txbuf, systime_t time) {
msg_t msg;
osalDbgCheck((uartp != NULL) && (*np > 0U) && (txbuf != NULL));
osalSysLock();
osalDbgAssert(uartp->state == UART_READY, "is active");
osalDbgAssert(uartp->txstate != UART_TX_ACTIVE, "tx active");
/* Transmission start.*/
uartp->early = false;
uart_lld_start_send(uartp, *np, txbuf);
uartp->txstate = UART_TX_ACTIVE;
/* Waiting for result.*/
msg = osalThreadSuspendTimeoutS(&uartp->threadtx, time);
if (msg != MSG_OK) {
*np = uartStopSendI(uartp);
}
osalSysUnlock();
return msg;
}
/**
* @brief Performs a receive operation on the UART peripheral.
* @note The function returns when the specified number of frames have been
* received or on error/timeout.
* @note The buffers are organized as uint8_t arrays for data sizes below
* or equal to 8 bits else it is organized as uint16_t arrays.
*
* @param[in] uartp pointer to the @p UARTDriver object
* @param[in,out] np number of data frames to receive, on exit the number
* of frames actually received
* @param[in] rxbuf the pointer to the receive buffer
* @param[in] time operation timeout
*
* @return The operation status.
* @retval MSG_OK if the operation completed successfully.
* @retval MSG_TIMEOUT if the operation timed out.
* @retval MSG_RESET in case of a receive error.
*
* @api
*/
msg_t uartReceiveTimeout(UARTDriver *uartp, size_t *np,
void *rxbuf, systime_t time) {
msg_t msg;
osalDbgCheck((uartp != NULL) && (*np > 0U) && (rxbuf != NULL));
osalSysLock();
osalDbgAssert(uartp->state == UART_READY, "is active");
osalDbgAssert(uartp->rxstate != UART_RX_ACTIVE, "rx active");
/* Receive start.*/
uart_lld_start_receive(uartp, *np, rxbuf);
uartp->rxstate = UART_RX_ACTIVE;
/* Waiting for result.*/
msg = osalThreadSuspendTimeoutS(&uartp->threadrx, time);
if (msg != MSG_OK) {
*np = uartStopReceiveI(uartp);
}
osalSysUnlock();
return msg;
}
#endif
#if (UART_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
/**
* @brief Gains exclusive access to the UART bus.
* @details This function tries to gain ownership to the UART bus, if the bus
* is already being used then the invoking thread is queued.
* @pre In order to use this function the option @p UART_USE_MUTUAL_EXCLUSION
* must be enabled.
*
* @param[in] uartp pointer to the @p UARTDriver object
*
* @api
*/
void uartAcquireBus(UARTDriver *uartp) {
osalDbgCheck(uartp != NULL);
osalMutexLock(&uartp->mutex);
}
/**
* @brief Releases exclusive access to the UART bus.
* @pre In order to use this function the option @p UART_USE_MUTUAL_EXCLUSION
* must be enabled.
*
* @param[in] uartp pointer to the @p UARTDriver object
*
* @api
*/
void uartReleaseBus(UARTDriver *uartp) {
osalDbgCheck(uartp != NULL);
osalMutexUnlock(&uartp->mutex);
}
#endif
#endif /* HAL_USE_UART == TRUE */
/** @} */

View File

@ -143,6 +143,26 @@ struct UARTDriver {
* @brief Current configuration data.
*/
const UARTConfig *config;
#if UART_USE_WAIT || defined(__DOXYGEN__)
/**
* @brief Synchronization flag for transmit operations.
*/
bool early;
/**
* @brief Waiting thread on RX.
*/
thread_reference_t threadrx;
/**
* @brief Waiting thread on TX.
*/
thread_reference_t threadtx;
#endif /* UART_USE_WAIT */
#if UART_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
/**
* @brief Mutex protecting the peripheral.
*/
mutex_t mutex;
#endif /* UART_USE_MUTUAL_EXCLUSION */
#if defined(UART_DRIVER_EXT_FIELDS)
UART_DRIVER_EXT_FIELDS
#endif

View File

@ -76,6 +76,7 @@
- HAL: Introduced preliminary support for STM32F7xx devices.
- HAL: Introduced preliminary support for STM32L4xx devices.
- HAL: Introduced preliminary support for STM32L0xx devices.
- HAL: Added synchronous API and mutual exclusion to the UART driver.
- HAL: Added PAL driver for STM32L4xx GPIOv3 peripheral.
- HAL: Added I2S driver for STM32 SPIv2 peripheral.
- HAL: Added demos and board files for ST's Nucleo32 boards (F031, F042, F303).