Given optional stream interface to SIO driver.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@13817 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2020-08-30 14:03:57 +00:00
parent 6e72cb497c
commit 61b839a7c6
3 changed files with 242 additions and 42 deletions

View File

@ -121,12 +121,33 @@ struct hal_sio_config {
sio_lld_config_fields;
};
/**
* @brief @p SIODriver specific methods.
*/
#define _sio_driver_methods \
_base_channel_methods
/**
* @extends BaseChannelVMT
*
* @brief @p SIODriver virtual methods table.
*/
struct sio_driver_vmt {
_sio_driver_methods
};
/**
* @brief Structure representing a SIO driver.
* @note Implementations may extend this structure to contain more,
* architecture dependent, fields.
*/
struct hal_sio_driver {
#if (HAL_SIO_USE_SYNCHRONIZATION == TRUE) || defined(__DOXYGEN__)
/**
* @brief Virtual Methods Table.
*/
const struct sio_driver_vmt *vmt;
#endif
/**
* @brief Driver state.
*/
@ -294,6 +315,120 @@ struct hal_sio_operation {
*/
#define sioControlX(siop, operation, arg) sio_lld_control(siop, operation, arg)
/**
* @name Low level driver helper macros
* @{
*/
/**
* @brief RX callback.
*
* @param[in] siop pointer to the @p SIODriver object
*
* @notapi
*/
#define __sio_callback_rx(siop) { \
if ((siop)->operation->rx_cb != NULL) { \
(siop)->operation->rx_cb(siop); \
} \
}
/**
* @brief RX idle callback.
*
* @param[in] siop pointer to the @p SIODriver object
*
* @notapi
*/
#define __sio_callback_rx_idle(siop) { \
if ((siop)->operation->rx_idle_cb != NULL) { \
(siop)->operation->rx_idle_cb(siop); \
} \
}
/**
* @brief TX callback.
*
* @param[in] siop pointer to the @p SIODriver object
*
* @notapi
*/
#define __sio_callback_tx(siop) { \
if ((siop)->operation->tx_cb != NULL) { \
(siop)->operation->tx_cb(siop); \
} \
}
/**
* @brief TX end callback.
*
* @param[in] siop pointer to the @p SIODriver object
*
* @notapi
*/
#define __sio_callback_tx_end(siop) { \
if ((siop)->operation->tx_end_cb != NULL) { \
(siop)->operation->tx_end_cb(siop); \
} \
}
/**
* @brief RX event callback.
*
* @param[in] siop pointer to the @p SIODriver object
*
* @notapi
*/
#define __sio_callback_rx_evt(siop) { \
if ((siop)->operation->rx_evt_cb != NULL) { \
(siop)->operation->rx_evt_cb(siop); \
} \
}
#if (HAL_SIO_USE_SYNCHRONIZATION == TRUE) || defined(__DOXYGEN__)
/**
* @brief Wakes up the RX-waiting thread.
*
* @param[in] siop pointer to the @p SIODriver object
*
* @notapi
*/
#define __sio_wakeup_rx(siop, msg) { \
osalSysLockFromISR(); \
osalThreadResumeI(&(siop)->sync_rx, msg); \
osalSysUnlockFromISR(); \
}
/**
* @brief Wakes up the TX-waiting thread.
*
* @param[in] siop pointer to the @p SIODriver object
*
* @notapi
*/
#define __sio_wakeup_tx(siop, msg) { \
osalSysLockFromISR(); \
osalThreadResumeI(&(siop)->sync_tx, msg); \
osalSysUnlockFromISR(); \
}
/**
* @brief Wakes up the TXend-waiting thread.
*
* @param[in] siop pointer to the @p SIODriver object
*
* @notapi
*/
#define __sio_wakeup_txend(siop, msg) { \
osalSysLockFromISR(); \
osalThreadResumeI(&(siop)->sync_txend, msg); \
osalSysUnlockFromISR(); \
}
#else /* !HAL_SIO_USE_SYNCHRONIZATION */
#define __sio_wakeup_rx(siop, msg)
#define __sio_wakeup_tx(siop, msg)
#define __sio_wakeup_txend(siop, msg)
#endif /* !HAL_SIO_USE_SYNCHRONIZATION */
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/

View File

