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:
Giovanni Di Sirio 2022-08-21 06:10:28 +00:00
parent 7134a34b9b
commit 8c025f78c0
15 changed files with 202 additions and 291 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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");
}
}

View File

@ -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);

View File

@ -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.
*
@ -559,7 +534,7 @@ sioevents_t sio_lld_get_and_clear_events(SIODriver *siop) {
USART_ISR_RXNE |
USART_ISR_IDLE |
USART_ISR_TXE |
USART_ISR_TC);
USART_ISR_TC);
/* Clearing captured events.*/
siop->usart->ICR = isr;
@ -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");
}
}

View File

@ -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);

View File

@ -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.
*
@ -608,10 +583,10 @@ sioevents_t sio_lld_get_and_clear_events(SIODriver *siop) {
some scientist decided to use different positions for some
of them.*/
isr = siop->usart->ISR & (SIO_LLD_ISR_RX_ERRORS |
USART_ISR_RXNE_RXFNE |
USART_ISR_RXNE_RXFNE |
USART_ISR_IDLE |
USART_ISR_TXE_TXFNF |
USART_ISR_TC);
USART_ISR_TC);
/* Clearing captured events.*/
siop->usart->ICR = isr;
@ -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");
}
}

View File

@ -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);

View File

@ -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()

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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