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:
parent
6e72cb497c
commit
61b839a7c6
|
@ -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. */
|
||||
/*===========================================================================*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue