diff --git a/os/hal/include/hal_qspi.h b/os/hal/include/hal_qspi.h index 67fc7ad10..0b67923b3 100644 --- a/os/hal/include/hal_qspi.h +++ b/os/hal/include/hal_qspi.h @@ -114,7 +114,8 @@ typedef enum { QSPI_STOP = 1, /**< Stopped. */ QSPI_READY = 2, /**< Ready. */ QSPI_ACTIVE = 3, /**< Exchanging data. */ - QSPI_COMPLETE = 4 /**< Asynchronous operation complete. */ + QSPI_COMPLETE = 4, /**< Asynchronous operation complete. */ + QSPI_MEMMAP = 5 /**< In memory mapped mode. */ } qspistate_t; /** @@ -128,6 +129,10 @@ typedef struct { #include "hal_qspi_lld.h" +#if !defined(QSPI_SUPPORTS_MEMMAP) +#error "low level does not define QSPI_SUPPORTS_MEMMAP" +#endif + /*===========================================================================*/ /* Driver macros. */ /*===========================================================================*/ @@ -192,6 +197,35 @@ typedef struct { (qspip)->state = QSPI_ACTIVE; \ qspi_lld_receive(qspip, cmdp, n, rxbuf); \ } + +#if (QSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__) +/** + * @brief Maps in memory space a QSPI flash device. + * @pre The memory flash device must be initialized appropriately + * before mapping it in memory space. + * + * @param[in] qspip pointer to the @p QSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * @param[out] addrp pointer to the memory start address of the mapped + * flash or @p NULL + * + * @iclass + */ +#define qspiMapFlashI(qspip, cmdp, addrp) \ + qspi_lld_map_flash(qspip, cmdp, addrp) + +/** + * @brief Maps in memory space a QSPI flash device. + * @post The memory flash device must be re-initialized for normal + * commands exchange. + * + * @param[in] qspip pointer to the @p QSPIDriver object + * + * @iclass + */ +#define qspiUnmapFlashI(qspip) \ + qspi_lld_unmap_flash(qspip) +#endif /* QSPI_SUPPORTS_MEMMAP == TRUE */ /** @} */ /** @@ -265,6 +299,12 @@ extern "C" { void qspiReceive(QSPIDriver *qspip, const qspi_command_t *cmdp, size_t n, uint8_t *rxbuf); #endif +#if QSPI_SUPPORTS_MEMMAP == TRUE +void qspiMapFlash(QSPIDriver *qspip, + const qspi_command_t *cmdp, + uint8_t **addrp); +void qspiUnmapFlash(QSPIDriver *qspip); +#endif #if QSPI_USE_MUTUAL_EXCLUSION == TRUE void qspiAcquireBus(QSPIDriver *qspip); void qspiReleaseBus(QSPIDriver *qspip); diff --git a/os/hal/ports/STM32/LLD/QUADSPIv1/hal_qspi_lld.c b/os/hal/ports/STM32/LLD/QUADSPIv1/hal_qspi_lld.c index f914b6163..4c8ee0f2d 100644 --- a/os/hal/ports/STM32/LLD/QUADSPIv1/hal_qspi_lld.c +++ b/os/hal/ports/STM32/LLD/QUADSPIv1/hal_qspi_lld.c @@ -291,6 +291,40 @@ void qspi_lld_receive(QSPIDriver *qspip, const qspi_command_t *cmdp, dmaStreamEnable(qspip->dma); } + +#if (QSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__) +/** + * @brief Maps in memory space a QSPI flash device. + * @pre The memory flash device must be initialized appropriately + * before mapping it in memory space. + * + * @param[in] qspip pointer to the @p QSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * @param[out] addrp pointer to the memory start address of the mapped + * flash or @p NULL + * + * @notapi + */ +void qspi_lld_map_flash(QSPIDriver *qspip, + const qspi_command_t *cmdp, + uint8_t **addrp) { + +} + +/** + * @brief Maps in memory space a QSPI flash device. + * @post The memory flash device must be re-initialized for normal + * commands exchange. + * + * @param[in] qspip pointer to the @p QSPIDriver object + * + * @notapi + */ +void qspi_lld_unmap_flash(QSPIDriver *qspip) { + +} +#endif /* QSPI_SUPPORTS_MEMMAP == TRUE */ + #endif /* HAL_USE_QSPI */ /** @} */ diff --git a/os/hal/ports/STM32/LLD/QUADSPIv1/hal_qspi_lld.h b/os/hal/ports/STM32/LLD/QUADSPIv1/hal_qspi_lld.h index 4465755bf..5f8cd86af 100644 --- a/os/hal/ports/STM32/LLD/QUADSPIv1/hal_qspi_lld.h +++ b/os/hal/ports/STM32/LLD/QUADSPIv1/hal_qspi_lld.h @@ -31,6 +31,13 @@ /* Driver constants. */ /*===========================================================================*/ +/** + * @name QSPI capabilities + * @{ + */ +#define QSPI_SUPPORTS_MEMMAP FALSE +/** @} */ + /** * @name DCR register options * @{ @@ -257,6 +264,12 @@ extern "C" { size_t n, const uint8_t *txbuf); void qspi_lld_receive(QSPIDriver *qspip, const qspi_command_t *cmdp, size_t n, uint8_t *rxbuf); +#if QSPI_SUPPORTS_MEMMAP == TRUE + void qspi_lld_map_flash(QSPIDriver *qspip, + const qspi_command_t *cmdp, + uint8_t **addrp); + void qspi_lld_unmap_flash(QSPIDriver *qspip); +#endif #ifdef __cplusplus } #endif diff --git a/os/hal/src/hal_qspi.c b/os/hal/src/hal_qspi.c index d3cf0cf32..dd091498b 100644 --- a/os/hal/src/hal_qspi.c +++ b/os/hal/src/hal_qspi.c @@ -92,12 +92,16 @@ void qspiStart(QSPIDriver *qspip, const QSPIConfig *config) { osalDbgCheck((qspip != NULL) && (config != NULL)); + osalSysLock(); + osalDbgAssert((qspip->state == QSPI_STOP) || (qspip->state == QSPI_READY), "invalid state"); + qspip->config = config; qspi_lld_start(qspip); qspip->state = QSPI_READY; + osalSysUnlock(); } @@ -115,10 +119,13 @@ void qspiStop(QSPIDriver *qspip) { osalDbgCheck(qspip != NULL); osalSysLock(); + osalDbgAssert((qspip->state == QSPI_STOP) || (qspip->state == QSPI_READY), "invalid state"); + qspi_lld_stop(qspip); qspip->state = QSPI_STOP; + osalSysUnlock(); } @@ -136,8 +143,11 @@ void qspiStartCommand(QSPIDriver *qspip, const qspi_command_t *cmdp) { osalDbgCheck((qspip != NULL) && (cmdp != NULL)); osalSysLock(); + osalDbgAssert(qspip->state == QSPI_READY, "not ready"); + qspiStartCommandI(qspip, cmdp); + osalSysUnlock(); } @@ -159,8 +169,11 @@ void qspiStartSend(QSPIDriver *qspip, const qspi_command_t *cmdp, osalDbgCheck((n > 0U) && (txbuf != NULL)); osalSysLock(); + osalDbgAssert(qspip->state == QSPI_READY, "not ready"); + qspiStartSendI(qspip, cmdp, n, txbuf); + osalSysUnlock(); } @@ -182,8 +195,11 @@ void qspiStartReceive(QSPIDriver *qspip, const qspi_command_t *cmdp, osalDbgCheck((n > 0U) && (rxbuf != NULL)); osalSysLock(); + osalDbgAssert(qspip->state == QSPI_READY, "not ready"); + qspiStartReceiveI(qspip, cmdp, n, rxbuf); + osalSysUnlock(); } @@ -206,10 +222,13 @@ void qspiCommand(QSPIDriver *qspip, const qspi_command_t *cmdp) { osalDbgCheck((cmdp->cfg & QSPI_CFG_DATA_MODE_MASK) == QSPI_CFG_DATA_MODE_NONE); osalSysLock(); + osalDbgAssert(qspip->state == QSPI_READY, "not ready"); osalDbgAssert(qspip->config->end_cb == NULL, "has callback"); + qspiStartCommandI(qspip, cmdp); (void) osalThreadSuspendS(&qspip->thread); + osalSysUnlock(); } @@ -235,10 +254,13 @@ void qspiSend(QSPIDriver *qspip, const qspi_command_t *cmdp, osalDbgCheck((cmdp->cfg & QSPI_CFG_DATA_MODE_MASK) != QSPI_CFG_DATA_MODE_NONE); osalSysLock(); + osalDbgAssert(qspip->state == QSPI_READY, "not ready"); osalDbgAssert(qspip->config->end_cb == NULL, "has callback"); + qspiStartSendI(qspip, cmdp, n, txbuf); (void) osalThreadSuspendS(&qspip->thread); + osalSysUnlock(); } @@ -264,14 +286,71 @@ void qspiReceive(QSPIDriver *qspip, const qspi_command_t *cmdp, osalDbgCheck((cmdp->cfg & QSPI_CFG_DATA_MODE_MASK) != QSPI_CFG_DATA_MODE_NONE); osalSysLock(); + osalDbgAssert(qspip->state == QSPI_READY, "not ready"); osalDbgAssert(qspip->config->end_cb == NULL, "has callback"); + qspiStartReceiveI(qspip, cmdp, n, rxbuf); (void) osalThreadSuspendS(&qspip->thread); + osalSysUnlock(); } #endif /* QSPI_USE_WAIT == TRUE */ +#if (QSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__) +/** + * @brief Maps in memory space a QSPI flash device. + * @pre The memory flash device must be initialized appropriately + * before mapping it in memory space. + * + * @param[in] qspip pointer to the @p QSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * @param[out] addrp pointer to the memory start address of the mapped + * flash or @p NULL + * + * @api + */ +void qspiMapFlash(QSPIDriver *qspip, + const qspi_command_t *cmdp, + uint8_t **addrp) { + + osalDbgCheck((qspip != NULL) && (cmdp != NULL)); + osalDbgCheck((cmdp->cfg & QSPI_CFG_DATA_MODE_MASK) != QSPI_CFG_DATA_MODE_NONE); + + osalSysLock(); + + osalDbgAssert(qspip->state == QSPI_READY, "not ready"); + + qspiMapFlashI(qspip, cmdp, addrp); + qspip->state = QSPI_MEMMAP; + + osalSysUnlock(); +} + +/** + * @brief Maps in memory space a QSPI flash device. + * @post The memory flash device must be re-initialized for normal + * commands exchange. + * + * @param[in] qspip pointer to the @p QSPIDriver object + * + * @api + */ +void qspiUnmapFlash(QSPIDriver *qspip) { + + osalDbgCheck(qspip != NULL); + + osalSysLock(); + + osalDbgAssert(qspip->state == QSPI_MEMMAP, "not ready"); + + qspiUnmapFlashI(qspip); + qspip->state = QSPI_READY; + + osalSysUnlock(); +} +#endif /* QSPI_SUPPORTS_MEMMAP == TRUE */ + #if (QSPI_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__) /** * @brief Gains exclusive access to the QSPI bus. diff --git a/testhal/STM32/STM32L4xx/QSPI-N25Q128/debug/QSPI-N25Q128 (OpenOCD, Flash and Run).launch b/testhal/STM32/STM32L4xx/QSPI-N25Q128/debug/QSPI-N25Q128 (OpenOCD, Flash and Run).launch index 573a54f12..9187ae1d8 100644 --- a/testhal/STM32/STM32L4xx/QSPI-N25Q128/debug/QSPI-N25Q128 (OpenOCD, Flash and Run).launch +++ b/testhal/STM32/STM32L4xx/QSPI-N25Q128/debug/QSPI-N25Q128 (OpenOCD, Flash and Run).launch @@ -33,7 +33,7 @@ - +