forked from nuttx/nuttx-update
SAMA5: Fix HSMCI race condition. Now memory card interface is functional with DMA
This commit is contained in:
parent
d60e9e14f6
commit
da4cebf572
11 changed files with 362 additions and 111 deletions
|
@ -5332,4 +5332,10 @@
|
|||
verified (with SPI) (2013-8-9).
|
||||
* arch/arm/src/sama5/sam_memories.c and .h: Central logic for
|
||||
conversions between physical and virtual addresses (2013-8-9).
|
||||
|
||||
* arch/arm/src/sama5/sam_hsmci.c and sam34/sam_hsmci.c: Correct a
|
||||
race condition in the SAMA5 HSCMI driver: The tranfer done
|
||||
interrupt was firing before the wait was started. Fix this and
|
||||
also backported the changes to SAM3/4 (untested). Now HSCMI is
|
||||
functional on the SAMA5 with DMA! (2013-8-10).
|
||||
* arch/arm/src/sam34/sam3u_periphclks.h: Correct a typo in a register
|
||||
name (2013-8-10).
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "chip.h"
|
||||
|
||||
#include "sam_dmac.h"
|
||||
#include "sam_periphclks.h"
|
||||
#include "chip/sam3u_pmc.h"
|
||||
#include "chip/sam3u_dmac.h"
|
||||
|
||||
|
@ -413,7 +414,7 @@ sam_txctrlabits(struct sam_dma_s *dmach)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static size_t sam_maxtxtransfer(struct sam_dmach_s *dmach)
|
||||
static size_t sam_maxtxtransfer(struct sam_dma_s *dmach)
|
||||
{
|
||||
unsigned int srcwidth;
|
||||
size_t maxtransfer;
|
||||
|
@ -558,7 +559,7 @@ static inline uint32_t sam_rxctrlabits(struct sam_dma_s *dmach)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static size_t sam_maxrxtransfer(struct sam_dmach_s *dmach)
|
||||
static size_t sam_maxrxtransfer(struct sam_dma_s *dmach)
|
||||
{
|
||||
unsigned int srcwidth;
|
||||
size_t maxtransfer;
|
||||
|
@ -1399,7 +1400,7 @@ DMA_HANDLE sam_dmachannel(uint32_t chflags)
|
|||
|
||||
void sam_dmaconfig(DMA_HANDLE handle, uint32_t chflags)
|
||||
{
|
||||
struct sam_dmach_s *dmach = (struct sam_dmach_s *)handle;
|
||||
struct sam_dma_s *dmach = (struct sam_dma_s *)handle;
|
||||
|
||||
/* Set the new DMA channel flags. */
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
/* Helper macros */
|
||||
|
||||
#define sam_enableperipheral(s) putreg32((1 << (s)), SAM_PMC_PCER)
|
||||
#define sam_disableperipheral(s) putreg32((1 << (s)), SAM_PMC_PDER)
|
||||
#define sam_disableperipheral(s) putreg32((1 << (s)), SAM_PMC_PCDR)
|
||||
|
||||
#define sam_supc_enableclk() sam_enableperipheral(SAM_PID_SUPC)
|
||||
#define sam_rstc_enableclk() sam_enableperipheral(SAM_PID_RSTC)
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
#include "sam_gpio.h"
|
||||
#include "sam_dmac.h"
|
||||
#include "sam_hsmci.h"
|
||||
#include "sam_periphclks.h"
|
||||
#include "chip/sam3u_dmac.h"
|
||||
#include "chip/sam3u_pmc.h"
|
||||
#include "chip/sam_hsmci.h"
|
||||
|
@ -268,6 +269,7 @@ struct sam_dev_s
|
|||
uint32_t cmdrmask; /* Interrupt enables for this particular cmd/response */
|
||||
volatile sdio_eventset_t wkupevent; /* The event that caused the wakeup */
|
||||
WDOG_ID waitwdog; /* Watchdog that handles event timeouts */
|
||||
bool dmabusy; /* TRUE: DMA is in progress */
|
||||
|
||||
/* Callback support */
|
||||
|
||||
|
@ -329,11 +331,14 @@ struct sam_xfrregs_s
|
|||
|
||||
static void sam_takesem(struct sam_dev_s *priv);
|
||||
#define sam_givesem(priv) (sem_post(&priv->waitsem))
|
||||
static void sam_enablewaitints(struct sam_dev_s *priv, uint32_t waitmask,
|
||||
|
||||
static void sam_configwaitints(struct sam_dev_s *priv, uint32_t waitmask,
|
||||
sdio_eventset_t waitevents);
|
||||
static void sam_disablewaitints(struct sam_dev_s *priv, sdio_eventset_t wkupevents);
|
||||
static void sam_enablexfrints(struct sam_dev_s *priv, uint32_t xfrmask);
|
||||
static inline void sam_configxfrints(struct sam_dev_s *priv, uint32_t xfrmask);
|
||||
static void sam_disablexfrints(struct sam_dev_s *priv);
|
||||
static void sam_enableints(struct sam_dev_s *priv);
|
||||
|
||||
static inline void sam_disable(void);
|
||||
static inline void sam_enable(void);
|
||||
|
||||
|
@ -522,10 +527,13 @@ static void sam_takesem(struct sam_dev_s *priv)
|
|||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_enablewaitints
|
||||
* Name: sam_configwaitints
|
||||
*
|
||||
* Description:
|
||||
* Enable HSMCI interrupts needed to suport the wait function
|
||||
* Configure HSMCI interrupts needed to support the wait function. Wait
|
||||
* interrupts are configured here, but not enabled until
|
||||
* sam_enableints() is called. Why? Because the XFRDONE interrupt
|
||||
* is always pending until start the data transfer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - A reference to the HSMCI device state structure
|
||||
|
@ -537,20 +545,17 @@ static void sam_takesem(struct sam_dev_s *priv)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void sam_enablewaitints(struct sam_dev_s *priv, uint32_t waitmask,
|
||||
static void sam_configwaitints(struct sam_dev_s *priv, uint32_t waitmask,
|
||||
sdio_eventset_t waitevents)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* Save all of the data and set the new interrupt mask in one, atomic
|
||||
* operation.
|
||||
*/
|
||||
/* Save all of the data in one, atomic operation. */
|
||||
|
||||
flags = irqsave();
|
||||
priv->waitevents = waitevents;
|
||||
priv->wkupevent = 0;
|
||||
priv->waitmask = waitmask;
|
||||
putreg32(priv->xfrmask | priv->waitmask, SAM_HSMCI_IER);
|
||||
irqrestore(flags);
|
||||
}
|
||||
|
||||
|
@ -587,10 +592,13 @@ static void sam_disablewaitints(struct sam_dev_s *priv,
|
|||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_enablexfrints
|
||||
* Name: sam_configxfrints
|
||||
*
|
||||
* Description:
|
||||
* Enable HSMCI interrupts needed to support the data transfer event
|
||||
* Configure HSMCI interrupts needed to support the data transfer. Data
|
||||
* transfer interrupts are configured here, but not enabled until
|
||||
* sam_enableints() is called. Why? Because the XFRDONE interrupt
|
||||
* is always pending until start the data transfer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - A reference to the HSMCI device state structure
|
||||
|
@ -601,12 +609,9 @@ static void sam_disablewaitints(struct sam_dev_s *priv,
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void sam_enablexfrints(struct sam_dev_s *priv, uint32_t xfrmask)
|
||||
static inline void sam_configxfrints(struct sam_dev_s *priv, uint32_t xfrmask)
|
||||
{
|
||||
irqstate_t flags = irqsave();
|
||||
priv->xfrmask = xfrmask;
|
||||
putreg32(priv->xfrmask | priv->waitmask, SAM_HSMCI_IER);
|
||||
irqrestore(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -632,6 +637,28 @@ static void sam_disablexfrints(struct sam_dev_s *priv)
|
|||
irqrestore(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_enableints
|
||||
*
|
||||
* Description:
|
||||
* Enable the previously configured HSMCI interrupts needed to suport the
|
||||
* wait and transfer functions.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - A reference to the HSMCI device state structure
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline void sam_enableints(struct sam_dev_s *priv)
|
||||
{
|
||||
/* Enable all interrupts associated with the waited-for event */
|
||||
|
||||
putreg32(priv->xfrmask | priv->waitmask, SAM_HSMCI_IER);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_disable
|
||||
*
|
||||
|
@ -903,10 +930,16 @@ static void sam_cmddump(void)
|
|||
|
||||
static void sam_dmacallback(DMA_HANDLE handle, void *arg, int result)
|
||||
{
|
||||
struct sam_dev_s *priv = (struct sam_dev_s *)arg;
|
||||
|
||||
/* We don't really do anything at the completion of DMA. The termination
|
||||
* of the transfer is driven by the HSMCI interrupts.
|
||||
*
|
||||
* Mark the DMA not busy.
|
||||
*/
|
||||
|
||||
priv->dmabusy = false;
|
||||
|
||||
sam_xfrsample((struct sam_dev_s*)arg, SAMPLENDX_DMA_CALLBACK);
|
||||
}
|
||||
|
||||
|
@ -1025,6 +1058,7 @@ static void sam_endtransfer(struct sam_dev_s *priv,
|
|||
*/
|
||||
|
||||
sam_dmastop(priv->dma);
|
||||
priv->dmabusy = false;
|
||||
|
||||
/* Disable the DMA handshaking */
|
||||
|
||||
|
@ -1100,6 +1134,7 @@ static int sam_interrupt(int irq, void *context)
|
|||
|
||||
sr = getreg32(SAM_HSMCI_SR);
|
||||
enabled = sr & getreg32(SAM_HSMCI_IMR);
|
||||
|
||||
if (enabled == 0)
|
||||
{
|
||||
break;
|
||||
|
@ -1270,6 +1305,7 @@ static void sam_reset(FAR struct sdio_dev_s *dev)
|
|||
priv->waitevents = 0; /* Set of events to be waited for */
|
||||
priv->waitmask = 0; /* Interrupt enables for event waiting */
|
||||
priv->wkupevent = 0; /* The event that caused the wakeup */
|
||||
priv->dmabusy = false; /* No DMA in progress */
|
||||
wd_cancel(priv->waitwdog); /* Cancel any timeouts */
|
||||
|
||||
/* Interrupt mode data transfer support */
|
||||
|
@ -1620,8 +1656,8 @@ static void sam_blocksetup(FAR struct sdio_dev_s *dev, unsigned int blocklen,
|
|||
* Name: sam_cancel
|
||||
*
|
||||
* Description:
|
||||
* Cancel the data transfer setup of HSMCI_RECVSETUP, HSMCI_SENDSETUP,
|
||||
* HSMCI_DMARECVSETUP or HSMCI_DMASENDSETUP. This must be called to cancel
|
||||
* Cancel the data transfer setup of SDIO_RECVSETUP, SDIO_SENDSETUP,
|
||||
* SDIO_DMARECVSETUP or SDIO_DMASENDSETUP. This must be called to cancel
|
||||
* the data transfer setup if, for some reason, you cannot perform the
|
||||
* transfer.
|
||||
*
|
||||
|
@ -1660,6 +1696,7 @@ static int sam_cancel(FAR struct sdio_dev_s *dev)
|
|||
*/
|
||||
|
||||
sam_dmastop(priv->dma);
|
||||
priv->dmabusy = false;
|
||||
|
||||
/* Disable the DMA handshaking */
|
||||
|
||||
|
@ -1947,13 +1984,24 @@ static int sam_recvnotimpl(FAR struct sdio_dev_s *dev,
|
|||
*
|
||||
* Description:
|
||||
* Enable/disable of a set of SDIO wait events. This is part of the
|
||||
* the HSMCI_WAITEVENT sequence. The set of to-be-waited-for events is
|
||||
* configured before calling sam_eventwait. This is done in this way
|
||||
* to help the driver to eliminate race conditions between the command
|
||||
* the SDIO_WAITEVENT sequence. The set of to-be-waited-for events is
|
||||
* configured before calling either calling SDIO_DMARECVSETUP,
|
||||
* SDIO_DMASENDSETUP, or or SDIO_WAITEVENT. This is the recommended
|
||||
* ordering:
|
||||
*
|
||||
* SDIO_WAITENABLE: Discard any pending interrupts, enable event(s)
|
||||
* of interest
|
||||
* SDIO_DMARECVSETUP/
|
||||
* SDIO_DMASENDSETUP: Setup the logic that will trigger the event the
|
||||
* event(s) of interest
|
||||
* SDIO_WAITEVENT: Wait for the event of interest (which might
|
||||
* already have occurred)
|
||||
*
|
||||
* This sequency should eliminate race conditions between the command/trasnfer
|
||||
* setup and the subsequent events.
|
||||
*
|
||||
* The enabled events persist until either (1) HSMCI_WAITENABLE is called
|
||||
* again specifying a different set of wait events, or (2) HSMCI_EVENTWAIT
|
||||
* The enabled events persist until either (1) SDIO_WAITENABLE is called
|
||||
* again specifying a different set of wait events, or (2) SDIO_EVENTWAIT
|
||||
* returns.
|
||||
*
|
||||
* Input Parameters:
|
||||
|
@ -1988,10 +2036,20 @@ static void sam_waitenable(FAR struct sdio_dev_s *dev,
|
|||
waitmask |= priv->cmdrmask;
|
||||
}
|
||||
|
||||
/* Enable event-related interrupts */
|
||||
/* Clear (most) pending interrupts by reading the status register.
|
||||
* No interrupts should be lost (assuming that interrupts were enabled
|
||||
* before sam_waitenable() was called). Any interrupts that become
|
||||
* pending after this point must be valid event indications.
|
||||
*/
|
||||
|
||||
(void)getreg32(SAM_HSMCI_SR);
|
||||
sam_enablewaitints(priv, waitmask, eventset);
|
||||
|
||||
/* Wait interrupts are configured here, but not enabled until
|
||||
* sam_eventwait() is called. Why? Because the XFRDONE interrupt is
|
||||
* always pending until start the data transfer.
|
||||
*/
|
||||
|
||||
sam_configwaitints(priv, waitmask, eventset);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -1999,8 +2057,8 @@ static void sam_waitenable(FAR struct sdio_dev_s *dev,
|
|||
*
|
||||
* Description:
|
||||
* Wait for one of the enabled events to occur (or a timeout). Note that
|
||||
* all events enabled by HSMCI_WAITEVENTS are disabled when sam_eventwait
|
||||
* returns. HSMCI_WAITEVENTS must be called again before sam_eventwait
|
||||
* all events enabled by SDIO_WAITEVENTS are disabled when sam_eventwait
|
||||
* returns. SDIO_WAITEVENTS must be called again before sam_eventwait
|
||||
* can be used again.
|
||||
*
|
||||
* Input Parameters:
|
||||
|
@ -2022,13 +2080,22 @@ static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev,
|
|||
sdio_eventset_t wkupevent = 0;
|
||||
int ret;
|
||||
|
||||
/* There is a race condition here... the event may have completed before
|
||||
* we get here. In this case waitevents will be zero, but wkupevents will
|
||||
* be non-zero (and, hopefully, the semaphore count will also be non-zero.
|
||||
/* Since interrupts not been enabled to this point, any relevant events
|
||||
* are pending and should not yet have occurred.
|
||||
*/
|
||||
|
||||
DEBUGASSERT((priv->waitevents != 0 && priv->wkupevent == 0) ||
|
||||
(priv->waitevents == 0 && priv->wkupevent != 0));
|
||||
DEBUGASSERT(priv->waitevents != 0 && priv->wkupevent == 0);
|
||||
|
||||
/* Now enable event-related interrupts. If the events are pending, they
|
||||
* may happen immediately here before entering the loop.
|
||||
*/
|
||||
|
||||
sam_enableints(priv);
|
||||
|
||||
/* There is a race condition here... the event may have completed before
|
||||
* we get here. In this case waitevents will be zero, but wkupevents will
|
||||
* be non-zero (and, hopefully, the semaphore count will also be non-zero).
|
||||
*/
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
|
@ -2043,7 +2110,16 @@ static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev,
|
|||
return SDIOWAIT_TIMEOUT;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
/* Start the watchdog timer. I am not sure why this is, but I am
|
||||
* currently seeing some additional delays when DMA is used (On the
|
||||
* SAMA5, might not be necessary for SAM3/4).
|
||||
*/
|
||||
|
||||
#warning REVISIT: This should not be necessary
|
||||
if (priv->dmabusy)
|
||||
{
|
||||
timeout += 500;
|
||||
}
|
||||
|
||||
delay = (timeout + (MSEC_PER_TICK-1)) / MSEC_PER_TICK;
|
||||
ret = wd_start(priv->waitwdog, delay, (wdentry_t)sam_eventtimeout,
|
||||
|
@ -2099,7 +2175,7 @@ static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev,
|
|||
*
|
||||
* Events are automatically disabled once the callback is performed and no
|
||||
* further callback events will occur until they are again enabled by
|
||||
* calling this methos.
|
||||
* calling this methods.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - An instance of the SDIO device interface
|
||||
|
@ -2133,7 +2209,7 @@ static void sam_callbackenable(FAR struct sdio_dev_s *dev,
|
|||
* thread.
|
||||
*
|
||||
* When this method is called, all callbacks should be disabled until they
|
||||
* are enabled via a call to HSMCI_CALLBACKENABLE
|
||||
* are enabled via a call to SDIO_CALLBACKENABLE.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - Device-specific state data
|
||||
|
@ -2216,7 +2292,6 @@ static int sam_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
|||
|
||||
/* Configure the RX DMA */
|
||||
|
||||
sam_enablexfrints(priv, HSMCI_DMARECV_INTS);
|
||||
sam_dmarxsetup(priv->dma, SAM_HSMCI_RDR, (uint32_t)buffer, buflen);
|
||||
|
||||
/* Enable DMA handshaking */
|
||||
|
@ -2226,8 +2301,16 @@ static int sam_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
|||
|
||||
/* Start the DMA */
|
||||
|
||||
priv->dmabusy = true;
|
||||
sam_dmastart(priv->dma, sam_dmacallback, priv);
|
||||
|
||||
/* Configure transfer-related interrupts. Transfer interrupts are not
|
||||
* enabled until after the transfer is stard with an SD command (i.e.,
|
||||
* at the beginning of sam_eventwait().
|
||||
*/
|
||||
|
||||
sam_xfrsample(priv, SAMPLENDX_AFTER_SETUP);
|
||||
sam_configxfrints(priv, HSMCI_DMARECV_INTS);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
@ -2274,12 +2357,16 @@ static int sam_dmasendsetup(FAR struct sdio_dev_s *dev,
|
|||
|
||||
/* Start the DMA */
|
||||
|
||||
priv->dmabusy = true;
|
||||
sam_dmastart(priv->dma, sam_dmacallback, priv);
|
||||
|
||||
/* Configure transfer-related interrupts. Transfer interrupts are not
|
||||
* enabled until after the transfer is stard with an SD command (i.e.,
|
||||
* at the beginning of sam_eventwait().
|
||||
*/
|
||||
|
||||
sam_xfrsample(priv, SAMPLENDX_AFTER_SETUP);
|
||||
|
||||
/* Enable TX interrrupts */
|
||||
|
||||
sam_enablexfrints(priv, HSMCI_DMASEND_INTS);
|
||||
sam_configxfrints(priv, HSMCI_DMASEND_INTS);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -313,6 +313,7 @@ struct sam_dev_s
|
|||
volatile sdio_eventset_t wkupevent; /* The event that caused the wakeup */
|
||||
WDOG_ID waitwdog; /* Watchdog that handles event timeouts */
|
||||
uint8_t hsmci; /* HSMCI (0, 1, or 2) */
|
||||
bool dmabusy; /* TRUE: DMA is in progress */
|
||||
|
||||
/* Callback support */
|
||||
|
||||
|
@ -375,11 +376,12 @@ static inline uint32_t sam_getreg(struct sam_dev_s *priv,
|
|||
static inline void sam_putreg(struct sam_dev_s *priv, uint32_t value,
|
||||
unsigned int offset);
|
||||
|
||||
static void sam_enablewaitints(struct sam_dev_s *priv, uint32_t waitmask,
|
||||
static inline void sam_configwaitints(struct sam_dev_s *priv, uint32_t waitmask,
|
||||
sdio_eventset_t waitevents);
|
||||
static void sam_disablewaitints(struct sam_dev_s *priv, sdio_eventset_t wkupevents);
|
||||
static void sam_enablexfrints(struct sam_dev_s *priv, uint32_t xfrmask);
|
||||
static inline void sam_configxfrints(struct sam_dev_s *priv, uint32_t xfrmask);
|
||||
static void sam_disablexfrints(struct sam_dev_s *priv);
|
||||
static inline void sam_enableints(struct sam_dev_s *priv);
|
||||
|
||||
static inline void sam_disable(struct sam_dev_s *priv);
|
||||
static inline void sam_enable(struct sam_dev_s *priv);
|
||||
|
@ -680,10 +682,13 @@ static inline void sam_putreg(struct sam_dev_s *priv, uint32_t value,
|
|||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_enablewaitints
|
||||
* Name: sam_configwaitints
|
||||
*
|
||||
* Description:
|
||||
* Enable HSMCI interrupts needed to suport the wait function
|
||||
* Configure HSMCI interrupts needed to support the wait function. Wait
|
||||
* interrupts are configured here, but not enabled until
|
||||
* sam_enableints() is called. Why? Because the XFRDONE interrupt
|
||||
* is always pending until start the data transfer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - A reference to the HSMCI device state structure
|
||||
|
@ -695,20 +700,18 @@ static inline void sam_putreg(struct sam_dev_s *priv, uint32_t value,
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void sam_enablewaitints(struct sam_dev_s *priv, uint32_t waitmask,
|
||||
sdio_eventset_t waitevents)
|
||||
static inline void sam_configwaitints(struct sam_dev_s *priv,
|
||||
uint32_t waitmask,
|
||||
sdio_eventset_t waitevents)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* Save all of the data and set the new interrupt mask in one, atomic
|
||||
* operation.
|
||||
*/
|
||||
/* Save all of the data in one, atomic operation. */
|
||||
|
||||
flags = irqsave();
|
||||
priv->waitevents = waitevents;
|
||||
priv->wkupevent = 0;
|
||||
priv->waitmask = waitmask;
|
||||
sam_putreg(priv, priv->xfrmask | priv->waitmask, SAM_HSMCI_IER_OFFSET);
|
||||
irqrestore(flags);
|
||||
}
|
||||
|
||||
|
@ -745,10 +748,13 @@ static void sam_disablewaitints(struct sam_dev_s *priv,
|
|||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_enablexfrints
|
||||
* Name: sam_configxfrints
|
||||
*
|
||||
* Description:
|
||||
* Enable HSMCI interrupts needed to support the data transfer event
|
||||
* Configure HSMCI interrupts needed to support the data transfer. Data
|
||||
* transfer interrupts are configured here, but not enabled until
|
||||
* sam_enableints() is called. Why? Because the XFRDONE interrupt
|
||||
* is always pending until start the data transfer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - A reference to the HSMCI device state structure
|
||||
|
@ -759,12 +765,9 @@ static void sam_disablewaitints(struct sam_dev_s *priv,
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void sam_enablexfrints(struct sam_dev_s *priv, uint32_t xfrmask)
|
||||
static inline void sam_configxfrints(struct sam_dev_s *priv, uint32_t xfrmask)
|
||||
{
|
||||
irqstate_t flags = irqsave();
|
||||
priv->xfrmask = xfrmask;
|
||||
sam_putreg(priv, priv->xfrmask | priv->waitmask, SAM_HSMCI_IER_OFFSET);
|
||||
irqrestore(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -790,6 +793,28 @@ static void sam_disablexfrints(struct sam_dev_s *priv)
|
|||
irqrestore(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_enableints
|
||||
*
|
||||
* Description:
|
||||
* Enable the previously configured HSMCI interrupts needed to suport the
|
||||
* wait and transfer functions.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - A reference to the HSMCI device state structure
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline void sam_enableints(struct sam_dev_s *priv)
|
||||
{
|
||||
/* Enable all interrupts associated with the waited-for event */
|
||||
|
||||
sam_putreg(priv, priv->xfrmask | priv->waitmask, SAM_HSMCI_IER_OFFSET);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_disable
|
||||
*
|
||||
|
@ -1068,10 +1093,16 @@ static void sam_cmddump(struct sam_dev_s *priv)
|
|||
|
||||
static void sam_dmacallback(DMA_HANDLE handle, void *arg, int result)
|
||||
{
|
||||
struct sam_dev_s *priv = (struct sam_dev_s *)arg;
|
||||
|
||||
/* We don't really do anything at the completion of DMA. The termination
|
||||
* of the transfer is driven by the HSMCI interrupts.
|
||||
*
|
||||
* Mark the DMA not busy.
|
||||
*/
|
||||
|
||||
priv->dmabusy = false;
|
||||
|
||||
sam_xfrsample((struct sam_dev_s *)arg, SAMPLENDX_DMA_CALLBACK);
|
||||
}
|
||||
|
||||
|
@ -1204,6 +1235,7 @@ static void sam_endtransfer(struct sam_dev_s *priv,
|
|||
*/
|
||||
|
||||
sam_dmastop(priv->dma);
|
||||
priv->dmabusy = false;
|
||||
|
||||
/* Disable the DMA handshaking */
|
||||
|
||||
|
@ -1287,6 +1319,7 @@ static int sam_hsmci_interrupt(struct sam_dev_s *priv)
|
|||
|
||||
sr = sam_getreg(priv, SAM_HSMCI_SR_OFFSET);
|
||||
enabled = sr & sam_getreg(priv, SAM_HSMCI_IMR_OFFSET);
|
||||
|
||||
if (enabled == 0)
|
||||
{
|
||||
break;
|
||||
|
@ -1491,6 +1524,7 @@ static void sam_reset(FAR struct sdio_dev_s *dev)
|
|||
priv->waitevents = 0; /* Set of events to be waited for */
|
||||
priv->waitmask = 0; /* Interrupt enables for event waiting */
|
||||
priv->wkupevent = 0; /* The event that caused the wakeup */
|
||||
priv->dmabusy = false; /* No DMA in progress */
|
||||
wd_cancel(priv->waitwdog); /* Cancel any timeouts */
|
||||
|
||||
/* Interrupt mode data transfer support */
|
||||
|
@ -1873,8 +1907,8 @@ static void sam_blocksetup(FAR struct sdio_dev_s *dev, unsigned int blocklen,
|
|||
* Name: sam_cancel
|
||||
*
|
||||
* Description:
|
||||
* Cancel the data transfer setup of HSMCI_RECVSETUP, HSMCI_SENDSETUP,
|
||||
* HSMCI_DMARECVSETUP or HSMCI_DMASENDSETUP. This must be called to cancel
|
||||
* Cancel the data transfer setup of SDIO_RECVSETUP, SDIO_SENDSETUP,
|
||||
* SDIO_DMARECVSETUP or SDIO_DMASENDSETUP. This must be called to cancel
|
||||
* the data transfer setup if, for some reason, you cannot perform the
|
||||
* transfer.
|
||||
*
|
||||
|
@ -1913,6 +1947,7 @@ static int sam_cancel(FAR struct sdio_dev_s *dev)
|
|||
*/
|
||||
|
||||
sam_dmastop(priv->dma);
|
||||
priv->dmabusy = false;
|
||||
|
||||
/* Disable the DMA handshaking */
|
||||
|
||||
|
@ -2200,13 +2235,24 @@ static int sam_recvnotimpl(FAR struct sdio_dev_s *dev,
|
|||
*
|
||||
* Description:
|
||||
* Enable/disable of a set of SDIO wait events. This is part of the
|
||||
* the HSMCI_WAITEVENT sequence. The set of to-be-waited-for events is
|
||||
* configured before calling sam_eventwait. This is done in this way
|
||||
* to help the driver to eliminate race conditions between the command
|
||||
* the SDIO_WAITEVENT sequence. The set of to-be-waited-for events is
|
||||
* configured before calling either calling SDIO_DMARECVSETUP,
|
||||
* SDIO_DMASENDSETUP, or or SDIO_WAITEVENT. This is the recommended
|
||||
* ordering:
|
||||
*
|
||||
* SDIO_WAITENABLE: Discard any pending interrupts, enable event(s)
|
||||
* of interest
|
||||
* SDIO_DMARECVSETUP/
|
||||
* SDIO_DMASENDSETUP: Setup the logic that will trigger the event the
|
||||
* event(s) of interest
|
||||
* SDIO_WAITEVENT: Wait for the event of interest (which might
|
||||
* already have occurred)
|
||||
*
|
||||
* This sequency should eliminate race conditions between the command/trasnfer
|
||||
* setup and the subsequent events.
|
||||
*
|
||||
* The enabled events persist until either (1) HSMCI_WAITENABLE is called
|
||||
* again specifying a different set of wait events, or (2) HSMCI_EVENTWAIT
|
||||
* The enabled events persist until either (1) SDIO_WAITENABLE is called
|
||||
* again specifying a different set of wait events, or (2) SDIO_EVENTWAIT
|
||||
* returns.
|
||||
*
|
||||
* Input Parameters:
|
||||
|
@ -2241,10 +2287,20 @@ static void sam_waitenable(FAR struct sdio_dev_s *dev,
|
|||
waitmask |= priv->cmdrmask;
|
||||
}
|
||||
|
||||
/* Enable event-related interrupts */
|
||||
/* Clear (most) pending interrupts by reading the status register.
|
||||
* No interrupts should be lost (assuming that interrupts were enabled
|
||||
* before sam_waitenable() was called). Any interrupts that become
|
||||
* pending after this point must be valid event indications.
|
||||
*/
|
||||
|
||||
(void)sam_getreg(priv, SAM_HSMCI_SR_OFFSET);
|
||||
sam_enablewaitints(priv, waitmask, eventset);
|
||||
|
||||
/* Wait interrupts are configured here, but not enabled until
|
||||
* sam_eventwait() is called. Why? Because the XFRDONE interrupt is
|
||||
* always pending until start the data transfer.
|
||||
*/
|
||||
|
||||
sam_configwaitints(priv, waitmask, eventset);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -2252,8 +2308,8 @@ static void sam_waitenable(FAR struct sdio_dev_s *dev,
|
|||
*
|
||||
* Description:
|
||||
* Wait for one of the enabled events to occur (or a timeout). Note that
|
||||
* all events enabled by HSMCI_WAITEVENTS are disabled when sam_eventwait
|
||||
* returns. HSMCI_WAITEVENTS must be called again before sam_eventwait
|
||||
* all events enabled by SDIO_WAITEVENTS are disabled when sam_eventwait
|
||||
* returns. SDIO_WAITEVENTS must be called again before sam_eventwait
|
||||
* can be used again.
|
||||
*
|
||||
* Input Parameters:
|
||||
|
@ -2275,13 +2331,22 @@ static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev,
|
|||
sdio_eventset_t wkupevent = 0;
|
||||
int ret;
|
||||
|
||||
/* There is a race condition here... the event may have completed before
|
||||
* we get here. In this case waitevents will be zero, but wkupevents will
|
||||
* be non-zero (and, hopefully, the semaphore count will also be non-zero.
|
||||
/* Since interrupts not been enabled to this point, any relevant events
|
||||
* are pending and should not yet have occurred.
|
||||
*/
|
||||
|
||||
DEBUGASSERT((priv->waitevents != 0 && priv->wkupevent == 0) ||
|
||||
(priv->waitevents == 0 && priv->wkupevent != 0));
|
||||
DEBUGASSERT(priv->waitevents != 0 && priv->wkupevent == 0);
|
||||
|
||||
/* Now enable event-related interrupts. If the events are pending, they
|
||||
* may happen immediately here before entering the loop.
|
||||
*/
|
||||
|
||||
sam_enableints(priv);
|
||||
|
||||
/* There is a race condition here... the event may have completed before
|
||||
* we get here. In this case waitevents will be zero, but wkupevents will
|
||||
* be non-zero (and, hopefully, the semaphore count will also be non-zero).
|
||||
*/
|
||||
|
||||
/* Check if the timeout event is specified in the event set */
|
||||
|
||||
|
@ -2296,7 +2361,15 @@ static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev,
|
|||
return SDIOWAIT_TIMEOUT;
|
||||
}
|
||||
|
||||
/* Start the watchdog timer */
|
||||
/* Start the watchdog timer. I am not sure why this is, but I am\
|
||||
* currently seeing some additional delays when DMA is used.
|
||||
*/
|
||||
|
||||
#warning REVISIT: This should not be necessary
|
||||
if (priv->dmabusy)
|
||||
{
|
||||
timeout += 500;
|
||||
}
|
||||
|
||||
delay = (timeout + (MSEC_PER_TICK-1)) / MSEC_PER_TICK;
|
||||
ret = wd_start(priv->waitwdog, delay, (wdentry_t)sam_eventtimeout,
|
||||
|
@ -2352,7 +2425,7 @@ static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev,
|
|||
*
|
||||
* Events are automatically disabled once the callback is performed and no
|
||||
* further callback events will occur until they are again enabled by
|
||||
* calling this methos.
|
||||
* calling this methods.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - An instance of the SDIO device interface
|
||||
|
@ -2386,7 +2459,7 @@ static void sam_callbackenable(FAR struct sdio_dev_s *dev,
|
|||
* thread.
|
||||
*
|
||||
* When this method is called, all callbacks should be disabled until they
|
||||
* are enabled via a call to HSMCI_CALLBACKENABLE
|
||||
* are enabled via a call to SDIO_CALLBACKENABLE.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - Device-specific state data
|
||||
|
@ -2478,7 +2551,6 @@ static int sam_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
|||
|
||||
/* Configure the RX DMA */
|
||||
|
||||
sam_enablexfrints(priv, HSMCI_DMARECV_INTS);
|
||||
sam_dmarxsetup(priv->dma, paddr, maddr, buflen);
|
||||
|
||||
/* Enable DMA handshaking */
|
||||
|
@ -2488,8 +2560,16 @@ static int sam_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
|||
|
||||
/* Start the DMA */
|
||||
|
||||
priv->dmabusy = true;
|
||||
sam_dmastart(priv->dma, sam_dmacallback, priv);
|
||||
|
||||
/* Configure transfer-related interrupts. Transfer interrupts are not
|
||||
* enabled until after the transfer is stard with an SD command (i.e.,
|
||||
* at the beginning of sam_eventwait().
|
||||
*/
|
||||
|
||||
sam_xfrsample(priv, SAMPLENDX_AFTER_SETUP);
|
||||
sam_configxfrints(priv, HSMCI_DMARECV_INTS);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
@ -2543,12 +2623,16 @@ static int sam_dmasendsetup(FAR struct sdio_dev_s *dev,
|
|||
|
||||
/* Start the DMA */
|
||||
|
||||
priv->dmabusy = true;
|
||||
sam_dmastart(priv->dma, sam_dmacallback, priv);
|
||||
|
||||
/* Configure transfer-related interrupts. Transfer interrupts are not
|
||||
* enabled until after the transfer is stard with an SD command (i.e.,
|
||||
* at the beginning of sam_eventwait().
|
||||
*/
|
||||
|
||||
sam_xfrsample(priv, SAMPLENDX_AFTER_SETUP);
|
||||
|
||||
/* Enable TX interrrupts */
|
||||
|
||||
sam_enablexfrints(priv, HSMCI_DMASEND_INTS);
|
||||
sam_configxfrints(priv, HSMCI_DMARECV_INTS);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -640,14 +640,44 @@ Configurations
|
|||
CONFIG_DEBUG_VERBOSE=y : Enable verbose debug output
|
||||
CONFIG_DEBUG_INPUT=y : Enable debug output from input devices
|
||||
|
||||
STATUS:
|
||||
2013-6-28: The touchscreen is functional.
|
||||
2013-6-29: Hmmm... but there appear to be conditions when the
|
||||
touchscreen driver locks up. Looks like some issue with
|
||||
managing the interrupts.
|
||||
2013-6-30: Those lock-ups appear to be due to poorly placed
|
||||
debug output statements. If you do not enable debug output,
|
||||
the touchscreen is rock-solid.
|
||||
3. Enabling HSMCI support. The SAM3U-KE provides a an SD memory card
|
||||
slot. Support for the SD slot can be enabled with the following
|
||||
settings:
|
||||
|
||||
System Type->ATSAM3/4 Peripheral Support
|
||||
CONFIG_SAM34_HSMCI=y : Enable HSMCI support
|
||||
CONFIG_SAM34_DMA=y : DMAC support is needed by HSMCI
|
||||
|
||||
System Type
|
||||
CONFIG_SAM34_GPIO_IRQ=y : PIO interrupts needed
|
||||
CONFIG_SAM34_GPIOA_IRQ=y : Card detect pin is on PIOA
|
||||
|
||||
Device Drivers -> MMC/SD Driver Support
|
||||
CONFIG_MMCSD=y : Enable MMC/SD support
|
||||
CONFIG_MMSCD_NSLOTS=1 : One slot per driver instance
|
||||
CONFIG_MMCSD_HAVECARDDETECT=y : Supports card-detect PIOs
|
||||
CONFIG_MMCSD_SDIO=y : SDIO-based MMC/SD support
|
||||
CONFIG_SDIO_DMA=y : Use SDIO DMA
|
||||
CONFIG_SDIO_BLOCKSETUP=y : Needs to know block sizes
|
||||
|
||||
Library Routines
|
||||
CONFIG_SCHED_WORKQUEUE=y : Driver needs work queue support
|
||||
|
||||
Application Configuration -> NSH Library
|
||||
CONFIG_NSH_ARCHINIT=y : NSH board-initialization
|
||||
|
||||
STATUS:
|
||||
2013-6-28: The touchscreen is functional.
|
||||
2013-6-29: Hmmm... but there appear to be conditions when the
|
||||
touchscreen driver locks up. Looks like some issue with
|
||||
managing the interrupts.
|
||||
2013-6-30: Those lock-ups appear to be due to poorly placed
|
||||
debug output statements. If you do not enable debug output,
|
||||
the touchscreen is rock-solid.
|
||||
2013-8-10: Added the comments above above enabling HSMCI memory
|
||||
card support and verified that the configuration builds without
|
||||
error. However, that configuration has not yet been tested (and
|
||||
is may even be incomplete).
|
||||
|
||||
nx:
|
||||
Configures to use examples/nx using the HX834x LCD hardware on
|
||||
|
|
|
@ -73,10 +73,17 @@ CONFIG_ARCH="arm"
|
|||
# CONFIG_ARCH_CHIP_LPC31XX is not set
|
||||
# CONFIG_ARCH_CHIP_LPC43XX is not set
|
||||
# CONFIG_ARCH_CHIP_NUC1XX is not set
|
||||
# CONFIG_ARCH_CHIP_SAMA5 is not set
|
||||
CONFIG_ARCH_CHIP_SAM34=y
|
||||
# CONFIG_ARCH_CHIP_STM32 is not set
|
||||
# CONFIG_ARCH_CHIP_STR71X is not set
|
||||
# CONFIG_ARCH_ARM7TDMI is not set
|
||||
# CONFIG_ARCH_ARM926EJS is not set
|
||||
# CONFIG_ARCH_ARM920T is not set
|
||||
# CONFIG_ARCH_CORTEXM0 is not set
|
||||
CONFIG_ARCH_CORTEXM3=y
|
||||
# CONFIG_ARCH_CORTEXM4 is not set
|
||||
# CONFIG_ARCH_CORTEXA5 is not set
|
||||
CONFIG_ARCH_FAMILY="armv7-m"
|
||||
CONFIG_ARCH_CHIP="sam34"
|
||||
# CONFIG_ARMV7M_USEBASEPRI is not set
|
||||
|
@ -93,6 +100,10 @@ CONFIG_ARMV7M_TOOLCHAIN_BUILDROOT=y
|
|||
# CONFIG_ARMV7M_TOOLCHAIN_GNU_EABIL is not set
|
||||
CONFIG_ARMV7M_OABI_TOOLCHAIN=y
|
||||
# CONFIG_GPIO_IRQ is not set
|
||||
CONFIG_ARCH_HAVE_EXTNAND=y
|
||||
CONFIG_ARCH_HAVE_EXTNOR=y
|
||||
CONFIG_ARCH_HAVE_EXTSRAM0=y
|
||||
CONFIG_ARCH_HAVE_EXTSRAM1=y
|
||||
|
||||
#
|
||||
# AT91SAM3/4 Configuration Options
|
||||
|
@ -162,26 +173,18 @@ CONFIG_SAM34_UART0=y
|
|||
# CONFIG_SAM34_WDT is not set
|
||||
# CONFIG_SAM34_HSMCI is not set
|
||||
|
||||
#
|
||||
# AT91SAM3/4 USART Configuration
|
||||
#
|
||||
|
||||
#
|
||||
# AT91SAM3/4 GPIO Interrupt Configuration
|
||||
#
|
||||
|
||||
#
|
||||
# External Memory Configuration
|
||||
#
|
||||
CONFIG_ARCH_HAVE_EXTNAND=y
|
||||
CONFIG_ARCH_HAVE_EXTNOR=y
|
||||
CONFIG_ARCH_HAVE_EXTSRAM0=y
|
||||
CONFIG_ARCH_HAVE_EXTSRAM1=y
|
||||
# CONFIG_SAM34_EXTNAND is not set
|
||||
# CONFIG_SAM34_EXTNOR is not set
|
||||
# CONFIG_SAM34_EXTSRAM0 is not set
|
||||
# CONFIG_SAM34_EXTSRAM1 is not set
|
||||
|
||||
#
|
||||
# AT91SAM3/4 GPIO Interrupt Configuration
|
||||
#
|
||||
|
||||
#
|
||||
# Architecture Options
|
||||
#
|
||||
|
@ -204,8 +207,6 @@ CONFIG_ARCH_HAVE_RAMVECTORS=y
|
|||
#
|
||||
CONFIG_BOARD_LOOPSPERMSEC=8720
|
||||
# CONFIG_ARCH_CALIBRATION is not set
|
||||
CONFIG_RAM_START=0x20000000
|
||||
CONFIG_RAM_SIZE=32768
|
||||
CONFIG_ARCH_HAVE_INTERRUPTSTACK=y
|
||||
CONFIG_ARCH_INTERRUPTSTACK=0
|
||||
|
||||
|
@ -218,6 +219,12 @@ CONFIG_BOOT_RUNFROMFLASH=y
|
|||
# CONFIG_BOOT_RUNFROMSDRAM is not set
|
||||
# CONFIG_BOOT_COPYTORAM is not set
|
||||
|
||||
#
|
||||
# Boot Memory Configuration
|
||||
#
|
||||
CONFIG_RAM_START=0x20000000
|
||||
CONFIG_RAM_SIZE=32768
|
||||
|
||||
#
|
||||
# Board Selection
|
||||
#
|
||||
|
@ -332,6 +339,10 @@ CONFIG_SERIAL=y
|
|||
# CONFIG_DEV_LOWCONSOLE is not set
|
||||
# CONFIG_16550_UART is not set
|
||||
CONFIG_ARCH_HAVE_UART0=y
|
||||
|
||||
#
|
||||
# USART Configuration
|
||||
#
|
||||
CONFIG_MCU_SERIAL=y
|
||||
CONFIG_STANDARD_SERIAL=y
|
||||
CONFIG_UART0_SERIAL_CONSOLE=y
|
||||
|
@ -577,6 +588,7 @@ CONFIG_NSH_BUILTIN_APPS=y
|
|||
# CONFIG_NSH_DISABLE_CAT is not set
|
||||
# CONFIG_NSH_DISABLE_CD is not set
|
||||
# CONFIG_NSH_DISABLE_CP is not set
|
||||
# CONFIG_NSH_DISABLE_CMP is not set
|
||||
# CONFIG_NSH_DISABLE_DD is not set
|
||||
# CONFIG_NSH_DISABLE_ECHO is not set
|
||||
# CONFIG_NSH_DISABLE_EXEC is not set
|
||||
|
@ -693,3 +705,8 @@ CONFIG_READLINE_ECHO=y
|
|||
#
|
||||
# USB Monitor
|
||||
#
|
||||
|
||||
#
|
||||
# Zmodem Commands
|
||||
#
|
||||
# CONFIG_SYSTEM_ZMODEM is not set
|
||||
|
|
|
@ -55,12 +55,21 @@
|
|||
* when the interrupt indicating that a card has been inserted or removed is received,
|
||||
* this function must call sio_mediachange() to handle that event. See
|
||||
* arch/arm/src/sam34/sam_hsmci.h for more information.
|
||||
*
|
||||
* Also see the SAMA5D3x-EK implementation of this same logic. The card detect
|
||||
* interrupt handling should be a drop-in.
|
||||
*/
|
||||
|
||||
#ifdef GPIO_MCI_CD
|
||||
# warning "Card detect interrupt handling needed"
|
||||
#endif
|
||||
|
||||
/* Usually defined in NuttX header files */
|
||||
|
||||
#ifndef OK
|
||||
# define OK 0
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
* Private Functions
|
||||
************************************************************************************/
|
||||
|
|
|
@ -1027,10 +1027,11 @@ Configurations
|
|||
CONFIG_SAMA5_DMAC0=y : DMAC0 is needed by HSMCI0
|
||||
CONFIG_SAMA5_DMAC1=y : DMAC1 is needed by HSMCI1
|
||||
|
||||
System Type
|
||||
CONFIG_SAMA5_PIO_IRQ=y : PIO interrupts needed
|
||||
CONFIG_SAMA5_PIOD_IRQ=y : Card detect pins are on PIOD
|
||||
|
||||
Device Drivers ->
|
||||
Device Drivers -> MMC/SD Driver Support
|
||||
CONFIG_MMCSD=y : Enable MMC/SD support
|
||||
CONFIG_MMSCD_NSLOTS=1 : One slot per driver instance
|
||||
CONFIG_MMCSD_HAVECARDDETECT=y : Supports card-detect PIOs
|
||||
|
@ -1074,9 +1075,12 @@ Configurations
|
|||
where the memory test fails! No idea why.
|
||||
|
||||
2013-8-5: The AT25 configuration has been verified to be functional.
|
||||
2013-9-9: The AT25 configuration has been verified with DMA
|
||||
2013-8-9: The AT25 configuration has been verified with DMA
|
||||
enabled.
|
||||
|
||||
2013-8-10: Basic HSCMI1 functionality (with DMA) has been verified.
|
||||
Most testing is needed to assure that this is a stable solution.
|
||||
|
||||
ostest:
|
||||
This configuration directory, performs a simple OS test using
|
||||
examples/ostest.
|
||||
|
@ -1133,7 +1137,7 @@ Configurations
|
|||
configuration to start the program in NOR FLASH (see just above).
|
||||
See "Creating and Using NORBOOT" above.
|
||||
|
||||
2013-7-31: The OS test configuration is basically functional, but
|
||||
2013-7-31: The OS test configuration is basically functional, but
|
||||
takes a very long time in the round-robin scheduler test computing
|
||||
prime numbers. This test is supposed to be slow -- like several
|
||||
seconds -- but not many minutes. No idea why yet. The best guess
|
||||
|
|
|
@ -63,10 +63,12 @@ endif
|
|||
|
||||
config ARCH_HAVE_SDIO
|
||||
bool
|
||||
default n
|
||||
|
||||
config MMCSD_SDIO
|
||||
bool "MMC/SD SDIO transfer support"
|
||||
default n
|
||||
depends on ARCH_HAVE_SDIO
|
||||
|
||||
if MMCSD_SDIO
|
||||
|
||||
|
|
|
@ -582,8 +582,19 @@
|
|||
* Description:
|
||||
* Enable/disable of a set of SDIO wait events. This is part of the
|
||||
* the SDIO_WAITEVENT sequence. The set of to-be-waited-for events is
|
||||
* configured before calling SDIO_EVENTWAIT. This is done in this way
|
||||
* to help the driver to eliminate race conditions between the command
|
||||
* configured before calling either calling SDIO_DMARECVSETUP,
|
||||
* SDIO_DMASENDSETUP, or or SDIO_WAITEVENT. This is the recommended
|
||||
* ordering:
|
||||
*
|
||||
* SDIO_WAITENABLE: Discard any pending interrupts, enable event(s)
|
||||
* of interest
|
||||
* SDIO_DMARECVSETUP/
|
||||
* SDIO_DMASENDSETUP: Setup the logic that will trigger the event the
|
||||
* event(s) of interest
|
||||
* SDIO_WAITEVENT: Wait for the event of interest (which might
|
||||
* already have occurred)
|
||||
*
|
||||
* This sequency should eliminate race conditions between the command/trasnfer
|
||||
* setup and the subsequent events.
|
||||
*
|
||||
* The enabled events persist until either (1) SDIO_WAITENABLE is called
|
||||
|
|
Loading…
Reference in a new issue