diff options
author | Giovanni Di Sirio <gdisirio@gmail.com> | 2016-05-14 09:42:48 +0000 |
---|---|---|
committer | Giovanni Di Sirio <gdisirio@gmail.com> | 2016-05-14 09:42:48 +0000 |
commit | 6483a05d1408d56b0d8a4c173c3d9967cfc03e74 (patch) | |
tree | 9b78f55d4ac4d72d1b251ddb36ea949b74c1b60f /os | |
parent | ea922dd95f88d6795f0bb5bda6af3d4d10ace726 (diff) | |
download | ChibiOS-6483a05d1408d56b0d8a4c173c3d9967cfc03e74.tar.gz ChibiOS-6483a05d1408d56b0d8a4c173c3d9967cfc03e74.tar.bz2 ChibiOS-6483a05d1408d56b0d8a4c173c3d9967cfc03e74.zip |
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9480 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os')
-rw-r--r-- | os/hal/include/hal_qspi.h | 30 | ||||
-rw-r--r-- | os/hal/ports/STM32/LLD/QUADSPIv1/hal_qspi_lld.c | 68 | ||||
-rw-r--r-- | os/hal/ports/STM32/LLD/QUADSPIv1/hal_qspi_lld.h | 11 | ||||
-rw-r--r-- | os/hal/ports/STM32/STM32L4xx/stm32_registry.h | 3 | ||||
-rw-r--r-- | os/hal/src/hal_qspi.c | 71 |
5 files changed, 146 insertions, 37 deletions
diff --git a/os/hal/include/hal_qspi.h b/os/hal/include/hal_qspi.h index 498fedec7..0fe1e79fb 100644 --- a/os/hal/include/hal_qspi.h +++ b/os/hal/include/hal_qspi.h @@ -69,11 +69,6 @@ #define QSPI_CFG_DATA_MODE_ONE_LINE (1U << 24U)
#define QSPI_CFG_DATA_MODE_TWO_LINES (2U << 24U)
#define QSPI_CFG_DATA_MODE_FOUR_LINES (3U << 24U)
-#define QSPI_CFG_F_MODE_MASK (3U << 26U)
-#define QSPI_CFG_F_MODE_INDIRECT_WRITE (0U << 26U)
-#define QSPI_CFG_F_MODE_INDIRECT_READ (1U << 26U)
-#define QSPI_CFG_F_MODE_MEMORY_MAPPED (2U << 26U)
-#define QSPI_CFG_F_MODE_FOUR_LINES (3U << 26U)
#define QSPI_CFG_SIOO (1U << 28U)
#define QSPI_CFG_DDRM (1U << 31U)
/** @} */
@@ -142,6 +137,23 @@ typedef struct { * @{
*/
/**
+ * @brief Sends a command without data phase.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] qspip pointer to the @p QSPIDriver object
+ * @param[in] cmd pointer to the command descriptor
+ *
+ * @iclass
+ */
+#define qspiCommandI(qspip, cmd) { \
+ osalDbgAssert(((cmd)->cfg & QSPI_CFG_DATA_MODE_MASK) == \
+ QSPI_CFG_DATA_MODE_NONE, \
+ "data mode specified"); \
+ (qspip)->state = QSPI_ACTIVE; \
+ qspi_lld_command(qspip, cmd, n, txbuf); \
+}
+
+/**
* @brief Sends data over the QSPI bus.
* @details This asynchronous function starts a transmit operation.
* @post At the end of the operation the configured callback is invoked.
@@ -154,6 +166,9 @@ typedef struct { * @iclass
*/
#define qspiStartSendI(qspip, cmd, n, txbuf) { \
+ osalDbgAssert(((cmd)->cfg & QSPI_CFG_DATA_MODE_MASK) != \
+ QSPI_CFG_DATA_MODE_NONE, \
+ "data mode required"); \
(qspip)->state = QSPI_ACTIVE; \
qspi_lld_send(qspip, cmd, n, txbuf); \
}
@@ -171,6 +186,9 @@ typedef struct { * @iclass
*/
#define qspiStartReceiveI(qspip, cmd, n, rxbuf) { \
+ osalDbgAssert(((cmd)->cfg & QSPI_CFG_DATA_MODE_MASK) != \
+ QSPI_CFG_DATA_MODE_NONE, \
+ "data mode required"); \
(qspip)->state = QSPI_ACTIVE; \
qspi_lld_receive(qspip, cmd, n, rxbuf); \
}
@@ -235,11 +253,13 @@ extern "C" { void qspiObjectInit(QSPIDriver *qspip);
void qspiStart(QSPIDriver *qspip, const QSPIConfig *config);
void qspiStop(QSPIDriver *qspip);
+ void qspiStartCommand(QSPIDriver *qspip, const qspi_command_t *cmdp);
void qspiStartSend(QSPIDriver *qspip, const qspi_command_t *cmdp,
size_t n, const uint8_t *txbuf);
void qspiStartReceive(QSPIDriver *qspip, const qspi_command_t *cmdp,
size_t n, uint8_t *rxbuf);
#if QSPI_USE_WAIT == TRUE
+ void qspiCommand(QSPIDriver *qspip, const qspi_command_t *cmdp);
void qspiSend(QSPIDriver *qspip, const qspi_command_t *cmdp,
size_t n, const uint8_t *txbuf);
void qspiReceive(QSPIDriver *qspip, const qspi_command_t *cmdp,
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 4f4036a15..d395e0b43 100644 --- a/os/hal/ports/STM32/LLD/QUADSPIv1/hal_qspi_lld.c +++ b/os/hal/ports/STM32/LLD/QUADSPIv1/hal_qspi_lld.c @@ -123,21 +123,29 @@ void qspi_lld_init(void) { */
void qspi_lld_start(QSPIDriver *qspip) {
- /* If in stopped state then enables the QUADSPI and DMA clocks.*/
+ /* If in stopped state then full initialization.*/
if (qspip->state == QSPI_STOP) {
#if STM32_QSPI_USE_QUADSPI1
if (&QSPID1 == qspip) {
- rccEnableQUADSPI1(FALSE);
+ bool b = dmaStreamAllocate(qspip->dma,
+ STM32_QSPI_QUADSPI1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)qspi_lld_serve_dma_interrupt,
+ (void *)qspip);
+ osalDbgAssert(!b, "stream already allocated");
+ rccEnableQUADSPI1(false);
}
#endif
+
+ /* Common initializations.*/
+ dmaStreamSetPeripheral(qspip->dma, &qspip->qspi->DR);
}
/* QSPI setup and enable.*/
-// spip->spi->CR1 = 0;
-// spip->spi->CR1 = spip->config->cr1 | SPI_CR1_MSTR;
-// spip->spi->CR2 = spip->config->cr2 | SPI_CR2_FRXTH | SPI_CR2_SSOE |
-// SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN;
-// spip->spi->CR1 |= SPI_CR1_SPE;
+ qspip->qspi->CR = ((STM32_QSPI_QUADSPI1_PRESCALER_VALUE - 1U) << 24U) |
+ QUADSPI_CR_TCIE | QUADSPI_CR_TEIE | QUADSPI_CR_DMAEN |
+ QUADSPI_CR_EN;
+ qspip->qspi->FCR = QUADSPI_FCR_CTEF | QUADSPI_FCR_CTCF |
+ QUADSPI_FCR_CSMF | QUADSPI_FCR_CTOF;
}
/**
@@ -153,10 +161,12 @@ void qspi_lld_stop(QSPIDriver *qspip) { if (qspip->state == QSPI_READY) {
/* QSPI disable.*/
-// spip->spi->CR1 = 0;
-// spip->spi->CR2 = 0;
+ qspip->qspi->CR = 0U;
+
+ /* Releasing the DMA.*/
dmaStreamRelease(qspip->dma);
+ /* Stopping involved clocks.*/
#if STM32_QSPI_USE_QUADSPI1
if (&QSPID1 == qspip) {
rccDisableQUADSPI1(FALSE);
@@ -166,13 +176,32 @@ void qspi_lld_stop(QSPIDriver *qspip) { }
/**
- * @brief Sends data over the QSPI bus.
- * @details This asynchronous function starts a transmit operation.
+ * @brief Sends a command without data phase.
* @post At the end of the operation the configured callback is invoked.
*
* @param[in] qspip pointer to the @p QSPIDriver object
* @param[in] cmd pointer to the command descriptor
- * @param[in] n number of words to send
+ *
+ * @notapi
+ */
+void qspi_lld_command(QSPIDriver *qspip, const qspi_command_t *cmdp) {
+
+ qspip->qspi->CCR = cmdp->cfg;
+ if ((cmdp->cfg & QSPI_CFG_ALT_MODE_MASK) != QSPI_CFG_ALT_MODE_NONE) {
+ qspip->qspi->ABR = cmdp->alt;
+ }
+ if ((cmdp->cfg & QSPI_CFG_ADDR_MODE_MASK) != QSPI_CFG_ADDR_MODE_NONE) {
+ qspip->qspi->AR = cmdp->addr;
+ }
+}
+
+/**
+ * @brief Sends a command with data over the QSPI bus.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] qspip pointer to the @p QSPIDriver object
+ * @param[in] cmd pointer to the command descriptor
+ * @param[in] n number of bytes to send
* @param[in] txbuf the pointer to the transmit buffer
*
* @notapi
@@ -184,17 +213,21 @@ void qspi_lld_send(QSPIDriver *qspip, const qspi_command_t *cmdp, dmaStreamSetTransactionSize(qspip->dma, n);
dmaStreamSetMode(qspip->dma, qspip->dmamode | STM32_DMA_CR_DIR_M2P);
+ qspip->qspi->DLR = n - 1;
+ qspip->qspi->ABR = cmdp->alt;
+ qspip->qspi->CCR = cmdp->cfg;
+ qspip->qspi->AR = cmdp->addr;
+
dmaStreamEnable(qspip->dma);
}
/**
- * @brief Receives data from the QSPI bus.
- * @details This asynchronous function starts a receive operation.
+ * @brief Sends a command then receives data over the QSPI bus.
* @post At the end of the operation the configured callback is invoked.
*
* @param[in] qspip pointer to the @p QSPIDriver object
* @param[in] cmd pointer to the command descriptor
- * @param[in] n number of words to receive
+ * @param[in] n number of bytes to send
* @param[out] rxbuf the pointer to the receive buffer
*
* @notapi
@@ -206,6 +239,11 @@ void qspi_lld_receive(QSPIDriver *qspip, const qspi_command_t *cmdp, dmaStreamSetTransactionSize(qspip->dma, n);
dmaStreamSetMode(qspip->dma, qspip->dmamode | STM32_DMA_CR_DIR_P2M);
+ qspip->qspi->DLR = n - 1;
+ qspip->qspi->ABR = cmdp->alt;
+ qspip->qspi->CCR = cmdp->cfg | QUADSPI_CCR_FMODE_0;
+ qspip->qspi->AR = cmdp->addr;
+
dmaStreamEnable(qspip->dma);
}
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 14dc01b2f..100572dfc 100644 --- a/os/hal/ports/STM32/LLD/QUADSPIv1/hal_qspi_lld.h +++ b/os/hal/ports/STM32/LLD/QUADSPIv1/hal_qspi_lld.h @@ -49,6 +49,16 @@ #endif
/**
+ * @brief QUADSPI1 prescaler setting.
+ * @note This is the prescaler divider value 1..256. The maximum frequency
+ * varies depending on the STM32 model and operating conditions,
+ * find the details in the data sheet.
+ */
+#if !defined(STM32_QSPI_QUADSPI1_PRESCALER_VALUE) || defined(__DOXYGEN__)
+#define STM32_QSPI_QUADSPI1_PRESCALER_VALUE 4
+#endif
+
+/**
* @brief QUADSPI1 interrupt priority level setting.
*/
#if !defined(STM32_QSPI_QUADSPI1_IRQ_PRIORITY) || defined(__DOXYGEN__)
@@ -199,6 +209,7 @@ extern "C" { void qspi_lld_init(void);
void qspi_lld_start(QSPIDriver *qspip);
void qspi_lld_stop(QSPIDriver *qspip);
+ void qspi_lld_command(QSPIDriver *qspip, const qspi_command_t *cmdp);
void qspi_lld_send(QSPIDriver *qspip, const qspi_command_t *cmdp,
size_t n, const uint8_t *txbuf);
void qspi_lld_receive(QSPIDriver *qspip, const qspi_command_t *cmdp,
diff --git a/os/hal/ports/STM32/STM32L4xx/stm32_registry.h b/os/hal/ports/STM32/STM32L4xx/stm32_registry.h index a1474a5c4..09de989ca 100644 --- a/os/hal/ports/STM32/STM32L4xx/stm32_registry.h +++ b/os/hal/ports/STM32/STM32L4xx/stm32_registry.h @@ -211,7 +211,8 @@ /* QUADSPI attributes.*/
#define STM32_HAS_QUADSPI1 TRUE
-#define STM32_QUADSPI1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 7))
+#define STM32_QUADSPI1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\
+ STM32_DMA_STREAM_ID_MSK(2, 7))
#define STM32_QUADSPI1_DMA_CHN 0x03000000
/* RTC attributes.*/
diff --git a/os/hal/src/hal_qspi.c b/os/hal/src/hal_qspi.c index 3070eeb66..6fdb0c3a0 100644 --- a/os/hal/src/hal_qspi.c +++ b/os/hal/src/hal_qspi.c @@ -123,13 +123,31 @@ void qspiStop(QSPIDriver *qspip) { }
/**
- * @brief Sends data over the QSPI bus.
- * @details This asynchronous function starts a transmit operation.
+ * @brief Sends a command without data phase.
* @post At the end of the operation the configured callback is invoked.
*
* @param[in] qspip pointer to the @p QSPIDriver object
* @param[in] cmd pointer to the command descriptor
- * @param[in] n number of words to send or zero if no data phase
+ *
+ * @api
+ */
+void qspiStartCommand(QSPIDriver *qspip, const qspi_command_t *cmdp) {
+
+ osalDbgCheck((qspip != NULL) && (cmdp != NULL));
+
+ osalSysLock();
+ osalDbgAssert(qspip->state == QSPI_READY, "not ready");
+ qspiStartCommandI(qspip, cmd);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Sends a command with data over the QSPI bus.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] qspip pointer to the @p QSPIDriver object
+ * @param[in] cmd pointer to the command descriptor
+ * @param[in] n number of bytes to send
* @param[in] txbuf the pointer to the transmit buffer
*
* @api
@@ -138,7 +156,7 @@ void qspiStartSend(QSPIDriver *qspip, const qspi_command_t *cmdp, size_t n, const uint8_t *txbuf) {
osalDbgCheck((qspip != NULL) && (cmdp != NULL));
- osalDbgCheck((n == 0U) || ((n > 0U) && (txbuf != NULL)));
+ osalDbgCheck((n > 0U) && (txbuf != NULL));
osalSysLock();
osalDbgAssert(qspip->state == QSPI_READY, "not ready");
@@ -147,13 +165,12 @@ void qspiStartSend(QSPIDriver *qspip, const qspi_command_t *cmdp, }
/**
- * @brief Receives data from the QSPI bus.
- * @details This asynchronous function starts a receive operation.
+ * @brief Sends a command then receives data over the QSPI bus.
* @post At the end of the operation the configured callback is invoked.
*
* @param[in] qspip pointer to the @p QSPIDriver object
* @param[in] cmd pointer to the command descriptor
- * @param[in] n number of words to receive or zero if no data phase
+ * @param[in] n number of bytes to send
* @param[out] rxbuf the pointer to the receive buffer
*
* @api
@@ -162,7 +179,7 @@ void qspiStartReceive(QSPIDriver *qspip, const qspi_command_t *cmdp, size_t n, uint8_t *rxbuf) {
osalDbgCheck((qspip != NULL) && (cmdp != NULL));
- osalDbgCheck((n == 0U) || ((n > 0U) && (rxbuf != NULL)));
+ osalDbgCheck((n > 0U) && (rxbuf != NULL));
osalSysLock();
osalDbgAssert(qspip->state == QSPI_READY, "not ready");
@@ -172,8 +189,31 @@ void qspiStartReceive(QSPIDriver *qspip, const qspi_command_t *cmdp, #if (QSPI_USE_WAIT == TRUE) || defined(__DOXYGEN__)
/**
- * @brief Sends data over the QSPI bus.
- * @details This synchronous function performs a transmit operation.
+ * @brief Sends a command without data phase.
+ * @pre In order to use this function the option @p QSPI_USE_WAIT must be
+ * enabled.
+ * @pre In order to use this function the driver must have been configured
+ * without callbacks (@p end_cb = @p NULL).
+ *
+ * @param[in] qspip pointer to the @p QSPIDriver object
+ * @param[in] cmd pointer to the command descriptor
+ *
+ * @api
+ */
+void qspiCommand(QSPIDriver *qspip, const qspi_command_t *cmdp) {
+
+ osalDbgCheck((qspip != NULL) && (cmdp != NULL));
+
+ osalSysLock();
+ osalDbgAssert(qspip->state == QSPI_READY, "not ready");
+ osalDbgAssert(qspip->config->end_cb == NULL, "has callback");
+ qspiStartCommandI(qspip, cmd, n, txbuf);
+ (void) osalThreadSuspendS(&qspip->thread);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Sends a command with data over the QSPI bus.
* @pre In order to use this function the option @p QSPI_USE_WAIT must be
* enabled.
* @pre In order to use this function the driver must have been configured
@@ -181,7 +221,7 @@ void qspiStartReceive(QSPIDriver *qspip, const qspi_command_t *cmdp, *
* @param[in] qspip pointer to the @p QSPIDriver object
* @param[in] cmd pointer to the command descriptor
- * @param[in] n number of words to send or zero if no data phase
+ * @param[in] n number of bytes to send
* @param[in] txbuf the pointer to the transmit buffer
*
* @api
@@ -190,7 +230,7 @@ void qspiSend(QSPIDriver *qspip, const qspi_command_t *cmdp, size_t n, const uint8_t *txbuf) {
osalDbgCheck((qspip != NULL) && (cmdp != NULL));
- osalDbgCheck((n == 0U) || ((n > 0U) && (txbuf != NULL)));
+ osalDbgCheck((n > 0U) && (txbuf != NULL));
osalSysLock();
osalDbgAssert(qspip->state == QSPI_READY, "not ready");
@@ -201,8 +241,7 @@ void qspiSend(QSPIDriver *qspip, const qspi_command_t *cmdp, }
/**
- * @brief Receives data from the QSPI bus.
- * @details This synchronous function performs a receive operation.
+ * @brief Sends a command then receives data over the QSPI bus.
* @pre In order to use this function the option @p QSPI_USE_WAIT must be
* enabled.
* @pre In order to use this function the driver must have been configured
@@ -210,7 +249,7 @@ void qspiSend(QSPIDriver *qspip, const qspi_command_t *cmdp, *
* @param[in] qspip pointer to the @p QSPIDriver object
* @param[in] cmd pointer to the command descriptor
- * @param[in] n number of words to receive or zero if no data phase
+ * @param[in] n number of bytes to send
* @param[out] rxbuf the pointer to the receive buffer
*
* @api
@@ -219,7 +258,7 @@ void qspiReceive(QSPIDriver *qspip, const qspi_command_t *cmdp, size_t n, uint8_t *rxbuf) {
osalDbgCheck((qspip != NULL) && (cmdp != NULL));
- osalDbgCheck((n == 0U) || ((n > 0U) && (rxbuf != NULL)));
+ osalDbgCheck((n > 0U) && (rxbuf != NULL));
osalSysLock();
osalDbgAssert(qspip->state == QSPI_READY, "not ready");
|