@ -601,16 +601,10 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
siop->events |= evtmask;
/* The callback is invoked if defined.*/
if (siop->operation->rx_evt_cb != NULL) {
siop->operation->rx_evt_cb(siop);
}
__sio_callback_rx_evt(siop);
#if HAL_SIO_USE_SYNCHRONIZATION == TRUE
/* Waiting thread woken, if any.*/
osalSysLockFromISR();
osalThreadResumeI(&siop->sync_rx, SIO_MSG_ERRORS);
osalSysUnlockFromISR();
#endif
__sio_wakeup_rx(siop, SIO_MSG_ERRORS);
}
/* RX FIFO is non-empty.*/
@ -618,16 +612,10 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
(isr & USART_ISR_RXFT) != 0U) {
/* The callback is invoked if defined.*/
if (siop->operation->rx_cb != NULL) {
siop->operation->rx_cb(siop);
}
__sio_callback_rx(siop);
#if HAL_SIO_USE_SYNCHRONIZATION == TRUE
/* Waiting thread woken, if any.*/
osalSysLockFromISR();
osalThreadResumeI(&siop->sync_rx, MSG_OK);
osalSysUnlockFromISR();
#endif
__sio_wakeup_rx(siop, MSG_OK);
/* Called once then the interrupt source is disabled.*/
cr3 &= ~USART_CR3_RXFTIE;
@ -638,16 +626,10 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
(isr & USART_ISR_IDLE) != 0U) {
/* The callback is invoked if defined.*/
if (siop->operation->rx_idle_cb != NULL) {
siop->operation->rx_idle_cb(siop);
}
__sio_callback_rx_idle(siop);
#if HAL_SIO_USE_SYNCHRONIZATION == TRUE
/* Waiting thread woken, if any.*/
osalSysLockFromISR();
osalThreadResumeI(&siop->sync_rx, SIO_MSG_IDLE);
osalSysUnlockFromISR();
#endif
__sio_wakeup_rx(siop, SIO_MSG_IDLE);
}
/* TX FIFO is non-full.*/
@ -655,16 +637,10 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
(isr & USART_ISR_TXFT) != 0U) {
/* The callback is invoked if defined.*/
if (siop->operation->tx_cb != NULL) {
siop->operation->tx_cb(siop);
}
__sio_callback_tx(siop);
#if HAL_SIO_USE_SYNCHRONIZATION == TRUE
/* Waiting thread woken, if any.*/
osalSysLockFromISR();
osalThreadResumeI(&siop->sync_tx, MSG_OK);
osalSysUnlockFromISR();
#endif
__sio_wakeup_tx(siop, MSG_OK);
/* Called once then the interrupt is disabled.*/
cr3 &= ~USART_CR3_TXFTIE;
@ -675,16 +651,10 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
(isr & USART_ISR_TC) != 0U) {
/* The callback is invoked if defined.*/
if (siop->operation->tx_end_cb != NULL) {
siop->operation->tx_end_cb(siop);
}
__sio_callback_tx_end(siop);
#if HAL_SIO_USE_SYNCHRONIZATION == TRUE
/* Waiting thread woken, if any.*/
osalSysLockFromISR();
osalThreadResumeI(&siop->sync_txend, MSG_OK);
osalSysUnlockFromISR();
#endif
__sio_wakeup_txend(siop, MSG_OK);
/* Called once then the interrupt is disabled.*/
cr1 &= ~USART_CR1_TCIE;

View File

@ -42,6 +42,98 @@
/* Driver local functions. */
/*===========================================================================*/
#if (HAL_SIO_USE_SYNCHRONIZATION == TRUE) || defined(__DOXYGEN__)
/*
* Interface implementation, the following functions just invoke the equivalent
* queue-level function or macro.
*/
static size_t __write(void *ip, const uint8_t *bp, size_t n) {
SIODriver *siop = (SIODriver *)ip;
sioSynchronizeTX(siop, TIME_INFINITE);
return sioAsyncWrite(siop, n, bp);
}
static size_t __read(void *ip, uint8_t *bp, size_t n) {
SIODriver *siop = (SIODriver *)ip;
sioSynchronizeRX(siop, TIME_INFINITE);
return sioAsyncRead(siop, n, bp);
}
static msg_t __put(void *ip, uint8_t b) {
SIODriver *siop = (SIODriver *)ip;
sioSynchronizeTX(siop, TIME_INFINITE);
sioPut(b);
return MSG_OK;
}
static msg_t __get(void *ip) {
SIODriver *siop = (SIODriver *)ip;
sioSynchronizeRX(siop, TIME_INFINITE);
return sioGet();
}
static msg_t __putt(void *ip, uint8_t b, sysinterval_t timeout) {
SIODriver *siop = (SIODriver *)ip;
sioSynchronizeTX(siop, timeout);
sioPut(b);
return MSG_OK;
}
static msg_t __gett(void *ip, sysinterval_t timeout) {
SIODriver *siop = (SIODriver *)ip;
sioSynchronizeRX(siop, timeout);
return sioGet();
}
static size_t __writet(void *ip, const uint8_t *bp, size_t n,
sysinterval_t timeout) {
SIODriver *siop = (SIODriver *)ip;
sioSynchronizeTX(siop, timeout);
return sioAsyncWrite(siop, n, bp);
}
static size_t __readt(void *ip, uint8_t *bp, size_t n,
sysinterval_t timeout) {
SIODriver *siop = (SIODriver *)ip;
sioSynchronizeRX(siop, timeout);
return sioAsyncRead(siop, n, bp);
}
static msg_t __ctl(void *ip, unsigned int operation, void *arg) {
SIODriver *siop = (SIODriver *)ip;
osalDbgCheck(siop != NULL);
switch (operation) {
case CHN_CTL_NOP:
osalDbgCheck(arg == NULL);
break;
case CHN_CTL_INVALID:
osalDbgAssert(false, "invalid CTL operation");
break;
default:
break;
}
return MSG_OK;
}
static const struct sio_driver_vmt vmt = {
(size_t)0,
__write, __read, __put, __get,
__putt, __gett, __writet, __readt,
__ctl
};
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
@ -67,8 +159,11 @@ void sioInit(void) {
*/
void sioObjectInit(SIODriver *siop) {
siop->state = SIO_STOP;
siop->config = NULL;
#if HAL_SIO_USE_SYNCHRONIZATION == TRUE
siop->vmt = &vmt;
#endif
siop->state = SIO_STOP;
siop->config = NULL;
/* Optional, user-defined initializer.*/
#if defined(SIO_DRIVER_EXT_INIT_HOOK)