git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@13302 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
parent
5c234f3ca7
commit
c0c88a59bf
|
@ -0,0 +1,9 @@
|
||||||
|
ifeq ($(USE_SMART_BUILD),yes)
|
||||||
|
ifneq ($(findstring HAL_USE_WSPI TRUE,$(HALCONF)),)
|
||||||
|
PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv2/hal_wspi_lld.c
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv2/hal_wspi_lld.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv2
|
|
@ -0,0 +1,357 @@
|
||||||
|
/*
|
||||||
|
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file QUADSPIv2//hal_wspi_lld.c
|
||||||
|
* @brief STM32 WSPI subsystem low level driver source.
|
||||||
|
*
|
||||||
|
* @addtogroup WSPI
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "hal.h"
|
||||||
|
|
||||||
|
#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__)
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver local definitions. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver exported variables. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/** @brief QUADSPI1 driver identifier.*/
|
||||||
|
#if STM32_WSPI_USE_QUADSPI1 || defined(__DOXYGEN__)
|
||||||
|
WSPIDriver WSPID1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver local variables and types. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver local functions. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Waits for completion of previous operation.
|
||||||
|
*/
|
||||||
|
static inline void wspi_lld_sync(WSPIDriver *wspip) {
|
||||||
|
|
||||||
|
while ((wspip->qspi->SR & QUADSPI_SR_BUSY) != 0U) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Shared service routine.
|
||||||
|
*
|
||||||
|
* @param[in] wspip pointer to the @p WSPIDriver object
|
||||||
|
* @param[in] flags content of the CISR register
|
||||||
|
*/
|
||||||
|
static void wspi_lld_serve_mdma_interrupt(WSPIDriver *wspip, uint32_t flags) {
|
||||||
|
|
||||||
|
(void)wspip;
|
||||||
|
(void)flags;
|
||||||
|
|
||||||
|
/* DMA errors handling.*/
|
||||||
|
#if defined(STM32_WSPI_MDMA_ERROR_HOOK)
|
||||||
|
if ((flags & STM32_MDMA_CISR_TEIF) != 0) {
|
||||||
|
STM32_WSPI_MDMA_ERROR_HOOK(wspip);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Shared service routine.
|
||||||
|
*
|
||||||
|
* @param[in] wspip pointer to the @p WSPIDriver object
|
||||||
|
*/
|
||||||
|
static void wspi_lld_serve_interrupt(WSPIDriver *wspip) {
|
||||||
|
|
||||||
|
/* Portable WSPI ISR code defined in the high level driver, note, it is
|
||||||
|
a macro.*/
|
||||||
|
_wspi_isr_code(wspip);
|
||||||
|
|
||||||
|
mdmaChannelDisableX(wspip->mdma);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver interrupt handlers. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
#if STM32_WSPI_USE_QUADSPI1 || defined(__DOXYGEN__)
|
||||||
|
#if !defined(STM32_QUADSPI1_SUPPRESS_ISR)
|
||||||
|
#if !defined(STM32_QUADSPI1_HANDLER)
|
||||||
|
#error "STM32_QUADSPI1_HANDLER not defined"
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* @brief STM32_QUADSPI1_HANDLER interrupt handler.
|
||||||
|
*
|
||||||
|
* @isr
|
||||||
|
*/
|
||||||
|
OSAL_IRQ_HANDLER(STM32_QUADSPI1_HANDLER) {
|
||||||
|
|
||||||
|
OSAL_IRQ_PROLOGUE();
|
||||||
|
|
||||||
|
QUADSPI->FCR = QUADSPI_FCR_CTEF | QUADSPI_FCR_CTCF |
|
||||||
|
QUADSPI_FCR_CSMF | QUADSPI_FCR_CTOF;
|
||||||
|
|
||||||
|
wspi_lld_serve_interrupt(&WSPID1);
|
||||||
|
|
||||||
|
OSAL_IRQ_EPILOGUE();
|
||||||
|
}
|
||||||
|
#endif /* !defined(STM32_QUADSPI1_SUPPRESS_ISR) */
|
||||||
|
#endif /* STM32_WSPI_USE_QUADSPI1 */
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver exported functions. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Low level WSPI driver initialization.
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
void wspi_lld_init(void) {
|
||||||
|
|
||||||
|
#if STM32_WSPI_USE_QUADSPI1
|
||||||
|
wspiObjectInit(&WSPID1);
|
||||||
|
WSPID1.qspi = QUADSPI;
|
||||||
|
WSPID1.mdma = NULL;
|
||||||
|
/* TODO WSPID1.mdmamode = STM32_DMA_CR_CHSEL(QUADSPI1_DMA_CHANNEL) |
|
||||||
|
STM32_DMA_CR_PL(STM32_WSPI_QUADSPI1_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_QUADSPI1_NUMBER, STM32_IRQ_QUADSPI1_PRIORITY);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Configures and activates the WSPI peripheral.
|
||||||
|
*
|
||||||
|
* @param[in] wspip pointer to the @p WSPIDriver object
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
void wspi_lld_start(WSPIDriver *wspip) {
|
||||||
|
|
||||||
|
/* If in stopped state then full initialization.*/
|
||||||
|
if (wspip->state == WSPI_STOP) {
|
||||||
|
#if STM32_WSPI_USE_QUADSPI1
|
||||||
|
if (&WSPID1 == wspip) {
|
||||||
|
wspip->mdma = mdmaChannelAllocI(STM32_WSPI_QUADSPI1_MDMA_CHANNEL,
|
||||||
|
(stm32_mdmaisr_t)wspi_lld_serve_mdma_interrupt,
|
||||||
|
(void *)wspip);
|
||||||
|
osalDbgAssert(wspip->mdma != NULL, "unable to allocate MDMA channel");
|
||||||
|
rccEnableQUADSPI1(true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WSPI setup and enable.*/
|
||||||
|
wspip->qspi->DCR = wspip->config->dcr;
|
||||||
|
wspip->qspi->CR = ((STM32_WSPI_QUADSPI1_PRESCALER_VALUE - 1U) << 24U) |
|
||||||
|
QUADSPI_CR_TCIE | QUADSPI_CR_DMAEN | QUADSPI_CR_EN;
|
||||||
|
wspip->qspi->FCR = QUADSPI_FCR_CTEF | QUADSPI_FCR_CTCF |
|
||||||
|
QUADSPI_FCR_CSMF | QUADSPI_FCR_CTOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deactivates the WSPI peripheral.
|
||||||
|
*
|
||||||
|
* @param[in] wspip pointer to the @p WSPIDriver object
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
void wspi_lld_stop(WSPIDriver *wspip) {
|
||||||
|
|
||||||
|
/* If in ready state then disables the QUADSPI clock.*/
|
||||||
|
if (wspip->state == WSPI_READY) {
|
||||||
|
|
||||||
|
/* WSPI disable.*/
|
||||||
|
wspip->qspi->CR = 0U;
|
||||||
|
|
||||||
|
/* Releasing the DMA.*/
|
||||||
|
mdmaChannelFreeI(wspip->mdma);
|
||||||
|
wspip->mdma = NULL;
|
||||||
|
|
||||||
|
/* Stopping involved clocks.*/
|
||||||
|
#if STM32_WSPI_USE_QUADSPI1
|
||||||
|
if (&WSPID1 == wspip) {
|
||||||
|
rccDisableQUADSPI1();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends a command without data phase.
|
||||||
|
* @post At the end of the operation the configured callback is invoked.
|
||||||
|
*
|
||||||
|
* @param[in] wspip pointer to the @p WSPIDriver object
|
||||||
|
* @param[in] cmdp pointer to the command descriptor
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp) {
|
||||||
|
|
||||||
|
#if 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) {
|
||||||
|
/* The command mode field is copied in the alternate mode field. All
|
||||||
|
other fields are not used in this scenario.*/
|
||||||
|
wspip->qspi->DLR = 0U;
|
||||||
|
wspip->qspi->ABR = cmdp->cmd;
|
||||||
|
wspip->qspi->CCR = (cmdp->cfg & WSPI_CFG_CMD_MODE_MASK) << 6U;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
wspip->qspi->DLR = 0U;
|
||||||
|
wspip->qspi->ABR = cmdp->alt;
|
||||||
|
wspip->qspi->CCR = cmdp->cmd | cmdp->cfg;
|
||||||
|
if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) {
|
||||||
|
wspip->qspi->AR = cmdp->addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Waiting for the previous operation to complete.*/
|
||||||
|
wspi_lld_sync(wspip);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends a command with data over the WSPI bus.
|
||||||
|
* @post At the end of the operation the configured callback is invoked.
|
||||||
|
*
|
||||||
|
* @param[in] wspip pointer to the @p WSPIDriver object
|
||||||
|
* @param[in] cmdp pointer to the command descriptor
|
||||||
|
* @param[in] n number of bytes to send
|
||||||
|
* @param[in] txbuf the pointer to the transmit buffer
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp,
|
||||||
|
size_t n, const uint8_t *txbuf) {
|
||||||
|
|
||||||
|
/* MDMA initializations.*/
|
||||||
|
mdmaChannelSetSourceX(wspip->mdma, &wspip->qspi->DR);
|
||||||
|
mdmaChannelSetDestinationX(wspip->mdma, txbuf);
|
||||||
|
mdmaChannelSetTransactionSizeX(wspip->mdma, n, 0, 0);
|
||||||
|
mdmaChannelSetModeX(wspip->mdma, wspip->mdmactcr, wspip->mdmaccr);
|
||||||
|
|
||||||
|
wspip->qspi->DLR = n - 1;
|
||||||
|
wspip->qspi->ABR = cmdp->alt;
|
||||||
|
wspip->qspi->CCR = cmdp->cmd | cmdp->cfg;
|
||||||
|
if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) {
|
||||||
|
wspip->qspi->AR = cmdp->addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
mdmaChannelEnableX(wspip->mdma);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends a command then receives data over the WSPI bus.
|
||||||
|
* @post At the end of the operation the configured callback is invoked.
|
||||||
|
*
|
||||||
|
* @param[in] wspip pointer to the @p WSPIDriver object
|
||||||
|
* @param[in] cmdp pointer to the command descriptor
|
||||||
|
* @param[in] n number of bytes to send
|
||||||
|
* @param[out] rxbuf the pointer to the receive buffer
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp,
|
||||||
|
size_t n, uint8_t *rxbuf) {
|
||||||
|
|
||||||
|
/* MDMA initializations.*/
|
||||||
|
mdmaChannelSetSourceX(wspip->mdma, rxbuf);
|
||||||
|
mdmaChannelSetDestinationX(wspip->mdma, &wspip->qspi->DR);
|
||||||
|
mdmaChannelSetTransactionSizeX(wspip->mdma, n, 0, 0);
|
||||||
|
mdmaChannelSetModeX(wspip->mdma, wspip->mdmactcr, wspip->mdmaccr);
|
||||||
|
|
||||||
|
wspip->qspi->DLR = n - 1;
|
||||||
|
wspip->qspi->ABR = cmdp->alt;
|
||||||
|
wspip->qspi->CCR = cmdp->cmd | cmdp->cfg |
|
||||||
|
QUADSPI_CCR_DUMMY_CYCLES(cmdp->dummy) |
|
||||||
|
QUADSPI_CCR_FMODE_0;
|
||||||
|
if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) {
|
||||||
|
wspip->qspi->AR = cmdp->addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
mdmaChannelEnableX(wspip->mdma);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__)
|
||||||
|
/**
|
||||||
|
* @brief Maps in memory space a WSPI flash device.
|
||||||
|
* @pre The memory flash device must be initialized appropriately
|
||||||
|
* before mapping it in memory space.
|
||||||
|
*
|
||||||
|
* @param[in] wspip pointer to the @p WSPIDriver 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 wspi_lld_map_flash(WSPIDriver *wspip,
|
||||||
|
const wspi_command_t *cmdp,
|
||||||
|
uint8_t **addrp) {
|
||||||
|
|
||||||
|
/* Disabling the DMA request while in memory mapped mode.*/
|
||||||
|
wspip->qspi->CR &= ~QUADSPI_CR_DMAEN;
|
||||||
|
|
||||||
|
/* Starting memory mapped mode using the passed parameters.*/
|
||||||
|
wspip->qspi->DLR = 0;
|
||||||
|
wspip->qspi->ABR = 0;
|
||||||
|
wspip->qspi->AR = 0;
|
||||||
|
wspip->qspi->CCR = cmdp->cmd | cmdp->cfg |
|
||||||
|
QUADSPI_CCR_DUMMY_CYCLES(cmdp->dummy) |
|
||||||
|
QUADSPI_CCR_FMODE_1 | QUADSPI_CCR_FMODE_0;
|
||||||
|
|
||||||
|
/* Mapped flash absolute base address.*/
|
||||||
|
if (addrp != NULL) {
|
||||||
|
*addrp = (uint8_t *)0x90000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unmaps from memory space a WSPI flash device.
|
||||||
|
* @post The memory flash device must be re-initialized for normal
|
||||||
|
* commands exchange.
|
||||||
|
*
|
||||||
|
* @param[in] wspip pointer to the @p WSPIDriver object
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
void wspi_lld_unmap_flash(WSPIDriver *wspip) {
|
||||||
|
|
||||||
|
/* Aborting memory mapped mode.*/
|
||||||
|
wspip->qspi->CR |= QUADSPI_CR_ABORT;
|
||||||
|
while ((wspip->qspi->CR & QUADSPI_CR_ABORT) != 0U) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Re-enabling DMA request, we are going back to indirect mode.*/
|
||||||
|
wspip->qspi->CR |= QUADSPI_CR_DMAEN;
|
||||||
|
}
|
||||||
|
#endif /* WSPI_SUPPORTS_MEMMAP == TRUE */
|
||||||
|
|
||||||
|
#endif /* HAL_USE_WSPI */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,292 @@
|
||||||
|
/*
|
||||||
|
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file QUADSPIv2/hal_wspi_lld.h
|
||||||
|
* @brief STM32 WSPI subsystem low level driver header.
|
||||||
|
*
|
||||||
|
* @addtogroup WSPI
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAL_WSPI_LLD_H
|
||||||
|
#define HAL_WSPI_LLD_H
|
||||||
|
|
||||||
|
#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__)
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver constants. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name WSPI implementation capabilities
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define WSPI_SUPPORTS_MEMMAP TRUE
|
||||||
|
#define WSPI_DEFAULT_CFG_MASKS FALSE
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Transfer options
|
||||||
|
* @note The low level driver has the option to override the following
|
||||||
|
* definitions and use its own ones. In must take care to use
|
||||||
|
* the same name for the same function or compatibility is not
|
||||||
|
* ensured.
|
||||||
|
* @note There are the following limitations in this implementation:
|
||||||
|
* - Eight lines are not supported.
|
||||||
|
* - DDR mode is only supported for the whole command, separate
|
||||||
|
* masks are defined but all define the same bit.
|
||||||
|
* - Only 8 bits instructions are supported.
|
||||||
|
* .
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define WSPI_CFG_CMD_MODE_MASK (3LU << 8LU)
|
||||||
|
#define WSPI_CFG_CMD_MODE_NONE (0LU << 8LU)
|
||||||
|
#define WSPI_CFG_CMD_MODE_ONE_LINE (1LU << 8LU)
|
||||||
|
#define WSPI_CFG_CMD_MODE_TWO_LINES (2LU << 8LU)
|
||||||
|
#define WSPI_CFG_CMD_MODE_FOUR_LINES (3LU << 8LU)
|
||||||
|
|
||||||
|
#define WSPI_CFG_CMD_DDR (1LU << 31LU)
|
||||||
|
|
||||||
|
#define WSPI_CFG_CMD_SIZE_MASK 0LU
|
||||||
|
#define WSPI_CFG_CMD_SIZE_8 0LU
|
||||||
|
|
||||||
|
#define WSPI_CFG_ADDR_MODE_MASK (3LU << 10LU)
|
||||||
|
#define WSPI_CFG_ADDR_MODE_NONE (0LU << 10LU)
|
||||||
|
#define WSPI_CFG_ADDR_MODE_ONE_LINE (1LU << 10LU)
|
||||||
|
#define WSPI_CFG_ADDR_MODE_TWO_LINES (2LU << 10LU)
|
||||||
|
#define WSPI_CFG_ADDR_MODE_FOUR_LINES (3LU << 10LU)
|
||||||
|
|
||||||
|
#define WSPI_CFG_ADDR_DDR (1LU << 31LU)
|
||||||
|
|
||||||
|
#define WSPI_CFG_ADDR_SIZE_MASK (3LU << 12LU)
|
||||||
|
#define WSPI_CFG_ADDR_SIZE_8 (0LU << 12LU)
|
||||||
|
#define WSPI_CFG_ADDR_SIZE_16 (1LU << 12LU)
|
||||||
|
#define WSPI_CFG_ADDR_SIZE_24 (2LU << 12LU)
|
||||||
|
#define WSPI_CFG_ADDR_SIZE_32 (3LU << 12LU)
|
||||||
|
|
||||||
|
#define WSPI_CFG_ALT_MODE_MASK (3LU << 14LU)
|
||||||
|
#define WSPI_CFG_ALT_MODE_NONE (0LU << 14LU)
|
||||||
|
#define WSPI_CFG_ALT_MODE_ONE_LINE (1LU << 14LU)
|
||||||
|
#define WSPI_CFG_ALT_MODE_TWO_LINES (2LU << 14LU)
|
||||||
|
#define WSPI_CFG_ALT_MODE_FOUR_LINES (3LU << 14LU)
|
||||||
|
|
||||||
|
#define WSPI_CFG_ALT_DDR (1LU << 31LU)
|
||||||
|
|
||||||
|
#define WSPI_CFG_ALT_SIZE_MASK (3LU << 16LU)
|
||||||
|
#define WSPI_CFG_ALT_SIZE_8 (0LU << 16LU)
|
||||||
|
#define WSPI_CFG_ALT_SIZE_16 (1LU << 16LU)
|
||||||
|
#define WSPI_CFG_ALT_SIZE_24 (2LU << 16LU)
|
||||||
|
#define WSPI_CFG_ALT_SIZE_32 (3LU << 16LU)
|
||||||
|
|
||||||
|
#define WSPI_CFG_DATA_MODE_MASK (3LU << 24LU)
|
||||||
|
#define WSPI_CFG_DATA_MODE_NONE (0LU << 24LU)
|
||||||
|
#define WSPI_CFG_DATA_MODE_ONE_LINE (1LU << 24LU)
|
||||||
|
#define WSPI_CFG_DATA_MODE_TWO_LINES (2LU << 24LU)
|
||||||
|
#define WSPI_CFG_DATA_MODE_FOUR_LINES (3LU << 24LU)
|
||||||
|
|
||||||
|
#define WSPI_CFG_DATA_DDR (1LU << 31LU)
|
||||||
|
|
||||||
|
#define WSPI_CFG_SIOO (1LU << 28LU)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Helpers for CCR register.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define QUADSPI_CCR_DUMMY_CYCLES_MASK (0x1FLU << 18LU)
|
||||||
|
#define QUADSPI_CCR_DUMMY_CYCLES(n) ((n) << 18LU)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name DCR register options
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define STM32_DCR_CK_MODE (1U << 0U)
|
||||||
|
#define STM32_DCR_CSHT_MASK (7U << 8U)
|
||||||
|
#define STM32_DCR_CSHT(n) ((n) << 8U)
|
||||||
|
#define STM32_DCR_FSIZE_MASK (31U << 16U)
|
||||||
|
#define STM32_DCR_FSIZE(n) ((n) << 16U)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver pre-compile time settings. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Configuration options
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @brief WSPID1 driver enable switch.
|
||||||
|
* @details If set to @p TRUE the support for QUADSPI1 is included.
|
||||||
|
* @note The default is @p FALSE.
|
||||||
|
*/
|
||||||
|
#if !defined(STM32_WSPI_USE_QUADSPI1) || defined(__DOXYGEN__)
|
||||||
|
#define STM32_WSPI_USE_QUADSPI1 FALSE
|
||||||
|
#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_WSPI_QUADSPI1_PRESCALER_VALUE) || defined(__DOXYGEN__)
|
||||||
|
#define STM32_WSPI_QUADSPI1_PRESCALER_VALUE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief QUADSPI1 MDMA priority (0..3|lowest..highest).
|
||||||
|
*/
|
||||||
|
#if !defined(STM32_WSPI_QUADSPI1_MDMA_PRIORITY) || defined(__DOXYGEN__)
|
||||||
|
#define STM32_WSPI_QUADSPI1_MDMA_PRIORITY 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief QUADSPI MDMA error hook.
|
||||||
|
*/
|
||||||
|
#if !defined(STM32_WSPI_MDMA_ERROR_HOOK) || defined(__DOXYGEN__)
|
||||||
|
#define STM32_WSPI_MDMA_ERROR_HOOK(qspip) osalSysHalt("MDMA failure")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enables a workaround for a STM32L476 QUADSPI errata.
|
||||||
|
* @details The document DM00111498 states: "QUADSPI_BK1_IO1 is always an
|
||||||
|
* input when the command is sent in dual or quad SPI mode".
|
||||||
|
* This workaround makes commands without address or data phases
|
||||||
|
* to be sent as alternate bytes.
|
||||||
|
*/
|
||||||
|
#if !defined(STM32_USE_STM32_D1_WORKAROUND) || defined(__DOXYGEN__)
|
||||||
|
#define STM32_USE_STM32_D1_WORKAROUND TRUE
|
||||||
|
#endif
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Derived constants and error checks. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
#if !defined(STM32_HAS_QUADSPI1)
|
||||||
|
#define STM32_HAS_QUADSPI1 FALSE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if STM32_WSPI_USE_QUADSPI1 && !STM32_HAS_QUADSPI1
|
||||||
|
#error "QUADSPI1 not present in the selected device"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !STM32_WSPI_USE_QUADSPI1
|
||||||
|
#error "WSPI driver activated but no QUADSPI peripheral assigned"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Priority settings checks.*/
|
||||||
|
#if !defined(STM32_IRQ_QUADSPI1_PRIORITY)
|
||||||
|
#error "STM32_IRQ_QUADSPI1_PRIORITY not defined in mcuconf.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if STM32_WSPI_USE_QUADSPI1 && \
|
||||||
|
!OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_QUADSPI1_PRIORITY)
|
||||||
|
#error "Invalid IRQ priority assigned to QUADSPI1"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* MDMA-related checks.*/
|
||||||
|
#if STM32_WSPI_USE_QUADSPI1 && \
|
||||||
|
!STM32_MDMA_IS_VALID_PRIORITY(STM32_WSPI_QUADSPI1_MDMA_PRIORITY)
|
||||||
|
#error "Invalid MDMA priority assigned to QUADSPI1"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Checks on prescaler setting.*/
|
||||||
|
#if (STM32_WSPI_QUADSPI1_PRESCALER_VALUE < 1) || \
|
||||||
|
(STM32_WSPI_QUADSPI1_PRESCALER_VALUE > 256)
|
||||||
|
#error "STM32_WSPI_QUADSPI1_PRESCALER_VALUE not within 1..256"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Check on the presence of the DMA channels settings in mcuconf.h.*/
|
||||||
|
#if STM32_WSPI_USE_QUADSPI1 && !defined(STM32_WSPI_QUADSPI1_MDMA_CHANNEL)
|
||||||
|
#error "QUADSPI1 MDMA channel not defined"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Check on the validity of the assigned DMA channels.*/
|
||||||
|
#if STM32_WSPI_USE_QUADSPI1 && \
|
||||||
|
!STM32_MDMA_IS_VALID_CHANNEL(STM32_WSPI_QUADSPI1_MDMA_CHANNEL)
|
||||||
|
#error "invalid MDMA channel associated to QUADSPI1"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(STM32_MDMA_REQUIRED)
|
||||||
|
#define STM32_MDMA_REQUIRED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver data structures and types. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver macros. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Low level fields of the WSPI configuration structure.
|
||||||
|
*/
|
||||||
|
#define wspi_lld_config_fields \
|
||||||
|
/* DCR register initialization data.*/ \
|
||||||
|
uint32_t dcr
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Low level fields of the WSPI driver structure.
|
||||||
|
*/
|
||||||
|
#define wspi_lld_driver_fields \
|
||||||
|
/* Pointer to the QUADSPIx registers block.*/ \
|
||||||
|
QUADSPI_TypeDef *qspi; \
|
||||||
|
/* QUADSPI MDMA channel.*/ \
|
||||||
|
const stm32_mdma_channel_t *mdma; \
|
||||||
|
/* QUADSPI MDMA CCR bit mask.*/ \
|
||||||
|
uint32_t mdmaccr; \
|
||||||
|
/* QUADSPI MDMA CTCR bit mask.*/ \
|
||||||
|
uint32_t mdmactcr
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* External declarations. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
#if (STM32_WSPI_USE_QUADSPI1 == TRUE) && !defined(__DOXYGEN__)
|
||||||
|
extern WSPIDriver WSPID1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
void wspi_lld_init(void);
|
||||||
|
void wspi_lld_start(WSPIDriver *wspip);
|
||||||
|
void wspi_lld_stop(WSPIDriver *wspip);
|
||||||
|
void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp);
|
||||||
|
void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp,
|
||||||
|
size_t n, const uint8_t *txbuf);
|
||||||
|
void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp,
|
||||||
|
size_t n, uint8_t *rxbuf);
|
||||||
|
#if WSPI_SUPPORTS_MEMMAP == TRUE
|
||||||
|
void wspi_lld_map_flash(WSPIDriver *wspip,
|
||||||
|
const wspi_command_t *cmdp,
|
||||||
|
uint8_t **addrp);
|
||||||
|
void wspi_lld_unmap_flash(WSPIDriver *wspip);
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* HAL_USE_WSPI */
|
||||||
|
|
||||||
|
#endif /* HAL_WSPI_LLD_H */
|
||||||
|
|
||||||
|
/** @} */
|
Loading…
Reference in New Issue