Added error handling to WSPI driver, now LLDs can report error conditions to upper layers.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@13061 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2019-10-05 07:04:14 +00:00
parent 3ea7ec6586
commit 375722180b
5 changed files with 62 additions and 13 deletions

View File

@ -140,6 +140,10 @@ struct hal_wspi_config {
* @brief Operation complete callback or @p NULL. * @brief Operation complete callback or @p NULL.
*/ */
wspicallback_t end_cb; wspicallback_t end_cb;
/**
* @brief Operation error callback or @p NULL.
*/
wspicallback_t error_cb;
/* End of the mandatory fields.*/ /* End of the mandatory fields.*/
wspi_lld_config_fields; wspi_lld_config_fields;
}; };
@ -356,13 +360,13 @@ struct hal_wspi_driver {
* *
* @notapi * @notapi
*/ */
#define _wspi_wakeup_isr(wspip) { \ #define _wspi_wakeup_isr(wspip, msg) { \
osalSysLockFromISR(); \ osalSysLockFromISR(); \
osalThreadResumeI(&(wspip)->thread, MSG_OK); \ osalThreadResumeI(&(wspip)->thread, msg); \
osalSysUnlockFromISR(); \ osalSysUnlockFromISR(); \
} }
#else /* !WSPI_USE_WAIT */ #else /* !WSPI_USE_WAIT */
#define _wspi_wakeup_isr(wspip) #define _wspi_wakeup_isr(wspip, msg)
#endif /* !WSPI_USE_WAIT */ #endif /* !WSPI_USE_WAIT */
/** /**
@ -388,7 +392,33 @@ struct hal_wspi_driver {
} \ } \
else \ else \
(wspip)->state = WSPI_READY; \ (wspip)->state = WSPI_READY; \
_wspi_wakeup_isr(wspip); \ _wspi_wakeup_isr(wspip, MSG_OK); \
}
/**
* @brief Common error ISR code.
* @details This code handles the portable part of the ISR code:
* - Callback invocation.
* - Waiting thread wakeup, if any.
* - Driver state transitions.
* .
* @note This macro is meant to be used in the low level drivers
* implementation only.
*
* @param[in] wspip pointer to the @p WSPIDriver object
*
* @notapi
*/
#define _wspi_error_code(wspip) { \
if ((wspip)->config->error_cb) { \
(wspip)->state = WSPI_COMPLETE; \
(wspip)->config->error_cb(wspip); \
if ((wspip)->state == WSPI_COMPLETE) \
(wspip)->state = WSPI_READY; \
} \
else \
(wspip)->state = WSPI_READY; \
_wspi_wakeup_isr(wspip, MSG_RESET); \
} }
/** @} */ /** @} */
@ -409,10 +439,10 @@ extern "C" {
void wspiStartReceive(WSPIDriver *wspip, const wspi_command_t *cmdp, void wspiStartReceive(WSPIDriver *wspip, const wspi_command_t *cmdp,
size_t n, uint8_t *rxbuf); size_t n, uint8_t *rxbuf);
#if WSPI_USE_WAIT == TRUE #if WSPI_USE_WAIT == TRUE
void wspiCommand(WSPIDriver *wspip, const wspi_command_t *cmdp); bool wspiCommand(WSPIDriver *wspip, const wspi_command_t *cmdp);
void wspiSend(WSPIDriver *wspip, const wspi_command_t *cmdp, bool wspiSend(WSPIDriver *wspip, const wspi_command_t *cmdp,
size_t n, const uint8_t *txbuf); size_t n, const uint8_t *txbuf);
void wspiReceive(WSPIDriver *wspip, const wspi_command_t *cmdp, bool wspiReceive(WSPIDriver *wspip, const wspi_command_t *cmdp,
size_t n, uint8_t *rxbuf); size_t n, uint8_t *rxbuf);
#endif #endif
#if WSPI_SUPPORTS_MEMMAP == TRUE #if WSPI_SUPPORTS_MEMMAP == TRUE

View File

@ -216,7 +216,8 @@ void wspiStartReceive(WSPIDriver *wspip, const wspi_command_t *cmdp,
* *
* @api * @api
*/ */
void wspiCommand(WSPIDriver *wspip, const wspi_command_t *cmdp) { bool wspiCommand(WSPIDriver *wspip, const wspi_command_t *cmdp) {
msg_t msg;
osalDbgCheck((wspip != NULL) && (cmdp != NULL)); osalDbgCheck((wspip != NULL) && (cmdp != NULL));
osalDbgCheck((cmdp->cfg & WSPI_CFG_DATA_MODE_MASK) == WSPI_CFG_DATA_MODE_NONE); osalDbgCheck((cmdp->cfg & WSPI_CFG_DATA_MODE_MASK) == WSPI_CFG_DATA_MODE_NONE);
@ -227,9 +228,11 @@ void wspiCommand(WSPIDriver *wspip, const wspi_command_t *cmdp) {
osalDbgAssert(wspip->config->end_cb == NULL, "has callback"); osalDbgAssert(wspip->config->end_cb == NULL, "has callback");
wspiStartCommandI(wspip, cmdp); wspiStartCommandI(wspip, cmdp);
(void) osalThreadSuspendS(&wspip->thread); msg = osalThreadSuspendS(&wspip->thread);
osalSysUnlock(); osalSysUnlock();
return (bool)(msg != MSG_OK);
} }
/** /**
@ -243,11 +246,15 @@ void wspiCommand(WSPIDriver *wspip, const wspi_command_t *cmdp) {
* @param[in] cmdp pointer to the command descriptor * @param[in] cmdp pointer to the command descriptor
* @param[in] n number of bytes to send * @param[in] n number of bytes to send
* @param[in] txbuf the pointer to the transmit buffer * @param[in] txbuf the pointer to the transmit buffer
* @return The operation status.
* @retval false if the operation succeeded.
* @retval true if the operation failed because HW issues.
* *
* @api * @api
*/ */
void wspiSend(WSPIDriver *wspip, const wspi_command_t *cmdp, bool wspiSend(WSPIDriver *wspip, const wspi_command_t *cmdp,
size_t n, const uint8_t *txbuf) { size_t n, const uint8_t *txbuf) {
msg_t msg;
osalDbgCheck((wspip != NULL) && (cmdp != NULL)); osalDbgCheck((wspip != NULL) && (cmdp != NULL));
osalDbgCheck((n > 0U) && (txbuf != NULL)); osalDbgCheck((n > 0U) && (txbuf != NULL));
@ -259,9 +266,11 @@ void wspiSend(WSPIDriver *wspip, const wspi_command_t *cmdp,
osalDbgAssert(wspip->config->end_cb == NULL, "has callback"); osalDbgAssert(wspip->config->end_cb == NULL, "has callback");
wspiStartSendI(wspip, cmdp, n, txbuf); wspiStartSendI(wspip, cmdp, n, txbuf);
(void) osalThreadSuspendS(&wspip->thread); msg = osalThreadSuspendS(&wspip->thread);
osalSysUnlock(); osalSysUnlock();
return (bool)(msg != MSG_OK);
} }
/** /**
@ -275,11 +284,15 @@ void wspiSend(WSPIDriver *wspip, const wspi_command_t *cmdp,
* @param[in] cmdp pointer to the command descriptor * @param[in] cmdp pointer to the command descriptor
* @param[in] n number of bytes to send * @param[in] n number of bytes to send
* @param[out] rxbuf the pointer to the receive buffer * @param[out] rxbuf the pointer to the receive buffer
* @return The operation status.
* @retval false if the operation succeeded.
* @retval true if the operation failed because HW issues.
* *
* @api * @api
*/ */
void wspiReceive(WSPIDriver *wspip, const wspi_command_t *cmdp, bool wspiReceive(WSPIDriver *wspip, const wspi_command_t *cmdp,
size_t n, uint8_t *rxbuf) { size_t n, uint8_t *rxbuf) {
msg_t msg;
osalDbgCheck((wspip != NULL) && (cmdp != NULL)); osalDbgCheck((wspip != NULL) && (cmdp != NULL));
osalDbgCheck((n > 0U) && (rxbuf != NULL)); osalDbgCheck((n > 0U) && (rxbuf != NULL));
@ -291,9 +304,11 @@ void wspiReceive(WSPIDriver *wspip, const wspi_command_t *cmdp,
osalDbgAssert(wspip->config->end_cb == NULL, "has callback"); osalDbgAssert(wspip->config->end_cb == NULL, "has callback");
wspiStartReceiveI(wspip, cmdp, n, rxbuf); wspiStartReceiveI(wspip, cmdp, n, rxbuf);
(void) osalThreadSuspendS(&wspip->thread); msg = osalThreadSuspendS(&wspip->thread);
osalSysUnlock(); osalSysUnlock();
return (bool)(msg != MSG_OK);
} }
#endif /* WSPI_USE_WAIT == TRUE */ #endif /* WSPI_USE_WAIT == TRUE */

View File

@ -74,6 +74,8 @@
***************************************************************************** *****************************************************************************
*** Next *** *** Next ***
- NEW: Added error handling to WSPI driver, now LLDs can report error
conditions to upper layers.
- NEW: Added mcuconf.h generator for STM32G4x4. - NEW: Added mcuconf.h generator for STM32G4x4.
- HAL: STM32 DMAv1 driver improvements and generalization, added support - HAL: STM32 DMAv1 driver improvements and generalization, added support
for 8 channels. for 8 channels.

View File

@ -36,6 +36,7 @@
const WSPIConfig WSPIcfg1 = { const WSPIConfig WSPIcfg1 = {
.end_cb = NULL, .end_cb = NULL,
.error_cb = NULL,
.dcr = STM32_DCR_FSIZE(24U) | /* 16MB device. */ .dcr = STM32_DCR_FSIZE(24U) | /* 16MB device. */
STM32_DCR_CSHT(1U) /* NCS 2 cycles delay. */ STM32_DCR_CSHT(1U) /* NCS 2 cycles delay. */
}; };

View File

@ -36,6 +36,7 @@
const WSPIConfig WSPIcfg1 = { const WSPIConfig WSPIcfg1 = {
.end_cb = NULL, .end_cb = NULL,
.error_cb = NULL,
.dcr1 = STM32_DCR1_MTYP(1U) | /* Macronix mode. */ .dcr1 = STM32_DCR1_MTYP(1U) | /* Macronix mode. */
STM32_DCR1_DEVSIZE(26U) | /* 64MB device. */ STM32_DCR1_DEVSIZE(26U) | /* 64MB device. */
STM32_DCR1_CSHT(1U), /* NCS 2 cycles delay. */ STM32_DCR1_CSHT(1U), /* NCS 2 cycles delay. */