SIO simplified. Added a "BufferedSIODriver" class that implements the behavior of the legacy Serial driver on top of a SIO implementation (buffering, events and all).
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@15727 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
parent
7134a34b9b
commit
8c025f78c0
|
@ -73,7 +73,6 @@ void c1_main(void) {
|
|||
* Activates the UART0 SIO driver using the default configuration.
|
||||
*/
|
||||
sioStart(&SIOD0, NULL);
|
||||
sioStartOperation(&SIOD0, NULL);
|
||||
|
||||
/*
|
||||
* Creates the timer thread.
|
||||
|
|
|
@ -161,7 +161,7 @@ static inline void __buffered_serial_objinit_impl(void *ip, const void *vmt,
|
|||
qnotify_t onotify, void *oarg) {
|
||||
BufferedSerial *bsp = (BufferedSerial *)ip;
|
||||
|
||||
bsp->vmt = (const struct BufferedSerialVMT *)&vmt; /* TODO use new obj model.*/
|
||||
bsp->vmt = (const struct BufferedSerialVMT *)vmt; /* TODO use new obj model.*/
|
||||
osalEventObjectInit(&bsp->event); /* TODO super class should do this.*/
|
||||
bsp->state = BS_STOP;
|
||||
iqObjectInit(&bsp->iqueue, ib, ibsize, inotify, iarg);
|
||||
|
|
|
@ -194,11 +194,6 @@ typedef struct hal_sio_driver SIODriver;
|
|||
*/
|
||||
typedef struct hal_sio_config SIOConfig;
|
||||
|
||||
/**
|
||||
* @brief Type of structure representing a SIO operation.
|
||||
*/
|
||||
typedef struct hal_sio_operation SIOOperation;
|
||||
|
||||
/**
|
||||
* @brief Generic SIO notification callback type.
|
||||
*
|
||||
|
@ -213,7 +208,6 @@ typedef enum {
|
|||
SIO_UNINIT = 0, /**< Not initialized. */
|
||||
SIO_STOP = 1, /**< Stopped. */
|
||||
SIO_READY = 2, /**< Ready. */
|
||||
SIO_ACTIVE = 3 /**< Operation ongoing. */
|
||||
} siostate_t;
|
||||
|
||||
#include "hal_sio_lld.h"
|
||||
|
@ -271,9 +265,10 @@ struct hal_sio_driver {
|
|||
*/
|
||||
sioflags_t enabled;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
* @brief Events callback.
|
||||
* @note Can be @p NULL.
|
||||
*/
|
||||
const SIOOperation *operation;
|
||||
siocb_t cb;
|
||||
/**
|
||||
* @brief User argument to the operation.
|
||||
* @note Can be retrieved through the @p siop argument of the callback.
|
||||
|
@ -304,24 +299,18 @@ struct hal_sio_driver {
|
|||
sio_lld_driver_fields;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure representing a SIO operation.
|
||||
*/
|
||||
struct hal_sio_operation {
|
||||
/**
|
||||
* @brief Events callback.
|
||||
* @note Can be @p NULL.
|
||||
*/
|
||||
siocb_t cb;
|
||||
#if defined(SIO_OPERATION_EXT_FIELS)
|
||||
SIO_OPERATION_EXT_FIELS
|
||||
#endif
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Associates a callback to te SIO instance.
|
||||
*
|
||||
* @param[in] siop pointer to the @p SIODriver object
|
||||
* @param[in] f callback to be associated
|
||||
*/
|
||||
#define sioSetCallbackX(siop, f) (siop)->cb = (f)
|
||||
|
||||
/**
|
||||
* @brief Determines the state of the RX FIFO.
|
||||
*
|
||||
|
@ -384,10 +373,10 @@ struct hal_sio_operation {
|
|||
#define sioIsTXOngoingX(siop) sio_lld_is_tx_ongoing(siop)
|
||||
|
||||
/**
|
||||
* @brief Writes the condition flags mask.
|
||||
* @brief Writes the enabled events mask.
|
||||
*
|
||||
* @param[in] siop pointer to the @p SIODriver object
|
||||
* @param[in] flags flags mask to be written
|
||||
* @param[in] flags enabled events mask to be written
|
||||
*
|
||||
* @iclass
|
||||
*/
|
||||
|
@ -397,10 +386,10 @@ struct hal_sio_operation {
|
|||
} while (false)
|
||||
|
||||
/**
|
||||
* @brief Enables flags to the condition flags mask.
|
||||
* @brief Sets flags into the enabled events flags mask.
|
||||
*
|
||||
* @param[in] siop pointer to the @p SIODriver object
|
||||
* @param[in] flags flags mask to be enabled
|
||||
* @param[in] flags enabled events mask to be set
|
||||
*
|
||||
* @iclass
|
||||
*/
|
||||
|
@ -410,10 +399,10 @@ struct hal_sio_operation {
|
|||
} while (false)
|
||||
|
||||
/**
|
||||
* @brief Disables flags from the condition flags mask.
|
||||
* @brief Clears flags from the enabled events flags mask.
|
||||
*
|
||||
* @param[in] siop pointer to the @p SIODriver object
|
||||
* @param[in] flags flags mask to be disabled
|
||||
* @param[in] flags enabled events mask to be cleared
|
||||
*
|
||||
* @iclass
|
||||
*/
|
||||
|
@ -533,8 +522,8 @@ struct hal_sio_operation {
|
|||
* @notapi
|
||||
*/
|
||||
#define __sio_callback(siop) do { \
|
||||
if ((siop)->operation->cb != NULL) { \
|
||||
(siop)->operation->cb(siop); \
|
||||
if ((siop)->cb != NULL) { \
|
||||
(siop)->cb(siop); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
|
@ -634,10 +623,6 @@ extern "C" {
|
|||
void sioObjectInit(SIODriver *siop);
|
||||
msg_t sioStart(SIODriver *siop, const SIOConfig *config);
|
||||
void sioStop(SIODriver *siop);
|
||||
void sioStartOperationI(SIODriver *siop, const SIOOperation *operation);
|
||||
void sioStartOperation(SIODriver *siop, const SIOOperation *operation);
|
||||
void sioStopOperationI(SIODriver *siop);
|
||||
void sioStopOperation(SIODriver *siop);
|
||||
void sioWriteEnableFlags(SIODriver *siop, sioflags_t flags);
|
||||
void sioSetEnableFlags(SIODriver *siop, sioflags_t flags);
|
||||
void sioClearEnableFlags(SIODriver *siop, sioflags_t flags);
|
||||
|
|
|
@ -40,11 +40,6 @@
|
|||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static void __bsio_default_cb(SIODriver *siop);
|
||||
static const SIOOperation __bsio_default_operation = {
|
||||
.cb = __bsio_default_cb
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
@ -208,15 +203,10 @@ msg_t bsioStart(BufferedSIODriver *bsiop, const BufferedSIOConfig *config) {
|
|||
osalDbgAssert((bsiop->state == BS_STOP) || (bsiop->state == BS_READY),
|
||||
"invalid state");
|
||||
|
||||
/* Stopping current operation, if any.*/
|
||||
if (bsiop->siop->state == SIO_ACTIVE) {
|
||||
sioStopOperation(bsiop->siop);
|
||||
}
|
||||
|
||||
msg = sioStart(bsiop->siop, config);
|
||||
if (msg == HAL_RET_SUCCESS) {
|
||||
osalSysLock();
|
||||
sioStartOperationI(bsiop->siop, &__bsio_default_operation);
|
||||
sioSetCallbackX(bsiop->siop, &__bsio_default_cb);
|
||||
sioWriteEnableFlagsI(bsiop->siop, SIO_FL_ALL);
|
||||
bsiop->state = BS_READY;
|
||||
osalSysUnlock();
|
||||
|
@ -244,9 +234,6 @@ void bsioStop(BufferedSIODriver *bsiop) {
|
|||
osalDbgAssert((bsiop->state == BS_STOP) || (bsiop->state == BS_READY),
|
||||
"invalid state");
|
||||
|
||||
/* Stopping current operation, if any.*/
|
||||
sioStopOperation(bsiop->siop);
|
||||
|
||||
/* Stopping undelying SIO driver.*/
|
||||
sioStop(bsiop->siop);
|
||||
|
||||
|
|
|
@ -126,6 +126,11 @@ __STATIC_INLINE void uart_init(SIODriver *siop) {
|
|||
/* Registers settings, the LCR_H write also latches dividers values.*/
|
||||
siop->uart->UARTLCR_H = siop->config->UARTLCR_H & ~UART_LCRH_CFG_FORBIDDEN;
|
||||
siop->uart->UARTCR = siop->config->UARTCR & ~UART_CR_CFG_FORBIDDEN;
|
||||
|
||||
/* Setting up the operation.*/
|
||||
siop->uart->UARTICR = siop->uart->UARTRIS;
|
||||
siop->uart->UARTCR = siop->config->UARTCR |
|
||||
UART_UARTCR_RXE | UART_UARTCR_TXE | UART_UARTCR_UARTEN;
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
|
@ -240,35 +245,6 @@ void sio_lld_stop(SIODriver *siop) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts a SIO operation.
|
||||
*
|
||||
* @param[in] siop pointer to an @p SIODriver structure
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void sio_lld_start_operation(SIODriver *siop) {
|
||||
|
||||
/* Setting up the operation.*/
|
||||
siop->uart->UARTICR = siop->uart->UARTRIS;
|
||||
siop->uart->UARTCR = siop->config->UARTCR |
|
||||
UART_UARTCR_RXE | UART_UARTCR_TXE | UART_UARTCR_UARTEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops an ongoing SIO operation, if any.
|
||||
*
|
||||
* @param[in] siop pointer to an @p SIODriver structure
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void sio_lld_stop_operation(SIODriver *siop) {
|
||||
|
||||
/* Stop operation.*/
|
||||
siop->uart->UARTIMSC = 0U;
|
||||
siop->uart->UARTCR = siop->config->UARTCR & ~UART_CR_CFG_FORBIDDEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable flags change notification.
|
||||
*
|
||||
|
@ -513,7 +489,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
|
|||
UART_TypeDef *u = siop->uart;
|
||||
uint32_t mis, imsc;
|
||||
|
||||
osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state");
|
||||
osalDbgAssert(siop->state == SIO_READY, "invalid state");
|
||||
|
||||
/* Note, ISR flags are just read but not cleared, ISR sources are
|
||||
disabled instead.*/
|
||||
|
@ -589,10 +565,9 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
|
|||
|
||||
/* The callback is invoked.*/
|
||||
__sio_callback(siop);
|
||||
|
||||
}
|
||||
else {
|
||||
osalDbgAssert(false, "spurious interrupt");
|
||||
// osalDbgAssert(false, "spurious interrupt");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -211,8 +211,6 @@ extern "C" {
|
|||
void sio_lld_init(void);
|
||||
msg_t sio_lld_start(SIODriver *siop);
|
||||
void sio_lld_stop(SIODriver *siop);
|
||||
void sio_lld_start_operation(SIODriver *siop);
|
||||
void sio_lld_stop_operation(SIODriver *siop);
|
||||
void sio_lld_update_enable_flags(SIODriver *siop);
|
||||
sioevents_t sio_lld_get_and_clear_errors(SIODriver *siop);
|
||||
sioevents_t sio_lld_get_and_clear_events(SIODriver *siop);
|
||||
|
|
|
@ -214,6 +214,10 @@ __STATIC_INLINE void usart_init(SIODriver *siop) {
|
|||
u->CR1 = siop->config->cr1 & ~USART_CR1_CFG_FORBIDDEN;
|
||||
u->CR2 = siop->config->cr2 & ~USART_CR2_CFG_FORBIDDEN;
|
||||
u->CR3 = siop->config->cr3 & ~USART_CR3_CFG_FORBIDDEN;
|
||||
|
||||
/* Starting operations.*/
|
||||
u->ICR = u->ISR;
|
||||
u->CR1 |= USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
|
@ -447,35 +451,6 @@ void sio_lld_stop(SIODriver *siop) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts a SIO operation.
|
||||
*
|
||||
* @param[in] siop pointer to an @p SIODriver structure
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void sio_lld_start_operation(SIODriver *siop) {
|
||||
|
||||
/* Setting up the operation.*/
|
||||
siop->usart->ICR = siop->usart->ISR;
|
||||
siop->usart->CR1 |= USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops an ongoing SIO operation, if any.
|
||||
*
|
||||
* @param[in] siop pointer to an @p SIODriver structure
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void sio_lld_stop_operation(SIODriver *siop) {
|
||||
|
||||
/* Stop operation.*/
|
||||
siop->usart->CR1 &= ~USART_CR1_CFG_FORBIDDEN;
|
||||
siop->usart->CR2 &= ~USART_CR2_CFG_FORBIDDEN;
|
||||
siop->usart->CR3 &= ~USART_CR3_CFG_FORBIDDEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable flags change notification.
|
||||
*
|
||||
|
@ -736,7 +711,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
|
|||
uint32_t isr, isrmask;
|
||||
uint32_t cr1, cr2, cr3;
|
||||
|
||||
osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state");
|
||||
osalDbgAssert(siop->state == SIO_READY, "invalid state");
|
||||
|
||||
/* Read on control registers.*/
|
||||
cr1 = u->CR1;
|
||||
|
@ -758,7 +733,8 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
|
|||
|
||||
/* Note, ISR flags are just read but not cleared, ISR sources are
|
||||
disabled instead.*/
|
||||
isr = u->ISR & isrmask;
|
||||
isr = u->ISR;
|
||||
isr = isr & isrmask;
|
||||
if (isr != 0U) {
|
||||
|
||||
/* Error events handled as a group, except ORE.*/
|
||||
|
@ -768,7 +744,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
|
|||
#if SIO_USE_SYNCHRONIZATION
|
||||
/* The idle flag is forcibly cleared when an RX error event is
|
||||
detected.*/
|
||||
u->ICR = USART_ISR_IDLE;
|
||||
u->ICR = USART_ICR_IDLECF;
|
||||
#endif
|
||||
|
||||
/* Interrupt sources disabled.*/
|
||||
|
@ -796,7 +772,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
|
|||
#if SIO_USE_SYNCHRONIZATION
|
||||
/* The idle flag is forcibly cleared when an RX data event is
|
||||
detected.*/
|
||||
u->ICR = USART_ISR_IDLE;
|
||||
u->ICR = USART_ICR_IDLECF;
|
||||
#endif
|
||||
|
||||
/* Interrupt source disabled.*/
|
||||
|
@ -835,7 +811,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
|
|||
__sio_callback(siop);
|
||||
}
|
||||
else {
|
||||
osalDbgAssert(false, "spurious interrupt");
|
||||
// osalDbgAssert(false, "spurious interrupt");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -396,8 +396,6 @@ extern "C" {
|
|||
void sio_lld_init(void);
|
||||
msg_t sio_lld_start(SIODriver *siop);
|
||||
void sio_lld_stop(SIODriver *siop);
|
||||
void sio_lld_start_operation(SIODriver *siop);
|
||||
void sio_lld_stop_operation(SIODriver *siop);
|
||||
void sio_lld_update_enable_flags(SIODriver *siop);
|
||||
sioevents_t sio_lld_get_and_clear_errors(SIODriver *siop);
|
||||
sioevents_t sio_lld_get_and_clear_events(SIODriver *siop);
|
||||
|
|
|
@ -147,7 +147,7 @@ static const SIOConfig default_config = {
|
|||
.presc = USART_PRESC1,
|
||||
.cr1 = USART_CR1_DATA8 | USART_CR1_OVER16,
|
||||
.cr2 = USART_CR2_STOP1_BITS,
|
||||
.cr3 = USART_CR3_TXFTCFG_1H | USART_CR3_RXFTCFG_NONEMPTY
|
||||
.cr3 = USART_CR3_TXFTCFG_NONFULL | USART_CR3_RXFTCFG_NONEMPTY
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
|
@ -234,6 +234,10 @@ __STATIC_INLINE void usart_init(SIODriver *siop) {
|
|||
u->CR1 = (siop->config->cr1 & ~USART_CR1_CFG_FORBIDDEN) | USART_CR1_FIFOEN;
|
||||
u->CR2 = siop->config->cr2 & ~USART_CR2_CFG_FORBIDDEN;
|
||||
u->CR3 = siop->config->cr3 & ~USART_CR3_CFG_FORBIDDEN;
|
||||
|
||||
/* Starting operations.*/
|
||||
u->ICR = u->ISR;
|
||||
u->CR1 |= USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
|
@ -501,35 +505,6 @@ void sio_lld_stop(SIODriver *siop) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts a SIO operation.
|
||||
*
|
||||
* @param[in] siop pointer to an @p SIODriver structure
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void sio_lld_start_operation(SIODriver *siop) {
|
||||
|
||||
/* Setting up the operation.*/
|
||||
siop->usart->ICR = siop->usart->ISR;
|
||||
siop->usart->CR1 |= USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops an ongoing SIO operation, if any.
|
||||
*
|
||||
* @param[in] siop pointer to an @p SIODriver structure
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void sio_lld_stop_operation(SIODriver *siop) {
|
||||
|
||||
/* Stop operation.*/
|
||||
siop->usart->CR1 &= ~USART_CR1_CFG_FORBIDDEN;
|
||||
siop->usart->CR2 &= ~USART_CR2_CFG_FORBIDDEN;
|
||||
siop->usart->CR3 &= ~USART_CR3_CFG_FORBIDDEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable flags change notification.
|
||||
*
|
||||
|
@ -788,7 +763,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
|
|||
uint32_t isr, isrmask;
|
||||
uint32_t cr1, cr2, cr3;
|
||||
|
||||
osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state");
|
||||
osalDbgAssert(siop->state == SIO_READY, "invalid state");
|
||||
|
||||
/* Read on control registers.*/
|
||||
cr1 = u->CR1;
|
||||
|
@ -810,7 +785,8 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
|
|||
|
||||
/* Note, ISR flags are just read but not cleared, ISR sources are
|
||||
disabled instead.*/
|
||||
isr = u->ISR & isrmask;
|
||||
isr = u->ISR;
|
||||
isr = isr & isrmask;
|
||||
if (isr != 0U) {
|
||||
|
||||
/* Error events handled as a group, except ORE.*/
|
||||
|
@ -820,7 +796,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
|
|||
#if SIO_USE_SYNCHRONIZATION
|
||||
/* The idle flag is forcibly cleared when an RX error event is
|
||||
detected.*/
|
||||
u->ICR = USART_ISR_IDLE;
|
||||
u->ICR = USART_ICR_IDLECF;
|
||||
#endif
|
||||
|
||||
/* Interrupt sources disabled.*/
|
||||
|
@ -848,7 +824,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
|
|||
#if SIO_USE_SYNCHRONIZATION
|
||||
/* The idle flag is forcibly cleared when an RX data event is
|
||||
detected.*/
|
||||
u->ICR = USART_ISR_IDLE;
|
||||
u->ICR = USART_ICR_IDLECF;
|
||||
#endif
|
||||
|
||||
/* Interrupt source disabled.*/
|
||||
|
@ -887,7 +863,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
|
|||
__sio_callback(siop);
|
||||
}
|
||||
else {
|
||||
osalDbgAssert(false, "spurious interrupt");
|
||||
// osalDbgAssert(false, "spurious interrupt");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -451,8 +451,6 @@ extern "C" {
|
|||
void sio_lld_init(void);
|
||||
msg_t sio_lld_start(SIODriver *siop);
|
||||
void sio_lld_stop(SIODriver *siop);
|
||||
void sio_lld_start_operation(SIODriver *siop);
|
||||
void sio_lld_stop_operation(SIODriver *siop);
|
||||
void sio_lld_update_enable_flags(SIODriver *siop);
|
||||
sioevents_t sio_lld_get_and_clear_errors(SIODriver *siop);
|
||||
sioevents_t sio_lld_get_and_clear_events(SIODriver *siop);
|
||||
|
|
|
@ -38,10 +38,6 @@
|
|||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static const SIOOperation default_operation = {
|
||||
.cb = NULL
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
@ -59,6 +55,9 @@ static size_t sync_write(void *ip, const uint8_t *bp, size_t n,
|
|||
|
||||
msg = sioSynchronizeTX(siop, timeout);
|
||||
if (msg != MSG_OK) {
|
||||
if (msg != MSG_TIMEOUT) {
|
||||
i = 0U;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -81,6 +80,9 @@ static size_t sync_read(void *ip, uint8_t *bp, size_t n,
|
|||
|
||||
msg = sioSynchronizeRX(siop, timeout);
|
||||
if (msg != MSG_OK) {
|
||||
if (msg != MSG_TIMEOUT) {
|
||||
i = 0U;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -225,6 +227,7 @@ void sioObjectInit(SIODriver *siop) {
|
|||
siop->state = SIO_STOP;
|
||||
siop->config = NULL;
|
||||
siop->enabled = (sioflags_t)0;
|
||||
siop->cb = NULL;
|
||||
siop->arg = NULL;
|
||||
#if SIO_USE_SYNCHRONIZATION == TRUE
|
||||
siop->sync_rx = NULL;
|
||||
|
@ -268,6 +271,14 @@ msg_t sioStart(SIODriver *siop, const SIOConfig *config) {
|
|||
siop->state = SIO_STOP;
|
||||
}
|
||||
|
||||
#if SIO_USE_SYNCHRONIZATION == TRUE
|
||||
/* If synchronization is enabled then all events by default.*/
|
||||
sioWriteEnableFlagsI(siop, SIO_FL_ALL);
|
||||
#else
|
||||
/* If synchronization is disabled then no events by default.*/
|
||||
sioWriteEnableFlagsI(siop, SIO_FL_NONE);
|
||||
#endif
|
||||
|
||||
osalSysUnlock();
|
||||
|
||||
return msg;
|
||||
|
@ -290,119 +301,28 @@ void sioStop(SIODriver *siop) {
|
|||
"invalid state");
|
||||
|
||||
sio_lld_stop(siop);
|
||||
siop->config = NULL;
|
||||
siop->state = SIO_STOP;
|
||||
siop->config = NULL;
|
||||
siop->cb = NULL;
|
||||
siop->arg = NULL;
|
||||
|
||||
osalSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts a SIO operation.
|
||||
*
|
||||
* @param[in] siop pointer to an @p SIODriver structure
|
||||
* @param[in] operation pointer to an @p SIOOperation structure, can
|
||||
* be @p NULL if callbacks are not required
|
||||
* encoding the operation to be performed
|
||||
*
|
||||
* @iclass
|
||||
*/
|
||||
void sioStartOperationI(SIODriver *siop, const SIOOperation *operation) {
|
||||
|
||||
osalDbgCheck(siop != NULL);
|
||||
osalDbgCheckClassI();
|
||||
|
||||
osalDbgAssert((siop->state == SIO_READY) ||
|
||||
(siop->state == SIO_ACTIVE), "invalid state");
|
||||
|
||||
/* The application can pass NULL if it is not interested in callbacks,
|
||||
attaching a default operation structure.*/
|
||||
if (operation != NULL) {
|
||||
siop->operation = operation;
|
||||
}
|
||||
else {
|
||||
siop->operation = &default_operation;
|
||||
}
|
||||
|
||||
if (siop->state == SIO_READY) {
|
||||
sio_lld_start_operation(siop);
|
||||
siop->state = SIO_ACTIVE;
|
||||
|
||||
#if SIO_USE_SYNCHRONIZATION == TRUE
|
||||
/* If synchronization is enabled then all events.*/
|
||||
sioWriteEnableFlagsI(siop, SIO_FL_ALL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts a SIO operation.
|
||||
*
|
||||
* @param[in] siop pointer to an @p SIODriver structure
|
||||
* @param[in] operation pointer to an @p SIOOperation structure, can
|
||||
* be @p NULL if callbacks are not required
|
||||
* encoding the operation to be performed
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void sioStartOperation(SIODriver *siop, const SIOOperation *operation) {
|
||||
|
||||
osalSysLock();
|
||||
sioStartOperationI(siop, operation);
|
||||
osalSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops an ongoing SIO operation, if any.
|
||||
*
|
||||
* @param[in] siop pointer to an @p SIODriver structure
|
||||
*
|
||||
* @iclass
|
||||
*/
|
||||
void sioStopOperationI(SIODriver *siop) {
|
||||
|
||||
osalDbgCheck(siop != NULL);
|
||||
osalDbgCheckClassI();
|
||||
|
||||
osalDbgAssert((siop->state == SIO_READY) ||
|
||||
(siop->state == SIO_ACTIVE), "invalid state");
|
||||
|
||||
if (siop->state == SIO_ACTIVE) {
|
||||
#if SIO_USE_SYNCHRONIZATION == TRUE
|
||||
/* Informing waiting threads, if any.*/
|
||||
osalThreadResumeI(&siop->sync_rx, MSG_RESET);
|
||||
osalThreadResumeI(&siop->sync_rxidle, MSG_RESET);
|
||||
osalThreadResumeI(&siop->sync_tx, MSG_RESET);
|
||||
osalThreadResumeI(&siop->sync_txend, MSG_RESET);
|
||||
osalOsRescheduleS();
|
||||
#endif
|
||||
|
||||
sio_lld_stop_operation(siop);
|
||||
|
||||
siop->operation = NULL;
|
||||
siop->state = SIO_READY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops an ongoing SIO operation, if any.
|
||||
*
|
||||
* @param[in] siop pointer to an @p SIODriver structure
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void sioStopOperation(SIODriver *siop) {
|
||||
|
||||
osalDbgCheck(siop != NULL);
|
||||
|
||||
osalSysLock();
|
||||
sioStopOperationI(siop);
|
||||
osalSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes the condition flags mask.
|
||||
* @brief Writes the enabled events flags mask.
|
||||
*
|
||||
* @param[in] siop pointer to the @p SIODriver object
|
||||
* @param[in] flags flags mask to be written
|
||||
* @param[in] flags enabled events mask to be written
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
|
@ -412,7 +332,7 @@ void sioWriteEnableFlags(SIODriver *siop, sioflags_t flags) {
|
|||
|
||||
osalSysLock();
|
||||
|
||||
osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state");
|
||||
osalDbgAssert(siop->state == SIO_READY, "invalid state");
|
||||
|
||||
sioWriteEnableFlagsI(siop, flags);
|
||||
|
||||
|
@ -420,10 +340,10 @@ void sioWriteEnableFlags(SIODriver *siop, sioflags_t flags) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Enables flags to the condition flags mask.
|
||||
* @brief Sets flags into the enabled events flags mask.
|
||||
*
|
||||
* @param[in] siop pointer to the @p SIODriver object
|
||||
* @param[in] flags flags mask to be enabled
|
||||
* @param[in] flags enabled events mask to be set
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
|
@ -433,7 +353,7 @@ void sioSetEnableFlags(SIODriver *siop, sioflags_t flags) {
|
|||
|
||||
osalSysLock();
|
||||
|
||||
osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state");
|
||||
osalDbgAssert(siop->state == SIO_READY, "invalid state");
|
||||
|
||||
sioSetEnableFlagsI(siop, flags);
|
||||
|
||||
|
@ -441,10 +361,10 @@ void sioSetEnableFlags(SIODriver *siop, sioflags_t flags) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Disables flags from the condition flags mask.
|
||||
* @brief Clears flags from the enabled events flags mask.
|
||||
*
|
||||
* @param[in] siop pointer to the @p SIODriver object
|
||||
* @param[in] flags flags mask to be disabled
|
||||
* @param[in] flags enabled events mask to be cleared
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
|
@ -454,7 +374,7 @@ void sioClearEnableFlags(SIODriver *siop, sioflags_t flags) {
|
|||
|
||||
osalSysLock();
|
||||
|
||||
osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state");
|
||||
osalDbgAssert(siop->state == SIO_READY, "invalid state");
|
||||
|
||||
sioClearEnableFlagsI(siop, flags);
|
||||
|
||||
|
@ -476,7 +396,7 @@ sioevents_t sioGetAndClearErrors(SIODriver *siop) {
|
|||
|
||||
osalSysLock();
|
||||
|
||||
osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state");
|
||||
osalDbgAssert(siop->state == SIO_READY, "invalid state");
|
||||
|
||||
errors = sioGetAndClearErrorsI(siop);
|
||||
|
||||
|
@ -500,7 +420,7 @@ sioevents_t sioGetAndClearEvents(SIODriver *siop) {
|
|||
|
||||
osalSysLock();
|
||||
|
||||
osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state");
|
||||
osalDbgAssert(siop->state == SIO_READY, "invalid state");
|
||||
|
||||
events = sioGetAndClearEventsI(siop);
|
||||
|
||||
|
@ -529,7 +449,7 @@ size_t sioAsyncRead(SIODriver *siop, uint8_t *buffer, size_t n) {
|
|||
|
||||
osalSysLock();
|
||||
|
||||
osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state");
|
||||
osalDbgAssert(siop->state == SIO_READY, "invalid state");
|
||||
|
||||
n = sioAsyncReadI(siop, buffer, n);
|
||||
|
||||
|
@ -558,7 +478,7 @@ size_t sioAsyncWrite(SIODriver *siop, const uint8_t *buffer, size_t n) {
|
|||
|
||||
osalSysLock();
|
||||
|
||||
osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state");
|
||||
osalDbgAssert(siop->state == SIO_READY, "invalid state");
|
||||
|
||||
n = sioAsyncWriteI(siop, buffer, n);
|
||||
|
||||
|
@ -591,7 +511,7 @@ msg_t sioSynchronizeRX(SIODriver *siop, sysinterval_t timeout) {
|
|||
|
||||
osalSysLock();
|
||||
|
||||
osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state");
|
||||
osalDbgAssert(siop->state == SIO_READY, "invalid state");
|
||||
|
||||
/* Checking for errors before going to sleep.*/
|
||||
if (((siop->enabled & SIO_FL_ALL_ERRORS) != 0U) && sioHasRXErrorsX(siop)) {
|
||||
|
@ -636,7 +556,7 @@ msg_t sioSynchronizeRXIdle(SIODriver *siop, sysinterval_t timeout) {
|
|||
|
||||
osalSysLock();
|
||||
|
||||
osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state");
|
||||
osalDbgAssert(siop->state == SIO_READY, "invalid state");
|
||||
|
||||
/* Checking for errors before going to sleep.*/
|
||||
if (((siop->enabled & SIO_FL_ALL_ERRORS) != 0U) && sioHasRXErrorsX(siop)) {
|
||||
|
@ -683,7 +603,7 @@ msg_t sioSynchronizeTX(SIODriver *siop, sysinterval_t timeout) {
|
|||
|
||||
osalSysLock();
|
||||
|
||||
osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state");
|
||||
osalDbgAssert(siop->state == SIO_READY, "invalid state");
|
||||
|
||||
msg = MSG_OK;
|
||||
/*lint -save -e506 -e681 [2.1] Silencing this error because it is
|
||||
|
@ -721,7 +641,7 @@ msg_t sioSynchronizeTXEnd(SIODriver *siop, sysinterval_t timeout) {
|
|||
|
||||
osalSysLock();
|
||||
|
||||
osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state");
|
||||
osalDbgAssert(siop->state == SIO_READY, "invalid state");
|
||||
|
||||
/*lint -save -e506 -e774 [2.1, 14.3] Silencing this error because
|
||||
it is tested with a template implementation of sio_lld_is_tx_ongoing()
|
||||
|
|
|
@ -74,6 +74,9 @@
|
|||
*****************************************************************************
|
||||
|
||||
*** Next ***
|
||||
- NEW: Added a "BufferedSIODriver" class that implements the behavior of the
|
||||
legacy Serial driver on top of a SIO implementation (buffering, events
|
||||
and all).
|
||||
- NEW: Added __CH_OWNEROF() macro to RT.
|
||||
- NEW; Now hal.h includes cc_portab.h by default making it mandatory.
|
||||
- NEW: Moved HAL serial error flags into asynchronous channels interface
|
||||
|
|
|
@ -20,6 +20,73 @@
|
|||
|
||||
#include "portab.h"
|
||||
|
||||
#include "chprintf.h"
|
||||
#include "shell.h"
|
||||
|
||||
static BufferedSIODriver bsio1;
|
||||
static uint8_t rxbuf[32];
|
||||
static uint8_t txbuf[32];
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Command line related. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define SHELL_WA_SIZE THD_WORKING_AREA_SIZE(2048)
|
||||
|
||||
/* Can be measured using dd if=/dev/xxxx of=/dev/null bs=512 count=10000.*/
|
||||
static void cmd_write(BaseSequentialStream *chp, int argc, char *argv[]) {
|
||||
static uint8_t buf[] =
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
|
||||
|
||||
(void)argv;
|
||||
if (argc > 0) {
|
||||
chprintf(chp, "Usage: write\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
while (chnGetTimeout((BaseChannel *)chp, TIME_IMMEDIATE) == Q_TIMEOUT) {
|
||||
#if 1
|
||||
/* Writing in channel mode.*/
|
||||
chnWrite(&bsio1, buf, sizeof buf - 1);
|
||||
#else
|
||||
/* Writing in buffer mode.*/
|
||||
(void) obqGetEmptyBufferTimeout(&PORTAB_SDU1.obqueue, TIME_INFINITE);
|
||||
memcpy(PORTAB_SDU1.obqueue.ptr, buf, SERIAL_USB_BUFFERS_SIZE);
|
||||
obqPostFullBuffer(&PORTAB_SDU1.obqueue, SERIAL_USB_BUFFERS_SIZE);
|
||||
#endif
|
||||
}
|
||||
chprintf(chp, "\r\n\nstopped\r\n");
|
||||
}
|
||||
|
||||
static const ShellCommand commands[] = {
|
||||
{"write", cmd_write},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static const ShellConfig shell_cfg1 = {
|
||||
(BaseSequentialStream *)&bsio1,
|
||||
commands
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Generic code. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*
|
||||
* RX consumer thread, times are in milliseconds.
|
||||
*/
|
||||
|
@ -36,13 +103,19 @@ static THD_FUNCTION(Thread1, arg) {
|
|||
uint8_t buf[16];
|
||||
|
||||
n = chnRead(&PORTAB_SIO2, buf, 16);
|
||||
if (n > 0) {
|
||||
chnWrite(&PORTAB_SIO1, buf, n);
|
||||
if (n == 0U) {
|
||||
break;
|
||||
}
|
||||
n = chnWrite(&PORTAB_SIO1, buf, n);
|
||||
if (n == 0) {
|
||||
break;
|
||||
}
|
||||
errors = sioGetAndClearErrors(&PORTAB_SIO2);
|
||||
(void) errors;
|
||||
|
||||
sioSynchronizeRXIdle(&PORTAB_SIO2, TIME_INFINITE);
|
||||
if (sioSynchronizeRXIdle(&PORTAB_SIO2, TIME_INFINITE) < MSG_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,6 +123,7 @@ static THD_FUNCTION(Thread1, arg) {
|
|||
* Application entry point.
|
||||
*/
|
||||
int main(void) {
|
||||
thread_t *tp;
|
||||
|
||||
/*
|
||||
* System initializations.
|
||||
|
@ -70,14 +144,13 @@ int main(void) {
|
|||
* Activates the SIO drivers using the default configuration.
|
||||
*/
|
||||
sioStart(&PORTAB_SIO1, NULL);
|
||||
sioStartOperation(&PORTAB_SIO1, NULL);
|
||||
sioStart(&PORTAB_SIO2, NULL);
|
||||
sioStartOperation(&PORTAB_SIO2, NULL);
|
||||
|
||||
/*
|
||||
* Creates the RX consumer thread.
|
||||
*/
|
||||
chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
|
||||
tp = chThdCreateStatic(waThread1, sizeof(waThread1),
|
||||
NORMALPRIO + 1, Thread1, NULL);
|
||||
|
||||
/*
|
||||
* Short TX writes.
|
||||
|
@ -88,7 +161,7 @@ int main(void) {
|
|||
for (c = 'A'; c <= 'Z'; c++) {
|
||||
chnWrite(&PORTAB_SIO2, (const uint8_t *)&c, 1);
|
||||
sioSynchronizeTXEnd(&PORTAB_SIO2, TIME_INFINITE);
|
||||
chThdSleepMilliseconds(100);
|
||||
chThdSleepMilliseconds(10);
|
||||
}
|
||||
} while (palReadLine(PORTAB_LINE_BUTTON) != PORTAB_BUTTON_PRESSED);
|
||||
|
||||
|
@ -112,10 +185,29 @@ int main(void) {
|
|||
}
|
||||
|
||||
/*
|
||||
* Normal main() thread activity, in this demo it does nothing.
|
||||
* Stopping SIOs.
|
||||
*/
|
||||
sioStop(&PORTAB_SIO1);
|
||||
sioStop(&PORTAB_SIO2);
|
||||
chThdWait(tp);
|
||||
|
||||
/*
|
||||
* Starting a buffered SIO, it must behave exactly as a serial driver.
|
||||
*/
|
||||
bsioObjectInit(&bsio1, &PORTAB_SIO1,
|
||||
rxbuf, sizeof rxbuf,
|
||||
txbuf, sizeof txbuf);
|
||||
bsioStart(&bsio1, NULL);
|
||||
|
||||
/*
|
||||
* Normal main() thread activity, spawning shells.
|
||||
*/
|
||||
while (true) {
|
||||
chThdSleepMilliseconds(500);
|
||||
tp = chThdCreateFromHeap(NULL, SHELL_WA_SIZE,
|
||||
"shell", NORMALPRIO + 1,
|
||||
shellThread, (void *)&shell_cfg1);
|
||||
chThdWait(tp); /* Waiting termination. */
|
||||
chThdSleepMilliseconds(1000);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -110,9 +110,11 @@ include $(CHIBIOS)/os/common/ports/ARMv7-M/compilers/GCC/mk/port.mk
|
|||
# Auto-build files in ./source recursively.
|
||||
include $(CHIBIOS)/tools/mk/autobuild.mk
|
||||
# Other files (optional).
|
||||
#include $(CHIBIOS)/os/test/test.mk
|
||||
#include $(CHIBIOS)/test/rt/rt_test.mk
|
||||
#include $(CHIBIOS)/test/oslib/oslib_test.mk
|
||||
include $(CHIBIOS)/os/test/test.mk
|
||||
include $(CHIBIOS)/test/rt/rt_test.mk
|
||||
include $(CHIBIOS)/test/oslib/oslib_test.mk
|
||||
include $(CHIBIOS)/os/hal/lib/streams/streams.mk
|
||||
include $(CHIBIOS)/os/various/shell/shell.mk
|
||||
|
||||
# Define linker script file here.
|
||||
LDSCRIPT= $(STARTUPLD)/STM32G474xE.ld
|
||||
|
|
|
@ -110,9 +110,11 @@ include $(CHIBIOS)/os/common/ports/ARMv7-M/compilers/GCC/mk/port.mk
|
|||
# Auto-build files in ./source recursively.
|
||||
include $(CHIBIOS)/tools/mk/autobuild.mk
|
||||
# Other files (optional).
|
||||
#include $(CHIBIOS)/os/test/test.mk
|
||||
#include $(CHIBIOS)/test/rt/rt_test.mk
|
||||
#include $(CHIBIOS)/test/oslib/oslib_test.mk
|
||||
include $(CHIBIOS)/os/test/test.mk
|
||||
include $(CHIBIOS)/test/rt/rt_test.mk
|
||||
include $(CHIBIOS)/test/oslib/oslib_test.mk
|
||||
include $(CHIBIOS)/os/hal/lib/streams/streams.mk
|
||||
include $(CHIBIOS)/os/various/shell/shell.mk
|
||||
|
||||
# Define linker script file here.
|
||||
LDSCRIPT= $(STARTUPLD)/STM32L476xG.ld
|
||||
|
|
Loading…
Reference in New Issue