arch/arm/src/stm32/stm32_sdio.c: SDIO Fix system hang on card eject.
This commit is contained in:
parent
77bf9b09a1
commit
5d095e00b3
@ -1,7 +1,8 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/stm32/stm32_sdio.c
|
||||
*
|
||||
* Copyright (C) 2009, 2011-2014, 2016-2018 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2009, 2011-2014, 2016-2019 Gregory Nutt. All rights
|
||||
* reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -72,6 +73,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/* Configuration ************************************************************/
|
||||
|
||||
/* Required system configuration options:
|
||||
*
|
||||
* CONFIG_ARCH_DMA - Enable architecture-specific DMA subsystem
|
||||
@ -315,6 +317,7 @@ struct stm32_dev_s
|
||||
struct sdio_dev_s dev; /* Standard, base SDIO interface */
|
||||
|
||||
/* STM32-specific extensions */
|
||||
|
||||
/* Event support */
|
||||
|
||||
sem_t waitsem; /* Implements event waiting */
|
||||
@ -424,13 +427,16 @@ static void stm32_dmacallback(DMA_HANDLE handle, uint8_t status, void *arg);
|
||||
/* Data Transfer Helpers ****************************************************/
|
||||
|
||||
static uint8_t stm32_log2(uint16_t value);
|
||||
static void stm32_dataconfig(uint32_t timeout, uint32_t dlen, uint32_t dctrl);
|
||||
static void stm32_dataconfig(uint32_t timeout, uint32_t dlen,
|
||||
uint32_t dctrl);
|
||||
static void stm32_datadisable(void);
|
||||
static void stm32_sendfifo(struct stm32_dev_s *priv);
|
||||
static void stm32_recvfifo(struct stm32_dev_s *priv);
|
||||
static void stm32_eventtimeout(int argc, uint32_t arg);
|
||||
static void stm32_endwait(struct stm32_dev_s *priv, sdio_eventset_t wkupevent);
|
||||
static void stm32_endtransfer(struct stm32_dev_s *priv, sdio_eventset_t wkupevent);
|
||||
static void stm32_endwait(struct stm32_dev_s *priv,
|
||||
sdio_eventset_t wkupevent);
|
||||
static void stm32_endtransfer(struct stm32_dev_s *priv,
|
||||
sdio_eventset_t wkupevent);
|
||||
|
||||
/* Interrupt Handling *******************************************************/
|
||||
|
||||
@ -633,14 +639,16 @@ static inline void stm32_setclkcr(uint32_t clkcr)
|
||||
|
||||
/* Clear CLKDIV, PWRSAV, BYPASS, WIDBUS, NEGEDGE, HWFC_EN bits */
|
||||
|
||||
regval &= ~(SDIO_CLKCR_CLKDIV_MASK | SDIO_CLKCR_PWRSAV | SDIO_CLKCR_BYPASS |
|
||||
SDIO_CLKCR_WIDBUS_MASK | SDIO_CLKCR_NEGEDGE | SDIO_CLKCR_HWFC_EN |
|
||||
regval &= ~(SDIO_CLKCR_CLKDIV_MASK | SDIO_CLKCR_PWRSAV |
|
||||
SDIO_CLKCR_BYPASS | SDIO_CLKCR_WIDBUS_MASK |
|
||||
SDIO_CLKCR_NEGEDGE | SDIO_CLKCR_HWFC_EN |
|
||||
SDIO_CLKCR_CLKEN);
|
||||
|
||||
/* Replace with user provided settings */
|
||||
|
||||
clkcr &= (SDIO_CLKCR_CLKDIV_MASK | SDIO_CLKCR_PWRSAV | SDIO_CLKCR_BYPASS |
|
||||
SDIO_CLKCR_WIDBUS_MASK | SDIO_CLKCR_NEGEDGE | SDIO_CLKCR_HWFC_EN |
|
||||
clkcr &= (SDIO_CLKCR_CLKDIV_MASK | SDIO_CLKCR_PWRSAV |
|
||||
SDIO_CLKCR_BYPASS | SDIO_CLKCR_WIDBUS_MASK |
|
||||
SDIO_CLKCR_NEGEDGE | SDIO_CLKCR_HWFC_EN |
|
||||
SDIO_CLKCR_CLKEN);
|
||||
|
||||
regval |= clkcr;
|
||||
@ -686,7 +694,7 @@ static void stm32_configwaitints(struct stm32_dev_s *priv, uint32_t waitmask,
|
||||
{
|
||||
/* Do not use this in STM32_SDIO_MASK register */
|
||||
|
||||
waitmask &= !SDIOWAIT_WRCOMPLETE;
|
||||
waitmask &= ~SDIOWAIT_WRCOMPLETE;
|
||||
|
||||
pinset = GPIO_SDIO_D0 & (GPIO_PORT_MASK | GPIO_PIN_MASK);
|
||||
pinset |= (GPIO_INPUT | GPIO_FLOAT | GPIO_EXTI);
|
||||
@ -815,7 +823,8 @@ static inline uint32_t stm32_getpwrctrl(void)
|
||||
#ifdef CONFIG_SDIO_XFRDEBUG
|
||||
static void stm32_sampleinit(void)
|
||||
{
|
||||
memset(g_sampleregs, 0xff, DEBUG_NSAMPLES * sizeof(struct stm32_sampleregs_s));
|
||||
memset(g_sampleregs, 0xff,
|
||||
DEBUG_NSAMPLES * sizeof(struct stm32_sampleregs_s));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -924,22 +933,27 @@ static void stm32_dumpsample(struct stm32_dev_s *priv,
|
||||
#ifdef CONFIG_SDIO_XFRDEBUG
|
||||
static void stm32_dumpsamples(struct stm32_dev_s *priv)
|
||||
{
|
||||
stm32_dumpsample(priv, &g_sampleregs[SAMPLENDX_BEFORE_SETUP], "Before setup");
|
||||
stm32_dumpsample(priv, &g_sampleregs[SAMPLENDX_BEFORE_SETUP],
|
||||
"Before setup");
|
||||
|
||||
#if defined(CONFIG_DEBUG_DMA_INFO) && defined(CONFIG_STM32_SDIO_DMA)
|
||||
if (priv->dmamode)
|
||||
{
|
||||
stm32_dumpsample(priv, &g_sampleregs[SAMPLENDX_BEFORE_ENABLE], "Before DMA enable");
|
||||
stm32_dumpsample(priv, &g_sampleregs[SAMPLENDX_BEFORE_ENABLE],
|
||||
"Before DMA enable");
|
||||
}
|
||||
#endif
|
||||
|
||||
stm32_dumpsample(priv, &g_sampleregs[SAMPLENDX_AFTER_SETUP], "After setup");
|
||||
stm32_dumpsample(priv, &g_sampleregs[SAMPLENDX_END_TRANSFER], "End of transfer");
|
||||
stm32_dumpsample(priv, &g_sampleregs[SAMPLENDX_AFTER_SETUP],
|
||||
"After setup");
|
||||
stm32_dumpsample(priv, &g_sampleregs[SAMPLENDX_END_TRANSFER],
|
||||
"End of transfer");
|
||||
|
||||
#if defined(CONFIG_DEBUG_DMA_INFO) && defined(CONFIG_STM32_SDIO_DMA)
|
||||
if (priv->dmamode)
|
||||
{
|
||||
stm32_dumpsample(priv, &g_sampleregs[SAMPLENDX_DMA_CALLBACK], "DMA Callback");
|
||||
stm32_dumpsample(priv, &g_sampleregs[SAMPLENDX_DMA_CALLBACK],
|
||||
"DMA Callback");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -972,7 +986,8 @@ static void stm32_dmacallback(DMA_HANDLE handle, uint8_t status, void *arg)
|
||||
|
||||
if ((status & DMA_STATUS_ERROR) != 0)
|
||||
{
|
||||
mcerr("ERROR: DMA error %02x, remaining: %d\n", status, priv->remaining);
|
||||
mcerr("ERROR: DMA error %02x, remaining: %d\n",
|
||||
status, priv->remaining);
|
||||
result = SDIOWAIT_ERROR;
|
||||
}
|
||||
else
|
||||
@ -1051,8 +1066,10 @@ static void stm32_dataconfig(uint32_t timeout, uint32_t dlen, uint32_t dctrl)
|
||||
*/
|
||||
|
||||
regval = getreg32(STM32_SDIO_DCTRL);
|
||||
regval &= ~(SDIO_DCTRL_DTDIR | SDIO_DCTRL_DTMODE | SDIO_DCTRL_DBLOCKSIZE_MASK);
|
||||
dctrl &= (SDIO_DCTRL_DTDIR | SDIO_DCTRL_DTMODE | SDIO_DCTRL_DBLOCKSIZE_MASK);
|
||||
regval &= ~(SDIO_DCTRL_DTDIR | SDIO_DCTRL_DTMODE |
|
||||
SDIO_DCTRL_DBLOCKSIZE_MASK);
|
||||
dctrl &= (SDIO_DCTRL_DTDIR | SDIO_DCTRL_DTMODE |
|
||||
SDIO_DCTRL_DBLOCKSIZE_MASK);
|
||||
regval |= (dctrl | SDIO_DCTRL_DTEN | SDIO_DCTRL_SDIOEN);
|
||||
putreg32(regval, STM32_SDIO_DCTRL);
|
||||
}
|
||||
@ -1228,7 +1245,8 @@ static void stm32_eventtimeout(int argc, uint32_t arg)
|
||||
|
||||
/* There is always race conditions with timer expirations. */
|
||||
|
||||
DEBUGASSERT((priv->waitevents & SDIOWAIT_TIMEOUT) != 0 || priv->wkupevent != 0);
|
||||
DEBUGASSERT((priv->waitevents & SDIOWAIT_TIMEOUT) != 0 ||
|
||||
priv->wkupevent != 0);
|
||||
|
||||
/* Is a data transfer complete event expected? */
|
||||
|
||||
@ -1294,7 +1312,8 @@ static void stm32_endwait(struct stm32_dev_s *priv, sdio_eventset_t wkupevent)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void stm32_endtransfer(struct stm32_dev_s *priv, sdio_eventset_t wkupevent)
|
||||
static void stm32_endtransfer(struct stm32_dev_s *priv,
|
||||
sdio_eventset_t wkupevent)
|
||||
{
|
||||
/* Disable all transfer related interrupts */
|
||||
|
||||
@ -1412,9 +1431,9 @@ static int stm32_interrupt(int irq, void *context, FAR void *arg)
|
||||
stm32_recvfifo(priv);
|
||||
}
|
||||
|
||||
/* Otherwise, Is the transmit FIFO half empty or less? If so we must
|
||||
* be processing a send transaction. NOTE: We can't be processing
|
||||
* both!
|
||||
/* Otherwise, Is the transmit FIFO half empty or less? If so
|
||||
* we must be processing a send transaction. NOTE: We can't
|
||||
* be processing both!
|
||||
*/
|
||||
|
||||
else if ((pending & SDIO_STA_TXFIFOHE) != 0)
|
||||
@ -1477,8 +1496,10 @@ static int stm32_interrupt(int irq, void *context, FAR void *arg)
|
||||
{
|
||||
/* Terminate the transfer with an error */
|
||||
|
||||
mcerr("ERROR: Data block CRC failure, remaining: %d\n", priv->remaining);
|
||||
stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE | SDIOWAIT_ERROR);
|
||||
mcerr("ERROR: Data block CRC failure, remaining: %d\n",
|
||||
priv->remaining);
|
||||
stm32_endtransfer(priv,
|
||||
SDIOWAIT_TRANSFERDONE | SDIOWAIT_ERROR);
|
||||
}
|
||||
|
||||
/* Handle data timeout error */
|
||||
@ -1487,8 +1508,10 @@ static int stm32_interrupt(int irq, void *context, FAR void *arg)
|
||||
{
|
||||
/* Terminate the transfer with an error */
|
||||
|
||||
mcerr("ERROR: Data timeout, remaining: %d\n", priv->remaining);
|
||||
stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE | SDIOWAIT_TIMEOUT);
|
||||
mcerr("ERROR: Data timeout, remaining: %d\n",
|
||||
priv->remaining);
|
||||
stm32_endtransfer(priv,
|
||||
SDIOWAIT_TRANSFERDONE | SDIOWAIT_TIMEOUT);
|
||||
}
|
||||
|
||||
/* Handle RX FIFO overrun error */
|
||||
@ -1497,8 +1520,10 @@ static int stm32_interrupt(int irq, void *context, FAR void *arg)
|
||||
{
|
||||
/* Terminate the transfer with an error */
|
||||
|
||||
mcerr("ERROR: RX FIFO overrun, remaining: %d\n", priv->remaining);
|
||||
stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE | SDIOWAIT_ERROR);
|
||||
mcerr("ERROR: RX FIFO overrun, remaining: %d\n",
|
||||
priv->remaining);
|
||||
stm32_endtransfer(priv,
|
||||
SDIOWAIT_TRANSFERDONE | SDIOWAIT_ERROR);
|
||||
}
|
||||
|
||||
/* Handle TX FIFO underrun error */
|
||||
@ -1507,8 +1532,10 @@ static int stm32_interrupt(int irq, void *context, FAR void *arg)
|
||||
{
|
||||
/* Terminate the transfer with an error */
|
||||
|
||||
mcerr("ERROR: TX FIFO underrun, remaining: %d\n", priv->remaining);
|
||||
stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE | SDIOWAIT_ERROR);
|
||||
mcerr("ERROR: TX FIFO underrun, remaining: %d\n",
|
||||
priv->remaining);
|
||||
stm32_endtransfer(priv,
|
||||
SDIOWAIT_TRANSFERDONE | SDIOWAIT_ERROR);
|
||||
}
|
||||
|
||||
/* Handle start bit error */
|
||||
@ -1517,8 +1544,10 @@ static int stm32_interrupt(int irq, void *context, FAR void *arg)
|
||||
{
|
||||
/* Terminate the transfer with an error */
|
||||
|
||||
mcerr("ERROR: Start bit, remaining: %d\n", priv->remaining);
|
||||
stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE | SDIOWAIT_ERROR);
|
||||
mcerr("ERROR: Start bit, remaining: %d\n",
|
||||
priv->remaining);
|
||||
stm32_endtransfer(priv,
|
||||
SDIOWAIT_TRANSFERDONE | SDIOWAIT_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1537,7 +1566,8 @@ static int stm32_interrupt(int irq, void *context, FAR void *arg)
|
||||
{
|
||||
/* Yes.. wake the thread up */
|
||||
|
||||
putreg32(SDIO_RESPDONE_ICR | SDIO_CMDDONE_ICR, STM32_SDIO_ICR);
|
||||
putreg32(SDIO_RESPDONE_ICR | SDIO_CMDDONE_ICR,
|
||||
STM32_SDIO_ICR);
|
||||
stm32_endwait(priv, SDIOWAIT_RESPONSEDONE);
|
||||
}
|
||||
}
|
||||
@ -1832,7 +1862,6 @@ static int stm32_attach(FAR struct sdio_dev_s *dev)
|
||||
ret = irq_attach(STM32_IRQ_SDIO, stm32_interrupt, NULL);
|
||||
if (ret == OK)
|
||||
{
|
||||
|
||||
/* Disable all interrupts at the SDIO controller and clear static
|
||||
* interrupt flags
|
||||
*/
|
||||
@ -1866,7 +1895,8 @@ static int stm32_attach(FAR struct sdio_dev_s *dev)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg)
|
||||
static int stm32_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
uint32_t arg)
|
||||
{
|
||||
uint32_t regval;
|
||||
uint32_t cmdidx;
|
||||
@ -2003,7 +2033,8 @@ static int stm32_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
||||
dblocksize = stm32_log2(nbytes) << SDIO_DCTRL_DBLOCKSIZE_SHIFT;
|
||||
}
|
||||
|
||||
stm32_dataconfig(SDIO_DTIMER_DATATIMEOUT, nbytes, dblocksize | SDIO_DCTRL_DTDIR);
|
||||
stm32_dataconfig(SDIO_DTIMER_DATATIMEOUT, nbytes,
|
||||
dblocksize | SDIO_DCTRL_DTDIR);
|
||||
|
||||
/* And enable interrupts */
|
||||
|
||||
@ -2016,9 +2047,9 @@ static int stm32_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
||||
* Name: stm32_sendsetup
|
||||
*
|
||||
* Description:
|
||||
* Setup hardware in preparation for data transfer from the card. This method
|
||||
* will do whatever controller setup is necessary. This would be called
|
||||
* for SD memory just AFTER sending CMD24 (WRITE_BLOCK), CMD25
|
||||
* Setup hardware in preparation for data transfer from the card. This
|
||||
* method will do whatever controller setup is necessary. This would be
|
||||
* called for SD memory just AFTER sending CMD24 (WRITE_BLOCK), CMD25
|
||||
* (WRITE_MULTIPLE_BLOCK), ... and before SDIO_SENDDATA is called.
|
||||
*
|
||||
* Input Parameters:
|
||||
@ -2031,8 +2062,8 @@ static int stm32_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer,
|
||||
size_t nbytes)
|
||||
static int stm32_sendsetup(FAR struct sdio_dev_s *dev,
|
||||
FAR const uint8_t *buffer, size_t nbytes)
|
||||
{
|
||||
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
|
||||
uint32_t dblocksize;
|
||||
@ -2218,7 +2249,8 @@ static int stm32_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32_recvshortcrc(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *rshort)
|
||||
static int stm32_recvshortcrc(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
uint32_t *rshort)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_MEMCARD_INFO
|
||||
uint32_t respcmd;
|
||||
@ -2248,7 +2280,6 @@ static int stm32_recvshortcrc(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t
|
||||
* 0 1 End bit
|
||||
*/
|
||||
|
||||
|
||||
#ifdef CONFIG_DEBUG_MEMCARD_INFO
|
||||
if (!rshort)
|
||||
{
|
||||
@ -2304,7 +2335,8 @@ static int stm32_recvshortcrc(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stm32_recvlong(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t rlong[4])
|
||||
static int stm32_recvlong(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
uint32_t rlong[4])
|
||||
{
|
||||
uint32_t regval;
|
||||
int ret = OK;
|
||||
@ -2358,7 +2390,8 @@ static int stm32_recvlong(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t rlo
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stm32_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *rshort)
|
||||
static int stm32_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
uint32_t *rshort)
|
||||
{
|
||||
uint32_t regval;
|
||||
int ret = OK;
|
||||
@ -2513,7 +2546,21 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev,
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
#if defined(CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE)
|
||||
/* A card ejected while in SDIOWAIT_WRCOMPLETE can lead to a
|
||||
* condition where there is no waitevents set and no wkupevent
|
||||
*/
|
||||
|
||||
if (priv->waitevents == 0 && priv->wkupevent == 0)
|
||||
{
|
||||
wkupevent = SDIOWAIT_ERROR;
|
||||
goto erroutdisable;
|
||||
}
|
||||
|
||||
#else
|
||||
DEBUGASSERT(priv->waitevents != 0 || priv->wkupevent != 0);
|
||||
#endif
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
@ -2567,16 +2614,17 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev,
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
/* Wait for an event in event set to occur. If this the event has already
|
||||
* occurred, then the semaphore will already have been incremented and
|
||||
* there will be no wait.
|
||||
/* Wait for an event in event set to occur. If this the event has
|
||||
* already occurred, then the semaphore will already have been
|
||||
* incremented and there will be no wait.
|
||||
*/
|
||||
|
||||
stm32_takesem(priv);
|
||||
wkupevent = priv->wkupevent;
|
||||
|
||||
/* Check if the event has occurred. When the event has occurred, then
|
||||
* evenset will be set to 0 and wkupevent will be set to a nonzero value.
|
||||
* evenset will be set to 0 and wkupevent will be set to a nonzero
|
||||
* value.
|
||||
*/
|
||||
|
||||
if (wkupevent != 0)
|
||||
@ -2589,6 +2637,10 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev,
|
||||
|
||||
/* Disable event-related interrupts */
|
||||
|
||||
#if defined(CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE)
|
||||
erroutdisable:
|
||||
#endif
|
||||
|
||||
stm32_configwaitints(priv, 0, 0, 0);
|
||||
#ifdef CONFIG_STM32_SDIO_DMA
|
||||
priv->xfrflags = 0;
|
||||
@ -2707,7 +2759,8 @@ static int stm32_dmapreflight(FAR struct sdio_dev_s *dev,
|
||||
|
||||
/* DMA must be possible to the buffer */
|
||||
|
||||
if (!stm32_dmacapable((uintptr_t)buffer, (buflen + 3) >> 2, SDIO_RXDMA32_CONFIG))
|
||||
if (!stm32_dmacapable((uintptr_t)buffer, (buflen + 3) >> 2,
|
||||
SDIO_RXDMA32_CONFIG))
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
@ -2775,7 +2828,8 @@ static int stm32_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
||||
dblocksize = stm32_log2(buflen) << SDIO_DCTRL_DBLOCKSIZE_SHIFT;
|
||||
}
|
||||
|
||||
stm32_dataconfig(SDIO_DTIMER_DATATIMEOUT, buflen, dblocksize | SDIO_DCTRL_DTDIR);
|
||||
stm32_dataconfig(SDIO_DTIMER_DATATIMEOUT, buflen,
|
||||
dblocksize | SDIO_DCTRL_DTDIR);
|
||||
|
||||
/* Configure the RX DMA */
|
||||
|
||||
@ -2945,8 +2999,10 @@ static void stm32_callback(void *arg)
|
||||
{
|
||||
/* Yes.. queue it */
|
||||
|
||||
mcinfo("Queuing callback to %p(%p)\n", priv->callback, priv->cbarg);
|
||||
(void)work_queue(HPWORK, &priv->cbwork, (worker_t)priv->callback, priv->cbarg, 0);
|
||||
mcinfo("Queuing callback to %p(%p)\n",
|
||||
priv->callback, priv->cbarg);
|
||||
(void)work_queue(HPWORK, &priv->cbwork, (worker_t)priv->callback,
|
||||
priv->cbarg, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2993,7 +3049,8 @@ static void stm32_default(void)
|
||||
* slotno - Not used.
|
||||
*
|
||||
* Returned Value:
|
||||
* A reference to an SDIO interface structure. NULL is returned on failures.
|
||||
* A reference to an SDIO interface structure. NULL is returned on
|
||||
* failures.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -3004,6 +3061,7 @@ FAR struct sdio_dev_s *sdio_initialize(int slotno)
|
||||
struct stm32_dev_s *priv = &g_sdiodev;
|
||||
|
||||
/* Initialize the SDIO slot structure */
|
||||
|
||||
/* Initialize semaphores */
|
||||
|
||||
nxsem_init(&priv->waitsem, 0, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user