Merge branch 'stm32l4_qspi_004'
This commit is contained in:
commit
37a33fd876
@ -140,6 +140,12 @@
|
|||||||
GPIO_QSPI_IO1 GPIO_QSPI_IO2 GPIO_QSPI_IO3 GPIO_QSPI_SCK in your board.h
|
GPIO_QSPI_IO1 GPIO_QSPI_IO2 GPIO_QSPI_IO3 GPIO_QSPI_SCK in your board.h
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_STM32L4_QSPI_DMA
|
||||||
|
#if !defined(DMACHAN_QUADSPI)
|
||||||
|
# error QSPI DMA channel must be specified via DMACHAN_QUADSPI in your board.h
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef BOARD_AHB_FREQUENCY
|
#ifndef BOARD_AHB_FREQUENCY
|
||||||
# error your board.h needs to define the value of BOARD_AHB_FREQUENCY
|
# error your board.h needs to define the value of BOARD_AHB_FREQUENCY
|
||||||
#endif
|
#endif
|
||||||
@ -176,6 +182,7 @@ struct stm32l4_qspidev_s
|
|||||||
uint8_t intf; /* QSPI controller number (0) */
|
uint8_t intf; /* QSPI controller number (0) */
|
||||||
bool initialized; /* TRUE: Controller has been initialized */
|
bool initialized; /* TRUE: Controller has been initialized */
|
||||||
sem_t exclsem; /* Assures mutually exclusive access to QSPI */
|
sem_t exclsem; /* Assures mutually exclusive access to QSPI */
|
||||||
|
bool memmap; /* TRUE: Controller is in memory mapped mode */
|
||||||
|
|
||||||
#ifdef QSPI_USE_INTERRUPTS
|
#ifdef QSPI_USE_INTERRUPTS
|
||||||
xcpt_t handler; /* Interrupt handler */
|
xcpt_t handler; /* Interrupt handler */
|
||||||
@ -1101,7 +1108,11 @@ static int qspi0_interrupt(int irq, void *context)
|
|||||||
regval &= ~(QSPI_CR_TEIE | QSPI_CR_TCIE | QSPI_CR_FTIE | QSPI_CR_SMIE | QSPI_CR_TOIE);
|
regval &= ~(QSPI_CR_TEIE | QSPI_CR_TCIE | QSPI_CR_FTIE | QSPI_CR_SMIE | QSPI_CR_TOIE);
|
||||||
qspi_putreg(&g_qspi0dev, regval, STM32L4_QUADSPI_CR_OFFSET);
|
qspi_putreg(&g_qspi0dev, regval, STM32L4_QUADSPI_CR_OFFSET);
|
||||||
|
|
||||||
/* Set error status */
|
/* Set error status; 'transfer error' means that, in 'indirect mode',
|
||||||
|
* an invalid address is attempted to be accessed. 'Invalid' is
|
||||||
|
* presumably relative to the FSIZE field in CCR; the manual is not
|
||||||
|
* explicit, but what else could it be?
|
||||||
|
*/
|
||||||
|
|
||||||
g_qspi0dev.xctn->disposition = - EIO;
|
g_qspi0dev.xctn->disposition = - EIO;
|
||||||
|
|
||||||
@ -1110,7 +1121,7 @@ static int qspi0_interrupt(int irq, void *context)
|
|||||||
sem_post(&g_qspi0dev.op_sem);
|
sem_post(&g_qspi0dev.op_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is it 'Timeout'? (: */
|
/* Is it 'Timeout'? */
|
||||||
|
|
||||||
if ((status & QSPI_SR_TOF) && (cr & QSPI_CR_TOIE))
|
if ((status & QSPI_SR_TOF) && (cr & QSPI_CR_TOIE))
|
||||||
{
|
{
|
||||||
@ -1118,13 +1129,17 @@ static int qspi0_interrupt(int irq, void *context)
|
|||||||
|
|
||||||
qspi_putreg(&g_qspi0dev, QSPI_FCR_CTOF, STM32L4_QUADSPI_FCR);
|
qspi_putreg(&g_qspi0dev, QSPI_FCR_CTOF, STM32L4_QUADSPI_FCR);
|
||||||
|
|
||||||
/* Set error status */
|
/* XXX this interrupt simply means that, in 'memory mapped mode',
|
||||||
|
* the QSPI memory has not been accessed for a while, and the
|
||||||
g_qspi0dev.xctn->disposition = - ETIMEDOUT;
|
* IP block was configured to automatically de-assert CS after
|
||||||
|
* a timeout. And now we're being informed that has happened.
|
||||||
/* Signal complete */
|
*
|
||||||
|
* But who cares? If someone does, perhaps a user callback is
|
||||||
sem_post(&g_qspi0dev.op_sem);
|
* appropriate, or some signal? Either way, realize the xctn
|
||||||
|
* member is /not/ valid, so you can't set the disposition
|
||||||
|
* field. Also, note signaling completion has no meaning here
|
||||||
|
* because in memory mapped mode no one holds the semaphore.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
@ -1340,6 +1355,14 @@ static uint32_t qspi_setfrequency(struct qspi_dev_s *dev, uint32_t frequency)
|
|||||||
uint32_t prescaler;
|
uint32_t prescaler;
|
||||||
uint32_t regval;
|
uint32_t regval;
|
||||||
|
|
||||||
|
if (priv->memmap)
|
||||||
|
{
|
||||||
|
/* XXX we have no better return here, but the caller will find out
|
||||||
|
* in their subsequent calls.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
qspivdbg("frequency=%d\n", frequency);
|
qspivdbg("frequency=%d\n", frequency);
|
||||||
DEBUGASSERT(priv);
|
DEBUGASSERT(priv);
|
||||||
|
|
||||||
@ -1424,6 +1447,14 @@ static void qspi_setmode(struct qspi_dev_s *dev, enum qspi_mode_e mode)
|
|||||||
struct stm32l4_qspidev_s *priv = (struct stm32l4_qspidev_s *)dev;
|
struct stm32l4_qspidev_s *priv = (struct stm32l4_qspidev_s *)dev;
|
||||||
uint32_t regval;
|
uint32_t regval;
|
||||||
|
|
||||||
|
if (priv->memmap)
|
||||||
|
{
|
||||||
|
/* XXX we have no better return here, but the caller will find out
|
||||||
|
* in their subsequent calls.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
qspivdbg("mode=%d\n", mode);
|
qspivdbg("mode=%d\n", mode);
|
||||||
|
|
||||||
/* Has the mode changed? */
|
/* Has the mode changed? */
|
||||||
@ -1518,6 +1549,16 @@ static int qspi_command(struct qspi_dev_s *dev,
|
|||||||
struct qspi_xctnspec_s xctn;
|
struct qspi_xctnspec_s xctn;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
/* Reject commands issued while in memory mapped mode, which will
|
||||||
|
* automatically cancel the memory mapping. You must exit the
|
||||||
|
* memory mapped mode first.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (priv->memmap)
|
||||||
|
{
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set up the transaction descriptor as per command info */
|
/* Set up the transaction descriptor as per command info */
|
||||||
|
|
||||||
ret = qspi_setupxctnfromcmd(&xctn, cmdinfo);
|
ret = qspi_setupxctnfromcmd(&xctn, cmdinfo);
|
||||||
@ -1689,6 +1730,16 @@ static int qspi_memory(struct qspi_dev_s *dev,
|
|||||||
struct qspi_xctnspec_s xctn;
|
struct qspi_xctnspec_s xctn;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
/* Reject commands issued while in memory mapped mode, which will
|
||||||
|
* automatically cancel the memory mapping. You must exit the
|
||||||
|
* memory mapped mode first.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (priv->memmap)
|
||||||
|
{
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set up the transaction descriptor as per command info */
|
/* Set up the transaction descriptor as per command info */
|
||||||
|
|
||||||
ret = qspi_setupxctnfrommem(&xctn, meminfo);
|
ret = qspi_setupxctnfrommem(&xctn, meminfo);
|
||||||
@ -2080,6 +2131,7 @@ struct qspi_dev_s *stm32l4_qspi_initialize(int intf)
|
|||||||
/* Enable interrupts at the NVIC */
|
/* Enable interrupts at the NVIC */
|
||||||
|
|
||||||
priv->initialized = true;
|
priv->initialized = true;
|
||||||
|
priv->memmap = false;
|
||||||
#ifdef QSPI_USE_INTERRUPTS
|
#ifdef QSPI_USE_INTERRUPTS
|
||||||
up_enable_irq(priv->irq);
|
up_enable_irq(priv->irq);
|
||||||
#endif
|
#endif
|
||||||
@ -2100,4 +2152,122 @@ errout_with_dmadog:
|
|||||||
sem_destroy(&priv->exclsem);
|
sem_destroy(&priv->exclsem);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: stm32l4_qspi_enter_memorymapped
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Put the QSPI device into memory mapped mode
|
||||||
|
*
|
||||||
|
* Input Parameter:
|
||||||
|
* dev - QSPI device
|
||||||
|
* meminfo - parameters like for a memory transfer used for reading
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void stm32l4_qspi_enter_memorymapped(struct qspi_dev_s* dev,
|
||||||
|
const struct qspi_meminfo_s *meminfo,
|
||||||
|
uint32_t lpto)
|
||||||
|
{
|
||||||
|
struct stm32l4_qspidev_s *priv = (struct stm32l4_qspidev_s *)dev;
|
||||||
|
uint32_t regval;
|
||||||
|
struct qspi_xctnspec_s xctn;
|
||||||
|
|
||||||
|
/* lock during this mode change */
|
||||||
|
|
||||||
|
qspi_lock(dev, true);
|
||||||
|
|
||||||
|
if (priv->memmap)
|
||||||
|
{
|
||||||
|
qspi_lock(dev, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Abort anything in-progress */
|
||||||
|
|
||||||
|
qspi_abort(priv);
|
||||||
|
|
||||||
|
/* Wait till BUSY flag reset */
|
||||||
|
|
||||||
|
qspi_waitstatusflags(priv, QSPI_SR_BUSY, 0);
|
||||||
|
|
||||||
|
/* if we want the 'low-power timeout counter' */
|
||||||
|
|
||||||
|
if (lpto > 0)
|
||||||
|
{
|
||||||
|
/* Set the Low Power Timeout value (automatically de-assert
|
||||||
|
* CS if memory is not accessed for a while)
|
||||||
|
*/
|
||||||
|
|
||||||
|
qspi_putreg(priv, lpto, STM32L4_QUADSPI_LPTR_OFFSET);
|
||||||
|
|
||||||
|
/* Clear Timeout interrupt */
|
||||||
|
|
||||||
|
qspi_putreg(&g_qspi0dev, QSPI_FCR_CTOF, STM32L4_QUADSPI_FCR);
|
||||||
|
|
||||||
|
#ifdef QSPI_USE_INTERRUPTS
|
||||||
|
/* Enable Timeout interrupt */
|
||||||
|
|
||||||
|
regval = qspi_getreg(priv, STM32L4_QUADSPI_CR_OFFSET);
|
||||||
|
regval |= (QSPI_CR_TCEN | QSPI_CR_TOIE);
|
||||||
|
qspi_putreg(priv, regval, STM32L4_QUADSPI_CR_OFFSET);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
regval = qspi_getreg(priv, STM32L4_QUADSPI_CR_OFFSET);
|
||||||
|
regval &= ~QSPI_CR_TCEN;
|
||||||
|
qspi_putreg(priv, regval, STM32L4_QUADSPI_CR_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create a transaction object */
|
||||||
|
|
||||||
|
qspi_setupxctnfrommem(&xctn, meminfo);
|
||||||
|
priv->xctn = NULL;
|
||||||
|
|
||||||
|
/* set it into the ccr */
|
||||||
|
|
||||||
|
qspi_ccrconfig(priv, &xctn, CCR_FMODE_MEMMAP);
|
||||||
|
priv->memmap = true;
|
||||||
|
|
||||||
|
/* we should be in memory mapped mode now */
|
||||||
|
|
||||||
|
qspi_dumpregs(priv, "After memory mapped:");
|
||||||
|
|
||||||
|
/* finished this mode change */
|
||||||
|
|
||||||
|
qspi_lock(dev, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: stm32l4_qspi_exit_memorymapped
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Take the QSPI device out of memory mapped mode
|
||||||
|
*
|
||||||
|
* Input Parameter:
|
||||||
|
* dev - QSPI device
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void stm32l4_qspi_exit_memorymapped(struct qspi_dev_s* dev)
|
||||||
|
{
|
||||||
|
struct stm32l4_qspidev_s *priv = (struct stm32l4_qspidev_s *)dev;
|
||||||
|
|
||||||
|
qspi_lock(dev, true);
|
||||||
|
|
||||||
|
/* A simple abort is sufficient */
|
||||||
|
|
||||||
|
qspi_abort(priv);
|
||||||
|
priv->memmap = false;
|
||||||
|
|
||||||
|
qspi_lock(dev, false);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_STM32L4_QSPI */
|
#endif /* CONFIG_STM32L4_QSPI */
|
||||||
|
@ -97,6 +97,42 @@ extern "C"
|
|||||||
struct qspi_dev_s;
|
struct qspi_dev_s;
|
||||||
FAR struct qspi_dev_s *stm32l4_qspi_initialize(int intf);
|
FAR struct qspi_dev_s *stm32l4_qspi_initialize(int intf);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: stm32l4_qspi_enter_memorymapped
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Put the QSPI device into memory mapped mode
|
||||||
|
*
|
||||||
|
* Input Parameter:
|
||||||
|
* dev - QSPI device
|
||||||
|
* meminfo - parameters like for a memory transfer used for reading
|
||||||
|
* lpto - number of cycles to wait to automatically de-assert CS
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void stm32l4_qspi_enter_memorymapped(struct qspi_dev_s* dev,
|
||||||
|
const struct qspi_meminfo_s *meminfo,
|
||||||
|
uint32_t lpto);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: stm32l4_qspi_exit_memorymapped
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Take the QSPI device out of memory mapped mode
|
||||||
|
*
|
||||||
|
* Input Parameter:
|
||||||
|
* dev - QSPI device
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void stm32l4_qspi_exit_memorymapped(struct qspi_dev_s* dev);
|
||||||
|
|
||||||
#undef EXTERN
|
#undef EXTERN
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user