MMC/SD driver needs to manage SPI mode and data width as well

This commit is contained in:
Gregory Nutt 2013-06-17 12:31:24 -06:00
parent 8db5d403ee
commit b9ad057972
5 changed files with 86 additions and 35 deletions

View file

@ -4994,4 +4994,5 @@
signal (it is active low) (2013-6-16).
* configs/sam3u-ek/include/board.h: The SAM3U-EK board now runs at
96MHz. This might have broken some things? (2013-6-17).
* drivers/mmcsd/mmcsd-spi.c: Driver need to make sure that the SPI mode
and data width are correct (2013-6-17).

View file

@ -615,21 +615,12 @@ Configuration sub-directories
perform good measurements but I am not getting the /PENIRQ
interrupt. The interrupt is set up correctly (I can ground
A24 and I get the interrupt), so apparently the ADS7843E is
not generating interrupts.
not generating interrupts. No idea why.
nx:
Configures to use examples/nx using the HX834x LCD hardware on
the SAM3U-EK development board.
STATUS:
This configuration used to work well in an older NuttX version
on an older SAM3U-EK board (my old board was bricked and I got
another after a lapse of a couple of years). But now it no
longer works! There appears to be some bug, perhaps a memory
clobbering bug, that causes a variety of symptons: Hangs on
UART0 or hard faults. The LCD functionality is basically intact,
but not usable because of these problems.
ostest:
This configuration directory, performs a simple OS test using
examples/ostest. By default, this project assumes that you are

View file

