From 9487a1f58c40b5cc3bc98c0eb14dfd1a0c18b8c2 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 28 Oct 2018 15:32:45 +0000 Subject: OCTOSPI driver and demo, to be tested. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@12395 110e8d01-0319-4d1e-a829-52ad28d1bb01 --- os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.c | 105 +++++++++++++++---- os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.h | 128 +++++++++++++++++++++++- 2 files changed, 213 insertions(+), 20 deletions(-) (limited to 'os/hal/ports/STM32/LLD/OCTOSPIv1') diff --git a/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.c b/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.c index 209ac1109..43a7a82a8 100644 --- a/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.c +++ b/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.c @@ -30,6 +30,11 @@ /* Driver local definitions. */ /*===========================================================================*/ +/* Workarounds for bugs in ST headers.*/ +#if !defined(OCTOSPI_FCR_CTOF) && defined(OCTOSPI_FCR_TOF) +#define OCTOSPI_FCR_CTOF OCTOSPI_FCR_TOF +#endif + /*===========================================================================*/ /* Driver exported variables. */ /*===========================================================================*/ @@ -39,6 +44,11 @@ WSPIDriver WSPID1; #endif +/** @brief OCTOSPI2 driver identifier.*/ +#if STM32_WSPI_USE_OCTOSPI2 || defined(__DOXYGEN__) +WSPIDriver WSPID2; +#endif + /*===========================================================================*/ /* Driver local variables and types. */ /*===========================================================================*/ @@ -102,8 +112,8 @@ OSAL_IRQ_HANDLER(STM32_OCTOSPI1_HANDLER) { OSAL_IRQ_PROLOGUE(); - OCTOSPI->FCR = OCTOSPI_FCR_CTEF | OCTOSPI_FCR_CTCF | - OCTOSPI_FCR_CSMF | OCTOSPI_FCR_CTOF; + OCTOSPI1->FCR = OCTOSPI_FCR_CTEF | OCTOSPI_FCR_CTCF | + OCTOSPI_FCR_CSMF | OCTOSPI_FCR_CTOF; wspi_lld_serve_interrupt(&WSPID1); @@ -112,6 +122,30 @@ OSAL_IRQ_HANDLER(STM32_OCTOSPI1_HANDLER) { #endif /* !defined(STM32_OCTOSPI1_SUPPRESS_ISR) */ #endif /* STM32_WSPI_USE_OCTOSPI1 */ +#if STM32_WSPI_USE_OCTOSPI2 || defined(__DOXYGEN__) +#if !defined(STM32_OCTOSPI2_SUPPRESS_ISR) +#if !defined(STM32_OCTOSPI2_HANDLER) +#error "STM32_OCTOSPI2_HANDLER not defined" +#endif +/** + * @brief STM32_OCTOSPI2_HANDLER interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_OCTOSPI2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + OCTOSPI2->FCR = OCTOSPI_FCR_CTEF | OCTOSPI_FCR_CTCF | + OCTOSPI_FCR_CSMF | OCTOSPI_FCR_CTOF; + + wspi_lld_serve_interrupt(&WSPID2); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_OCTOSPI2_SUPPRESS_ISR) */ +#endif /* STM32_WSPI_USE_OCTOSPI2 */ + /*===========================================================================*/ /* Driver exported functions. */ /*===========================================================================*/ @@ -125,8 +159,8 @@ void wspi_lld_init(void) { #if STM32_WSPI_USE_OCTOSPI1 wspiObjectInit(&WSPID1); - WSPID1.ospi = OCTOSPI; - WSPID1.dma = STM32_DMA_STREAM(STM32_WSPI_OCTOSPI1_DMA_STREAM); + WSPID1.ospi = OCTOSPI1; + WSPID1.dma = STM32_DMA_STREAM(STM32_WSPI_OCTOSPI1_DMA_CHANNEL); WSPID1.dmamode = STM32_DMA_CR_CHSEL(OCTOSPI1_DMA_CHANNEL) | STM32_DMA_CR_PL(STM32_WSPI_OCTOSPI1_DMA_PRIORITY) | STM32_DMA_CR_PSIZE_BYTE | @@ -136,6 +170,20 @@ void wspi_lld_init(void) { STM32_DMA_CR_TEIE; nvicEnableVector(STM32_OCTOSPI1_NUMBER, STM32_WSPI_OCTOSPI1_IRQ_PRIORITY); #endif + +#if STM32_WSPI_USE_OCTOSPI2 + wspiObjectInit(&WSPID2); + WSPID2.ospi = OCTOSPI2; + WSPID2.dma = STM32_DMA_STREAM(STM32_WSPI_OCTOSPI2_DMA_CHANNEL); + WSPID2.dmamode = STM32_DMA_CR_CHSEL(OCTOSPI2_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_WSPI_OCTOSPI2_DMA_PRIORITY) | + STM32_DMA_CR_PSIZE_BYTE | + STM32_DMA_CR_MSIZE_BYTE | + STM32_DMA_CR_MINC | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + nvicEnableVector(STM32_OCTOSPI2_NUMBER, STM32_WSPI_OCTOSPI2_IRQ_PRIORITY); +#endif } /** @@ -160,16 +208,29 @@ void wspi_lld_start(WSPIDriver *wspip) { } #endif +#if STM32_WSPI_USE_OCTOSPI2 + if (&WSPID2 == wspip) { + bool b = dmaStreamAllocate(wspip->dma, + STM32_WSPI_OCTOSPI2_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)wspi_lld_serve_dma_interrupt, + (void *)wspip); + osalDbgAssert(!b, "stream already allocated"); + rccEnableOCTOSPI2(true); + } +#endif + /* Common initializations.*/ dmaStreamSetPeripheral(wspip->dma, &wspip->ospi->DR); } /* WSPI setup and enable.*/ - wspip->ospi->DCR = wspip->config->dcr; - wspip->ospi->CR = ((STM32_WSPI_OCTOSPI1_PRESCALER_VALUE - 1U) << 24U) | - OCTOSPI_CR_TCIE | OCTOSPI_CR_DMAEN | OCTOSPI_CR_EN; - wspip->ospi->FCR = OCTOSPI_FCR_CTEF | OCTOSPI_FCR_CTCF | - OCTOSPI_FCR_CSMF | OCTOSPI_FCR_CTOF; + wspip->ospi->DCR1 = wspip->config->dcr1; + wspip->ospi->DCR2 = wspip->config->dcr2 | + STM32_DCR2_PRESCALER(STM32_WSPI_OCTOSPI1_PRESCALER_VALUE - 1U); + wspip->ospi->DCR3 = wspip->config->dcr3; + wspip->ospi->CR = OCTOSPI_CR_TCIE | OCTOSPI_CR_DMAEN | OCTOSPI_CR_EN; + wspip->ospi->FCR = OCTOSPI_FCR_CTEF | OCTOSPI_FCR_CTCF | + OCTOSPI_FCR_CSMF | OCTOSPI_FCR_CTOF; } /** @@ -210,7 +271,7 @@ void wspi_lld_stop(WSPIDriver *wspip) { */ void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp) { -#if STM32_USE_STM32_D1_WORKAROUND == TRUE +#if 0 //STM32_USE_STM32_D1_WORKAROUND == TRUE /* If it is a command without address and alternate phases then the command is sent as an alternate byte, the command phase is suppressed.*/ if ((cmdp->cfg & (WSPI_CFG_ADDR_MODE_MASK | WSPI_CFG_ALT_MODE_MASK)) == 0U) { @@ -222,9 +283,12 @@ void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp) { return; } #endif + wspip->ospi->CR &= ~OCTOSPI_CR_FMODE; wspip->ospi->DLR = 0U; + wspip->ospi->IR = cmdp->cmd; wspip->ospi->ABR = cmdp->alt; - wspip->ospi->CCR = cmdp->cmd | cmdp->cfg; + wspip->ospi->TCR = cmdp->dummy; + wspip->ospi->CCR = cmdp->cfg; if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) { wspip->ospi->AR = cmdp->addr; } @@ -248,9 +312,12 @@ void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp, dmaStreamSetTransactionSize(wspip->dma, n); dmaStreamSetMode(wspip->dma, wspip->dmamode | STM32_DMA_CR_DIR_M2P); + wspip->ospi->CR &= ~OCTOSPI_CR_FMODE; wspip->ospi->DLR = n - 1; + wspip->ospi->IR = cmdp->cmd; wspip->ospi->ABR = cmdp->alt; - wspip->ospi->CCR = cmdp->cmd | cmdp->cfg; + wspip->ospi->TCR = cmdp->dummy; + wspip->ospi->CCR = cmdp->cfg; if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) { wspip->ospi->AR = cmdp->addr; } @@ -276,11 +343,12 @@ void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp, dmaStreamSetTransactionSize(wspip->dma, n); dmaStreamSetMode(wspip->dma, wspip->dmamode | STM32_DMA_CR_DIR_P2M); + wspip->ospi->CR = (wspip->ospi->CR & ~OCTOSPI_CR_FMODE) | OCTOSPI_CR_FMODE_0; wspip->ospi->DLR = n - 1; + wspip->ospi->IR = cmdp->cmd; wspip->ospi->ABR = cmdp->alt; - wspip->ospi->CCR = cmdp->cmd | cmdp->cfg | - OCTOSPI_CCR_DUMMY_CYCLES(cmdp->dummy) | - OCTOSPI_CCR_FMODE_0; + wspip->ospi->TCR = cmdp->dummy; + wspip->ospi->CCR = cmdp->cfg; if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) { wspip->ospi->AR = cmdp->addr; } @@ -309,11 +377,14 @@ void wspi_lld_map_flash(WSPIDriver *wspip, wspip->ospi->CR &= ~OCTOSPI_CR_DMAEN; /* Starting memory mapped mode using the passed parameters.*/ + wspip->ospi->CR = (wspip->ospi->CR & ~OCTOSPI_CR_FMODE) | + (OCTOSPI_CR_FMODE_1 | OCTOSPI_CR_FMODE_0); wspip->ospi->DLR = 0; + wspip->ospi->IR = cmdp->cmd; wspip->ospi->ABR = 0; + wspip->ospi->TCR = cmdp->dummy; wspip->ospi->AR = 0; - wspip->ospi->CCR = cmdp->cmd | cmdp->cfg | - OCTOSPI_CCR_FMODE_1 | OCTOSPI_CCR_FMODE_0; + wspip->ospi->CCR = cmdp->cfg; /* Mapped flash absolute base address.*/ if (addrp != NULL) { diff --git a/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.h b/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.h index 7642dd71c..fd0ac2cd1 100644 --- a/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.h +++ b/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.h @@ -39,6 +39,46 @@ #define WSPI_DEFAULT_CFG_MASKS TRUE /** @} */ +/** + * @name DCR1 register options + * @{ + */ +#define STM32_DCR1_CK_MODE (1U << 0U) +#define STM32_DCR1_FRCK_MODE (1U << 1U) +#define STM32_DCR1_CSHT_MASK (7U << 8U) +#define STM32_DCR1_CSHT(n) ((n) << 8U) +#define STM32_DCR1_DEVSIZE_MASK (31U << 16U) +#define STM32_DCR1_DEVSIZE(n) ((n) << 16U) +#define STM32_DCR1_MTYP_MASK (7U << 16U) +#define STM32_DCR1_MTYP(n) ((n) << 24U) +/** @} */ + +/** + * @name DCR2 register options + * @{ + */ +#define STM32_DCR2_PRESCALER_MASK (255U << 0U) +#define STM32_DCR2_PRESCALER(n) ((n) << 0U) +#define STM32_DCR2_WRAPSIZE_MASK (7U << 16U) +#define STM32_DCR2_WRAPSIZE(n) ((n) << 16U) + +/** + * @name DCR3 register options + * @{ + */ +#define STM32_DCR3_MAXTRAN_MASK (255U << 0U) +#define STM32_DCR3_MAXTRAN(n) ((n) << 0U) +#define STM32_DCR3_CSBOUND_MASK (7U << 16U) +#define STM32_DCR3_CSBOUND(n) ((n) << 16U) + +/** + * @name DCR4 register options + * @{ + */ +#define STM32_DCR4_REFRESH_MASK (255U << 0U) +#define STM32_DCR4_REFRESH(n) ((n) << 0U) +/** @} */ + /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/ @@ -56,6 +96,15 @@ #define STM32_WSPI_USE_OCTOSPI1 FALSE #endif +/** + * @brief WSPID2 driver enable switch. + * @details If set to @p TRUE the support for OCTOSPI2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_WSPI_USE_OCTOSPI2) || defined(__DOXYGEN__) +#define STM32_WSPI_USE_OCTOSPI2 FALSE +#endif + /** * @brief OCTOSPI1 prescaler setting. * @note This is the prescaler divider value 1..256. The maximum frequency @@ -66,6 +115,16 @@ #define STM32_WSPI_OCTOSPI1_PRESCALER_VALUE 1 #endif +/** + * @brief OCTOSPI2 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_WSPI_OCTOSPI2_PRESCALER_VALUE) || defined(__DOXYGEN__) +#define STM32_WSPI_OCTOSPI2_PRESCALER_VALUE 1 +#endif + /** * @brief OCTOSPI1 interrupt priority level setting. */ @@ -73,6 +132,13 @@ #define STM32_WSPI_OCTOSPI1_IRQ_PRIORITY 10 #endif +/** + * @brief OCTOSPI2 interrupt priority level setting. + */ +#if !defined(STM32_WSPI_OCTOSPI2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_WSPI_OCTOSPI2_IRQ_PRIORITY 10 +#endif + /** * @brief OCTOSPI1 DMA priority (0..3|lowest..highest). */ @@ -80,6 +146,13 @@ #define STM32_WSPI_OCTOSPI1_DMA_PRIORITY 1 #endif +/** + * @brief OCTOSPI2 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_WSPI_OCTOSPI2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_WSPI_OCTOSPI2_DMA_PRIORITY 1 +#endif + /** * @brief OCTOSPI1 DMA interrupt priority level setting. */ @@ -87,6 +160,13 @@ #define STM32_WSPI_OCTOSPI1_DMA_IRQ_PRIORITY 10 #endif +/** + * @brief OCTOSPI2 DMA interrupt priority level setting. + */ +#if !defined(STM32_WSPI_OCTOSPI2_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_WSPI_OCTOSPI2_DMA_IRQ_PRIORITY 10 +#endif + /** * @brief OCTOSPI DMA error hook. */ @@ -103,11 +183,19 @@ #define STM32_HAS_OCTOSPI1 FALSE #endif +#if !defined(STM32_HAS_OCTOSPI2) +#define STM32_HAS_OCTOSPI2 FALSE +#endif + #if STM32_WSPI_USE_OCTOSPI1 && !STM32_HAS_OCTOSPI1 #error "OCTOSPI1 not present in the selected device" #endif -#if !STM32_WSPI_USE_OCTOSPI1 +#if STM32_WSPI_USE_OCTOSPI2 && !STM32_HAS_OCTOSPI2 +#error "OCTOSPI2 not present in the selected device" +#endif + +#if !STM32_WSPI_USE_OCTOSPI1 && !STM32_WSPI_USE_OCTOSPI2 #error "WSPI driver activated but no OCTOSPI peripheral assigned" #endif @@ -123,28 +211,52 @@ #error "Invalid IRQ priority assigned to OCTOSPI1" #endif +#if STM32_WSPI_USE_OCTOSPI2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to OCTOSPI2" +#endif + #if STM32_WSPI_USE_OCTOSPI1 && \ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI1_DMA_IRQ_PRIORITY) #error "Invalid IRQ priority assigned to OCTOSPI1 DMA" #endif -/* Check on the presence of the DMA chennels settings in mcuconf.h.*/ +#if STM32_WSPI_USE_OCTOSPI2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI2_DMA_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to OCTOSPI2 DMA" +#endif + +/* Check on the presence of the DMA channels settings in mcuconf.h.*/ #if STM32_WSPI_USE_OCTOSPI1 && !defined(STM32_WSPI_OCTOSPI1_DMA_CHANNEL) #error "OCTOSPI1 DMA channel not defined" #endif +#if STM32_WSPI_USE_OCTOSPI2 && !defined(STM32_WSPI_OCTOSPI2_DMA_CHANNEL) +#error "OCTOSPI2 DMA channel not defined" +#endif + /* Check on the validity of the assigned DMA channels.*/ #if STM32_WSPI_USE_OCTOSPI1 && \ - !STM32_DMA_IS_VALID_CHANNEL(STM32_OCTOSPI1_DMA_MSK) + !STM32_DMA_IS_VALID_CHANNEL(STM32_WSPI_OCTOSPI1_DMA_CHANNEL) #error "invalid DMA stream associated to OCTOSPI1" #endif +#if STM32_WSPI_USE_OCTOSPI2 && \ + !STM32_DMA_IS_VALID_CHANNEL(STM32_WSPI_OCTOSPI2_DMA_CHANNEL) +#error "invalid DMA stream associated to OCTOSPI2" +#endif + /* Check on DMA channels priority.*/ #if STM32_WSPI_USE_OCTOSPI1 && \ !STM32_DMA_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI1_DMA_PRIORITY) #error "Invalid DMA priority assigned to OCTOSPI1" #endif +#if STM32_WSPI_USE_OCTOSPI2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to OCTOSPI2" +#endif + #if !defined(STM32_DMA_REQUIRED) #define STM32_DMA_REQUIRED #endif @@ -168,12 +280,18 @@ struct hal_wspi_config { uint32_t dcr1; /** * @brief DCR2 register initialization data. + * @note Prescaler field is internally ORed to this field, leave it + * to zero. */ uint32_t dcr2; /** * @brief DCR3 register initialization data. */ uint32_t dcr3; + /** + * @brief DCR4 register initialization data. + */ + uint32_t dcr4; }; /** @@ -230,6 +348,10 @@ struct hal_wspi_driver { extern WSPIDriver WSPID1; #endif +#if (STM32_WSPI_USE_OCTOSPI2 == TRUE) && !defined(__DOXYGEN__) +extern WSPIDriver WSPID2; +#endif + #ifdef __cplusplus extern "C" { #endif -- cgit v1.2.3