git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@13812 27425a3e-05d8-49a3-a47f-9c15f0e5edd8

This commit is contained in:
Giovanni Di Sirio 2020-08-28 14:27:43 +00:00
parent c21bbe0fa0
commit 84119d5d52
4 changed files with 283 additions and 19 deletions

View File

@ -160,12 +160,12 @@ struct hal_sio_operation {
* @brief Receive buffer filled callback.
* @note Can be @p NULL.
*/
siocb_t rxne_cb;
siocb_t rx_cb;
/**
* @brief End of transmission buffer callback.
* @note Can be @p NULL.
*/
siocb_t txnf_cb;
siocb_t tx_cb;
/**
* @brief Physical end of transmission callback.
* @note Can be @p NULL.
@ -197,7 +197,7 @@ struct hal_sio_operation {
*
* @xclass
*/
#define sioRXIsEmptyX(siop) sio_lld_rx_is_empty(siop)
#define sioIsRXEmptyX(siop) sio_lld_is_rx_empty(siop)
/**
* @brief Determines the state of the TX FIFO.
@ -209,7 +209,7 @@ struct hal_sio_operation {
*
* @xclass
*/
#define sioTXIsFullX(siop) sio_lld_tx_is_full(siop)
#define sioIsTXFullX(siop) sio_lld_is_tx_full(siop)
/**
* @brief Returns one frame from the RX FIFO.
@ -218,9 +218,9 @@ struct hal_sio_operation {
* @param[in] siop pointer to the @p SIODriver object
* @return The frame from RX FIFO.
*
* @xclass
* @iclass
*/
#define sioRXGetX(siop) sio_lld_rx_get(siop)
#define sioGetI(siop) sio_lld_get(siop)
/**
* @brief Pushes one frame into the TX FIFO.
@ -229,9 +229,9 @@ struct hal_sio_operation {
* @param[in] siop pointer to the @p SIODriver object
* @param[in] data frame to be written
*
* @xclass
* @iclass
*/
#define sioTXPutX(siop, data) sio_lld_tx_put(siop, data)
#define sioPutI(siop, data) sio_lld_put(siop, data)
/**
* @brief Reads data from the RX FIFO.
@ -245,9 +245,9 @@ struct hal_sio_operation {
* @param[in] size maximum number of frames to read
* @return The number of received frames.
*
* @xclass
* @iclass
*/
#define sioReadX(siop, buffer, size) sio_lld_read(siop, buffer, size)
#define sioAsyncReadI(siop, buffer, size) sio_lld_read(siop, buffer, size)
/**
* @brief Writes data into the TX FIFO.
@ -261,9 +261,9 @@ struct hal_sio_operation {
* @param[in] size maximum number of frames to read
* @return The number of transmitted frames.
*
* @xclass
* @iclass
*/
#define sioWriteX(siop, buffer, size) sio_lld_write(siop, buffer, size)
#define sioAsyncWriteI(siop, buffer, size) sio_lld_write(siop, buffer, size)
/**
* @brief Control operation on a serial port.
@ -294,9 +294,13 @@ extern "C" {
void sioStop(SIODriver *siop);
void sioStartOperation(SIODriver *siop, const SIOOperation *operation);
void sioStopOperation(SIODriver *siop);
size_t sioAsyncRead(SIODriver *siop, size_t n, uint8_t *buffer);
size_t sioAsyncWrite(SIODriver *siop, size_t n, const uint8_t *buffer);
#if (HAL_SIO_USE_SYNCHRONIZATION == TRUE) || defined(__DOXYGEN__)
msg_t sioSynchronizeRX(SIODriver *siop);
msg_t sioSynchronizeTX(SIODriver *siop);
msg_t sioSynchronizeTXEnd(SIODriver *siop);
#endif
#ifdef __cplusplus
}
#endif

View File

@ -37,7 +37,7 @@
/**
* @brief SIO1 driver identifier.
*/
#if (PLATFORM_SIO_USE_SIO1 == TRUE) || defined(__DOXYGEN__)
#if (STM32_SIO_USE_USART1 == TRUE) || defined(__DOXYGEN__)
SIODriver SIOD1;
#endif
@ -64,7 +64,7 @@ SIODriver SIOD1;
*/
void sio_lld_init(void) {
#if PLATFORM_SIO_USE_SIO1 == TRUE
#if STM32_SIO_USE_USART1 == TRUE
/* Driver initialization.*/
sioObjectInit(&SIOD1);
#endif
@ -84,7 +84,7 @@ bool sio_lld_start(SIODriver *siop) {
if (siop->state == SIO_STOP) {
/* Enables the peripheral.*/
#if PLATFORM_SIO_USE_SIO1 == TRUE
#if STM32_SIO_USE_USART1 == TRUE
if (&SIOD1 == siop) {
}
@ -108,13 +108,91 @@ void sio_lld_stop(SIODriver *siop) {
/* Resets the peripheral.*/
/* Disables the peripheral.*/
#if PLATFORM_SIO_USE_SIO1 == TRUE
#if STM32_SIO_USE_USART1 == TRUE
if (&SIOD1 == siop) {
}
#endif
}
}
/**
* @brief Reads data from the RX FIFO.
* @details The function is not blocking, it writes frames until there
* is space available without waiting.
*
* @param[in] siop pointer to an @p SIODriver structure
* @param[in] n maximum number of frames to be read
* @param[in] buf pointer to the buffer for read frames
* @return The number of frames copied from the buffer.
* @retval 0 if the TX FIFO is full.
*/
size_t sio_lld_read(SIODriver *siop, size_t n, uint8_t *buf) {
size_t rd;
rd = 0U;
while (true) {
#if USART_ENABLE_INTERRUPTS == TRUE
/* If the RX FIFO has been emptied then the interrupt is enabled again.*/
if (sio_lld_is_rx_empty(siop)) {
siop->usart->CR3 |= USART_CR3_RXFTIE;
break;
}
#endif
/* Buffer filled condition.*/
if (rd > n) {
break;
}
*buf++ = (uint8_t)siop->usart->RDR;
rd++;
}
return n - rd;
}
/**
* @brief Writes data into the TX FIFO.
* @details The function is not blocking, it writes frames until there
* is space available without waiting.
*
* @param[in] siop pointer to an @p SIODriver structure
* @param[in] n maximum number of frames to be written
* @param[in] buf pointer to the buffer for read frames
* @return The number of frames copied from the buffer.
* @retval 0 if the TX FIFO is full.
*/
size_t sio_lld_write(SIODriver *siop, size_t n, const uint8_t *buf) {
size_t wr;
wr = 0U;
while (true) {
#if USART_ENABLE_INTERRUPTS == TRUE
/* If the TX FIFO has been filled then the interrupt is enabled again.*/
if (sio_lld_is_tx_full(siop)) {
siop->usart->CR3 |= USART_CR3_TXFTIE;
break;
}
#endif
/* Buffer emptied condition.*/
if (wr >= n) {
break;
}
siop->usart->TDR = (uint32_t)*buf++;
wr++;
}
#if USART_ENABLE_INTERRUPTS == TRUE
/* The transmit complete interrupt is always re-enabled on write.*/
siop->usart->CR1 |= USART_CR1_TCIE;
#endif
return n - wr;
}
/**
* @brief Control operation on a serial port.

View File

@ -44,8 +44,8 @@
* @details If set to @p TRUE the support for SIO1 is included.
* @note The default is @p FALSE.
*/
#if !defined(PLATFORM_SIO_USE_SIO1) || defined(__DOXYGEN__)
#define PLATFORM_SIO_USE_SIO1 FALSE
#if !defined(STM32_SIO_USE_USART1) || defined(__DOXYGEN__)
#define STM32_SIO_USE_USART1 FALSE
#endif
/** @} */
@ -133,7 +133,7 @@
/* External declarations. */
/*===========================================================================*/
#if (PLATFORM_SIO_USE_SIO1 == TRUE) && !defined(__DOXYGEN__)
#if (STM32_SIO_USE_USART1 == TRUE) && !defined(__DOXYGEN__)
extern SIODriver SIOD1;
#endif

View File

@ -129,6 +129,188 @@ void sioStop(SIODriver *siop) {
osalSysUnlock();
}
/**
* @brief Starts n SIO operation.
*
* @param[in] siop pointer to an @p SIODriver structure
* @param[in] operation pointer to an @p SIOOperation structure
* encoding the operation to be performed
*/
void sioStartOperation(SIODriver *siop, const SIOOperation *operation) {
osalDbgCheck((siop != NULL) && (operation != NULL));
osalSysLock();
osalDbgAssert(siop->state == SIO_READY, "invalid state");
siop->operation = operation;
siop->state = SIO_ACTIVE;
sio_lld_start_operation(siop);
osalSysUnlock();
}
/**
* @brief Stops an ongoing SIO operation, if any.
*
* @param[in] siop pointer to an @p SIODriver structure
*/
void sioStopOperation(SIODriver *siop) {
osalDbgCheck(siop != NULL);
osalSysLock();
osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state");
sio_lld_stop_operation(siop);
siop->operation = NULL;
siop->state = SIO_READY;
osalSysUnlock();
}
/**
* @brief Reads data from the RX FIFO.
* @details This function is non-blocking, data is read if present and the
* effective amount is returned.
* @note This function can be called from any context but it is meant to
* be called from the @p rxne_cb callback handler.
*
* @param[in] siop pointer to the @p SIODriver object
* @param[in] buffer buffer for the received data
* @param[in] size maximum number of frames to read
* @return The number of received frames.
*
* @api
*/
size_t sioAsyncReadI(SIODriver *siop, size_t n, uint8_t *buffer) {
osalDbgCheck((siop != NULL) && (buf != NULL));
osalSysLock();
n = sioAsyncReadI(siop, n, buffer);
osalSysUnlock();
return n;
}
/**
* @brief Writes data into the TX FIFO.
* @details This function is non-blocking, data is written if there is space
* in the FIFO and the effective amount is returned.
* @note This function can be called from any context but it is meant to
* be called from the @p txnf_cb callback handler.
*
* @param[in] siop pointer to the @p SIODriver object
* @param[out] buffer buffer containing the data to be transmitted
* @param[in] size maximum number of frames to read
* @return The number of transmitted frames.
*
* @api
*/
size_t sioAsyncWrite(SIODriver *siop, size_t n, const uint8_t *buffer) {
osalDbgCheck((siop != NULL) && (buf != NULL));
osalSysLock();
n = sioAsyncWriteI(siop, n, buffer);
osalSysUnlock();
return n;
}
#if (HAL_SIO_USE_SYNCHRONIZATION == TRUE) || defined(__DOXYGEN__)
/**
* @brief Synchronizes with RX FIFO data availability.
* @note The exact behavior depends on low level FIFO settings such
* as thresholds, etc.
* @note This function can only be called by a single thread at time.
*
* @param[in] siop pointer to an @p SIODriver structure
* @param[in] timeout synchronization timeout
* @return The synchronization result.
* @retval MSG_OK if there is space in the TX FIFO.
* @retval MSG_TIMEOUT if synchronization timed out.
*/
msg_t sioSynchronizeRX(SIODriver *siop) {
osalDbgCheck(siop != NULL);
osalSysLock();
osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state");
if (sio_lld_is_rx_empty(siop)) {
msg = osalThdSuspendTimeoutS(&siop->sync_rx, timeout);
}
else {
msg = MSG_OK;
}
osalSysUnlock();
}
/**
* @brief Synchronizes with TX FIFO space availability.
* @note The exact behavior depends on low level FIFO settings such
* as thresholds, etc.
* @note This function can only be called by a single thread at time.
*
* @param[in] siop pointer to an @p SIODriver structure
* @param[in] timeout synchronization timeout
* @return The synchronization result.
* @retval MSG_OK if there is space in the TX FIFO.
* @retval MSG_TIMEOUT if synchronization timed out.
*/
msg_t sioSynchronizeTX(SIODriver *siop) {
osalDbgCheck(siop != NULL);
osalSysLock();
osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state");
osalSysUnlock();
}
/**
* @brief Synchronizes with TX completion.
* @note This function can only be called by a single thread at time.
*
* @param[in] siop pointer to an @p SIODriver structure
* @param[in] timeout synchronization timeout
* @return The synchronization result.
* @retval MSG_OK if TX operation finished.
* @retval MSG_TIMEOUT if synchronization timed out.
*/
msg_t sioSynchronizeTXEnd(SIODriver *siop) {
osalDbgCheck(siop != NULL);
osalSysLock();
osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state");
if (sio_lld_is_tx_ongoing(siop)) {
msg = osalThdSuspendTimeoutS(&siop->sync_txend, timeout);
}
else {
msg = MSG_OK;
}
osalSysUnlock();
}
#endif /* HAL_SIO_USE_SYNCHRONIZATION == TRUE */
#endif /* HAL_USE_SIO == TRUE */
/** @} */