@ -697,6 +697,19 @@ Configuration sub-directories
System Type -> Peripherals:
CONFIG_SAM34_SPI=y : Enable the SAM4L SPI peripheral
Device Drivers
CONFIG_SPI=y : Enable SPI support
CONFIG_SPI_EXCHANGE=y : The exchange() method is supported
CONFIG_SPI_OWNBUS=y : Smaller code if this is the only SPI device
CONFIG_MMCSD=y : Enable MMC/SD support
CONFIG_MMCSD_NSLOTS=1 : Only one MMC/SD card slot
CONFIG_MMCSD_MULTIBLOCK_DISABLE=n : Should not need to disable multi-block transfers
CONFIG_MMCSD_HAVECARDDETECT=y : I/O1 module as a card detect GPIO
CONFIG_MMCSD_SPI=y : Use the SPI interface to the MMC/SD card
CONFIG_MMCSD_SPICLOCK=20000000 : This is a guess for the optimal MMC/SD frequency
CONFIG_MMCSD_SPIMODE=0 : Mode 0 is required
Board Selection -> Common Board Options
CONFIG_NSH_MMCSDSLOTNO=0 : Only one MMC/SD slot, slot 0
CONFIG_NSH_MMCSDSPIPORTNO=0 : Use CS=0 if the I/O1 is in EXT1, OR
@ -707,18 +720,6 @@ Configuration sub-directories
CONFIG_SAM4L_XPLAINED_IOMODULE_EXT1=y : In EXT1, or EXT2
CONFIG_SAM4L_XPLAINED_IOMODULE_EXT2=y
Device Drivers
CONFIG_SPI=y : Enable SPI support
CONFIG_SPI_EXCHANGE=y : The exchange() method is supported
CONFIG_SPI_OWNBUS=y : Smaller code if this is the only SPI device
CONFIG_MMCSD=y : Enable MMC/SD support
CONFIG_MMCSD_NSLOTS=1 : Only one MMC/SD card slot
CONFIG_MMCSD_MULTIBLOCK_DISABLE=y : I tested this way, but this may not be required
CONFIG_MMCSD_HAVECARDDETECT=y : I/O1 module as a card detect GPIO
CONFIG_MMCSD_SPI=y : Use the SPI interface to the MMC/SD card
CONFIG_MMCSD_SPICLOCK=20000000 : This is a guess for the optimal MMC/SD frequency
Application Configuration -> NSH Library
CONFIG_NSH_ARCHINIT=y : Board has architecture-specific initialization
@ -728,5 +729,18 @@ Configuration sub-directories
behave very well (since its outgoing prompts also appear as incoming
commands).
STATUS: As of 2013-6-16, the SPI interface is not communicating with
the SD card.
NOTE: If you get a compilation error like:
libxx_new.cxx:74:40: error: 'operator new' takes type 'size_t'
('unsigned int') as first parameter [-fper
Sometimes NuttX and your toolchain will disagree on the underlying
type of size_t; sometimes it is an 'unsigned int' and sometimes it is
an 'unsigned long int'. If this error occurs, then you may need to
toggle the value of CONFIG_CXX_NEWLONG.
STATUS: As of 2013-6-16, the microSD slot on the I/O1 is not working.
This could be an SPI communication issues, but it appears more like
a card interfacing problems. The card does make some appropriate
responses but also reports some other issues (erase reset) and will
not exit IDLE most.

View file

@ -43,6 +43,8 @@ config MMCSD_SPI
default y
depends on SPI
if MMCSD_SPI
config MMCSD_SPICLOCK
int "MMC/SD maximum SPI clock"
default 20000000
@ -51,11 +53,20 @@ config MMCSD_SPICLOCK
Maximum SPI clock to drive MMC/SD card.
Default is 20MHz.
config MMCSD_SPIMODE
int "MMC/SD SPI mode"
default 0
---help---
Should be mode 0. However, sometimes this is useful for experimenting.
endif
config MMCSD_SDIO
bool "MMC/SD sdio transfer support"
bool "MMC/SD SDIO transfer support"
default n
if MMCSD_SDIO
config SDIO_DMA
bool "SDIO DMA support"
default n

View file

@ -86,6 +86,10 @@
# define CONFIG_MMCSD_SPICLOCK 20000000
#endif
#ifndef CONFIG_MMCSD_SPIMODE
# define CONFIG_MMCSD_SPIMODE SPIDEV_MODE0
#endif
#ifndef CONFIG_MMCSD_SECTOR512
# define CONFIG_MMCSD_SECTOR512 /* Force 512 byte sectors on all cards */
#endif
@ -348,12 +352,13 @@ static void mmcsd_semtake(FAR struct mmcsd_slot_s *slot)
#ifndef CONFIG_SPI_OWNBUS
(void)SPI_LOCK(slot->spi, true);
/* Set the frequency, as some other driver could have changed it.
* TODO: Also need to restore mode and number-of-bits. Those can also
* change from SPI device-to-device.
/* Set the frequency, bit width and mode, as some other driver could have
* changed those since the last time that we had the SPI bus.
*/
SPI_SETFREQUENCY(slot->spi, slot->spispeed);
SPI_SETMODE(slot->sp, CONFIG_MMCSD_SPIMODE);
SPI_SETBITS(slot->sp, 8);
#endif
/* Get exclusive access to the MMC/SD device (prossibly un-necessary if
@ -370,6 +375,10 @@ static void mmcsd_semtake(FAR struct mmcsd_slot_s *slot)
}
}
/****************************************************************************
* Name: mmcsd_semgive
****************************************************************************/
static void mmcsd_semgive(FAR struct mmcsd_slot_s *slot)
{
/* Relinquish the lock on the MMC/SD device */
@ -391,6 +400,27 @@ static void mmcsd_semgive(FAR struct mmcsd_slot_s *slot)
#endif
}
/****************************************************************************
* Name: mmcsd_spiinit
*
* Description:
* Set SPI mode and data width.
*
* Assumptions:
* MMC/SD card already selected
*
****************************************************************************/
#ifdef CONFIG_SPI_OWNBUS
static inline void mmcsd_spiinit(FAR struct mmcsd_slot_s *slot)
{
SPI_SETMODE(slot->spi, CONFIG_MMCSD_SPIMODE);
SPI_SETBITS(slot->spi, 8);
}
#else
# define mmcsd_spiinit(slot)
#endif
/****************************************************************************
* Name: mmcsd_waitready
*
@ -682,7 +712,7 @@ static void mmcsd_decodecsd(FAR struct mmcsd_slot_s *slot, uint8_t *csd)
uint32_t csizemult;
uint32_t csize;
/* Calculate SPI max clock */
/* Calculate the SPI max clock frequency */
maxfrequency =
g_transpeedtu[MMCSD_CSD_TRANSPEED_TIMEVALUE(csd)] *
@ -696,12 +726,9 @@ static void mmcsd_decodecsd(FAR struct mmcsd_slot_s *slot, uint8_t *csd)
frequency = CONFIG_MMCSD_SPICLOCK;
}
/* Store the value for future use */
/* Set the actual SPI frequency as close as possible to the max frequency */
slot->spispeed = frequency;
/* Set the actual SPI frequency as close as possible to that value */
frequency = SPI_SETFREQUENCY(spi, frequency);
/* Now determine the delay to access data */
@ -1548,6 +1575,7 @@ static int mmcsd_mediainitialize(FAR struct mmcsd_slot_s *slot)
/* Clock Freq. Identification Mode < 400kHz */
slot->spispeed = MMCSD_IDMODE_CLOCK;
SPI_SETFREQUENCY(spi, MMCSD_IDMODE_CLOCK);
/* Set the maximum access time out */
@ -1910,9 +1938,15 @@ int mmcsd_spislotinitialize(int minor, int slotno, FAR struct spi_dev_s *spi)
slot->spi = spi;
slot->spispeed = MMCSD_IDMODE_CLOCK;
/* Ininitialize for the media in the slot (if any) */
/* Get exclusvice access to the SPI bus and make sure that SPI is properly
* configured for the MMC/SD card
*/
mmcsd_semtake(slot);
mmcsd_spiinit(slot);
/* Ininitialize for the media in the slot (if any) */
ret = mmcsd_mediainitialize(slot);
mmcsd_semgive(slot);
if (ret == 0)