aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--os/hal/include/hal_qspi.h42
-rw-r--r--os/hal/ports/STM32/LLD/QUADSPIv1/hal_qspi_lld.c34
-rw-r--r--os/hal/ports/STM32/LLD/QUADSPIv1/hal_qspi_lld.h13
-rw-r--r--os/hal/src/hal_qspi.c79
-rw-r--r--testhal/STM32/STM32L4xx/QSPI-N25Q128/debug/QSPI-N25Q128 (OpenOCD, Flash and Run).launch2
5 files changed, 168 insertions, 2 deletions
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
@@ -32,6 +32,13 @@
/*===========================================================================*/
/**
+ * @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 @@
<intAttribute key="org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR" value="2"/>
<stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/>
<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_REGISTER_GROUPS" value=""/>
-<stringAttribute key="org.eclipse.cdt.launch.FORMAT" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&lt;contentList&gt;&lt;content id=&quot;CCR-qspi-qspip-qspi_lld_receive-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;cfg-cmdp-qspi_lld_receive-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;id[2]-id-m25qStart-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;id[1]-id-m25qStart-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;id[0]-id-m25qStart-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;AFRL-gpiop-initgpio-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;AFRH-gpiop-initgpio-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;ODR-gpiop-initgpio-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;IDR-gpiop-initgpio-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;PUPDR-gpiop-initgpio-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;OSPEEDR-gpiop-initgpio-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;MODER-gpiop-initgpio-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;afrh-config-initgpio-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;moder-config-initgpio-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;config-initgpio-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;r2-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;cfg-cmdp-qspiReceive-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;CCR-qspi-qspip-qspi_lld_send-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;CR-qspi-qspip-qspi_lld_send-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;cfg-cmdp-qspiSend-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;CR2-adc-adcp-adc_lld_start_conversion-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;CR2-adc-null-port_wait_for_interrupt-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;cr2-adc_lld_start_conversion-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;cmd-flash_cmd_receive-(format)&quot; val=&quot;4&quot;/&gt;&lt;/contentList&gt;"/>
+<stringAttribute key="org.eclipse.cdt.launch.FORMAT" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&lt;contentList&gt;&lt;content id=&quot;cmd-flash_cmd_receive-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;cr2-adc_lld_start_conversion-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;CR2-adc-null-port_wait_for_interrupt-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;CR2-adc-adcp-adc_lld_start_conversion-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;cfg-cmdp-qspiSend-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;CR-qspi-qspip-qspi_lld_send-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;CCR-qspi-qspip-qspi_lld_send-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;cfg-cmdp-qspiReceive-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;r2-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;config-initgpio-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;moder-config-initgpio-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;afrh-config-initgpio-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;MODER-gpiop-initgpio-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;OSPEEDR-gpiop-initgpio-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;PUPDR-gpiop-initgpio-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;IDR-gpiop-initgpio-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;ODR-gpiop-initgpio-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;AFRH-gpiop-initgpio-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;AFRL-gpiop-initgpio-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;id[0]-id-m25qStart-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;id[1]-id-m25qStart-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;id[2]-id-m25qStart-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;cfg-cmdp-qspi_lld_receive-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;CCR-qspi-qspip-qspi_lld_receive-(format)&quot; val=&quot;4&quot;/&gt;&lt;/contentList&gt;"/>
<stringAttribute key="org.eclipse.cdt.launch.GLOBAL_VARIABLES" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;globalVariableList/&gt;&#13;&#10;"/>
<stringAttribute key="org.eclipse.cdt.launch.MEMORY_BLOCKS" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;memoryBlockExpressionList/&gt;&#13;&#10;"/>
<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="./build/ch.elf"/>