Fixes to STM32 SPI, USB MSC class driver, and MMC/SD SPI driver from Petteri Aimonen

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5688 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2013-02-28 17:34:57 +00:00
parent d0f21192e0
commit 7d20a67179
5 changed files with 99 additions and 48 deletions

View File

@ -4205,12 +4205,23 @@
* configs/ekk-lm3s9b96/ostest and nsh: All EKK-LM3S9B96 configurations
converted to use the mconf configuration tool.
* configs/zkit-arm-1769: Add support for Zilogic System's ARM development
Kit, ZKIT-ARM-1769.
Kit, ZKIT-ARM-1769. From Rashid.
* configs/zkit-arm-1769/hello: Add a "Hello, World!" configuration for
the KBIT-ARM-1769 board.
the KBIT-ARM-1769 board. From Rashid.
* configs/zkit-arm-1769/thttpd: Add a THTTPD configuration for the
KBIT-ARM-1769 board.
KBIT-ARM-1769 board. From Rashid.
* 2013-02-27: All configurations for the Cortex-M0 NuTINY-SDK-NUC120
appear to be functional and stable.
* configs/zkit-arm-1769/nsh: Add an NSH configuration for the
KBIT-ARM-1769 board.
KBIT-ARM-1769 board. From Rashid.
* arch/arm/src/stm32/stm32_otgfsdev.c: Fixes from Petterri Aimonen
related to corner cases that can cause infinite interrupts.
* drivers/usbdev/usbmsc_scsi.c: Change to allow the full name in the
USB descriptor but a truncated, 8-byte name in the SCSI field.
From Petteri Aimonen.
* arch/arm/src/stm32/stm32_spi.c: Need to clear error flags to prevent
corruption of subsequent transfers. Also, bit count should not be
changed while the SPI peripheral is enabled. From Petteri Aimonen.
* drivers/mmcsd/mmcsd_spi.c: When bus is shared, the speed has to be
set every time. Also SD cards require a few dummy clocks to react
into CS release. From Petteri Aimonen.

View File

@ -4050,7 +4050,7 @@ static void stm32_epout_disable(FAR struct stm32_ep_s *privep)
up_mdelay(50);
#endif
/* Clear the EPDISD interrupt */
/* Clear the EPDISD interrupt indication */
stm32_putreg(OTGFS_DOEPINT_EPDISD, STM32_OTGFS_DOEPINT(privep->epphy));
@ -4124,6 +4124,9 @@ static void stm32_epin_disable(FAR struct stm32_ep_s *privep)
regaddr = STM32_OTGFS_DIEPINT(privep->epphy);
while ((stm32_getreg(regaddr) & OTGFS_DIEPINT_INEPNE) == 0);
/* Clear the INEPNE interrupt indication */
stm32_putreg(OTGFS_DIEPINT_INEPNE, regaddr);
#endif
@ -4146,7 +4149,7 @@ static void stm32_epin_disable(FAR struct stm32_ep_s *privep)
regaddr = STM32_OTGFS_DIEPINT(privep->epphy);
while ((stm32_getreg(regaddr) & OTGFS_DIEPINT_EPDISD) == 0);
/* Clear the EPDISD interrupt */
/* Clear the EPDISD interrupt indication */
stm32_putreg(OTGFS_DIEPINT_EPDISD, stm32_getreg(regaddr));

View File

@ -777,7 +777,7 @@ static void spi_modifycr1(FAR struct stm32_spidev_s *priv, uint16_t setbits, uin
spi_putreg(priv, STM32_SPI_CR1_OFFSET, cr1);
}
/****************************************************************************
/************************************************************************************
* Name: spi_lock
*
* Description:
@ -796,7 +796,7 @@ static void spi_modifycr1(FAR struct stm32_spidev_s *priv, uint16_t setbits, uin
* Returned Value:
* None
*
****************************************************************************/
************************************************************************************/
#ifndef CONFIG_SPI_OWNBUS
static int spi_lock(FAR struct spi_dev_s *dev, bool lock)
@ -1049,12 +1049,14 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
return;
}
spi_modifycr1(priv, setbits, clrbits);
/* Save the selection so the subsequence re-configurations will be faster */
spi_modifycr1(priv, 0, SPI_CR1_SPE);
spi_modifycr1(priv, setbits, clrbits);
spi_modifycr1(priv, SPI_CR1_SPE, 0);
/* Save the selection so the subsequence re-configurations will be faster */
#ifndef CONFIG_SPI_OWNBUS
priv->nbits = nbits;
priv->nbits = nbits;
}
#endif
}
@ -1078,6 +1080,7 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
{
FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev;
uint32_t regval;
uint16_t ret;
DEBUGASSERT(priv && priv->spibase);
@ -1085,11 +1088,15 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
spi_writeword(priv, wd);
ret = spi_readword(priv);
spivdbg("Sent: %04x Return: %04x\n", wd, ret);
/* Check and clear any error flags (Reading from the SR clears the error flags) */
regval = spi_getreg(priv, STM32_SPI_SR_OFFSET);
spivdbg("Sent: %04x Return: %04x Status: %02x\n", wd, ret, regval);
return ret;
}
/*************************************************************************
/************************************************************************************
* Name: spi_exchange (no DMA)
*
* Description:

View File

@ -154,6 +154,7 @@ struct mmcsd_slot_s
uint32_t twrite; /* Card write time */
uint32_t ocr; /* Last 4 bytes of OCR (R3) */
uint32_t r7; /* Last 4 bytes of R7 */
uint32_t spispeed; /* Speed to use for SPI in data mode */
};
struct mmcsd_cmdinfo_s
@ -169,8 +170,8 @@ struct mmcsd_cmdinfo_s
/* Misc *********************************************************************/
static void mmcsd_semtake(sem_t *sem, FAR struct spi_dev_s *spi);
static void mmcsd_semgive(sem_t *sem, FAR struct spi_dev_s *spi);
static void mmcsd_semtake(FAR struct mmcsd_slot_s *slot);
static void mmcsd_semgive(FAR struct mmcsd_slot_s *slot);
/* Card SPI interface *******************************************************/
@ -340,19 +341,23 @@ static const struct mmcsd_cmdinfo_s g_acmd41 = {ACMD41, MMCSD_CMDRESP_R1, 0xff};
* Name: mmcsd_semtake
****************************************************************************/
static void mmcsd_semtake(sem_t *sem, FAR struct spi_dev_s *spi)
static void mmcsd_semtake(FAR struct mmcsd_slot_s *slot)
{
/* Get exclusive access to the SPI bus (if necessary) */
#ifndef CONFIG_SPI_OWNBUS
(void)SPI_LOCK(spi, true);
(void)SPI_LOCK(slot->spi, true);
/* Set the frequency, as some other driver could have changed it. */
SPI_SETFREQUENCY(slot->spi, slot->spispeed);
#endif
/* Get exclusive access to the MMC/SD device (prossibly un-necessary if
* SPI_LOCK is also implemented as a semaphore.
*/
while (sem_wait(sem) != 0)
while (sem_wait(&slot->sem) != 0)
{
/* The only case that an error should occur here is if the wait was
* awakened by a signal.
@ -362,19 +367,27 @@ static void mmcsd_semtake(sem_t *sem, FAR struct spi_dev_s *spi)
}
}
static void mmcsd_semgive(sem_t *sem, FAR struct spi_dev_s *spi)
static void mmcsd_semgive(FAR struct mmcsd_slot_s *slot)
{
/* Relinquish the lock on the MMC/SD device */
sem_post(sem);
sem_post(&slot->sem);
/* Relinquish the lock on the SPI bus */
#ifndef CONFIG_SPI_OWNBUS
(void)SPI_LOCK(spi, false);
/* The card may need up to 8 SCLK cycles to sample the CS status
* and release the MISO line.
*/
(void)SPI_SEND(slot->spi, 0xff);
/* Relinquish exclusive access to the SPI bus */
(void)SPI_LOCK(slot->spi, false);
#endif
}
/****************************************************************************
* Name: mmcsd_waitready
*
@ -680,6 +693,10 @@ static void mmcsd_decodecsd(FAR struct mmcsd_slot_s *slot, uint8_t *csd)
frequency = CONFIG_MMCSD_SPICLOCK;
}
/* Store the value for future use */
slot->spispeed = frequency;
/* Set the actual SPI frequency as close as possible to that value */
frequency = SPI_SETFREQUENCY(spi, frequency);
@ -1027,7 +1044,7 @@ static int mmcsd_open(FAR struct inode *inode)
/* Verify that an MMC/SD card has been inserted */
ret = -ENODEV;
mmcsd_semtake(&slot->sem, spi);
mmcsd_semtake(slot);
if ((SPI_STATUS(spi, SPIDEV_MMCSD) & SPI_STATUS_PRESENT) != 0)
{
/* Yes.. a card is present. Has it been initialized? */
@ -1052,7 +1069,7 @@ static int mmcsd_open(FAR struct inode *inode)
}
errout_with_sem:
mmcsd_semgive(&slot->sem, spi);
mmcsd_semgive(slot);
return ret;
}
@ -1146,7 +1163,7 @@ static ssize_t mmcsd_read(FAR struct inode *inode, unsigned char *buffer,
/* Select the slave */
mmcsd_semtake(&slot->sem, spi);
mmcsd_semtake(slot);
SPI_SELECT(spi, SPIDEV_MMCSD, true);
/* Single or multiple block read? */
@ -1207,7 +1224,7 @@ static ssize_t mmcsd_read(FAR struct inode *inode, unsigned char *buffer,
SPI_SELECT(spi, SPIDEV_MMCSD, false);
SPI_SEND(spi, 0xff);
mmcsd_semgive(&slot->sem, spi);
mmcsd_semgive(slot);
fvdbg("Read %d bytes:\n", nbytes);
mmcsd_dumpbuffer("Read buffer", buffer, nbytes);
@ -1215,7 +1232,7 @@ static ssize_t mmcsd_read(FAR struct inode *inode, unsigned char *buffer,
errout_with_eio:
SPI_SELECT(spi, SPIDEV_MMCSD, false);
mmcsd_semgive(&slot->sem, spi);
mmcsd_semgive(slot);
return -EIO;
}
@ -1309,7 +1326,7 @@ static ssize_t mmcsd_write(FAR struct inode *inode, const unsigned char *buffer,
/* Select the slave */
mmcsd_semtake(&slot->sem, spi);
mmcsd_semtake(slot);
SPI_SELECT(spi, SPIDEV_MMCSD, true);
/* Single or multiple block transfer? */
@ -1380,7 +1397,7 @@ static ssize_t mmcsd_write(FAR struct inode *inode, const unsigned char *buffer,
ret = mmcsd_waitready(slot);
SPI_SELECT(spi, SPIDEV_MMCSD, false);
SPI_SEND(spi, 0xff);
mmcsd_semgive(&slot->sem, spi);
mmcsd_semgive(slot);
/* The success return value is the number of sectors written */
@ -1388,7 +1405,7 @@ static ssize_t mmcsd_write(FAR struct inode *inode, const unsigned char *buffer,
errout_with_sem:
SPI_SELECT(spi, SPIDEV_MMCSD, false);
mmcsd_semgive(&slot->sem, spi);
mmcsd_semgive(slot);
return -EIO;
}
#endif
@ -1437,14 +1454,14 @@ static int mmcsd_geometry(FAR struct inode *inode, struct geometry *geometry)
/* Re-sample the CSD */
mmcsd_semtake(&slot->sem, spi);
mmcsd_semtake(slot);
SPI_SELECT(spi, SPIDEV_MMCSD, true);
ret = mmcsd_getcsd(slot, csd);
SPI_SELECT(spi, SPIDEV_MMCSD, false);
if (ret < 0)
{
mmcsd_semgive(&slot->sem, spi);
mmcsd_semgive(slot);
fdbg("mmcsd_getcsd returned %d\n", ret);
return ret;
}
@ -1473,7 +1490,7 @@ static int mmcsd_geometry(FAR struct inode *inode, struct geometry *geometry)
*/
slot->state &= ~MMCSD_SLOTSTATUS_MEDIACHGD;
mmcsd_semgive(&slot->sem, spi);
mmcsd_semgive(slot);
fvdbg("geo_available: %d\n", geometry->geo_available);
fvdbg("geo_mediachanged: %d\n", geometry->geo_mediachanged);
@ -1578,7 +1595,7 @@ static int mmcsd_mediainitialize(FAR struct mmcsd_slot_s *slot)
{
fdbg("Send CMD0 failed: R1=%02x\n", result);
SPI_SELECT(spi, SPIDEV_MMCSD, false);
mmcsd_semgive(&slot->sem, spi);
mmcsd_semgive(slot);
return -EIO;
}
@ -1703,7 +1720,7 @@ static int mmcsd_mediainitialize(FAR struct mmcsd_slot_s *slot)
{
fdbg("Failed to exit IDLE state\n");
SPI_SELECT(spi, SPIDEV_MMCSD, false);
mmcsd_semgive(&slot->sem, spi);
mmcsd_semgive(slot);
return -EIO;
}
}
@ -1712,7 +1729,7 @@ static int mmcsd_mediainitialize(FAR struct mmcsd_slot_s *slot)
{
fdbg("Failed to identify card\n");
SPI_SELECT(spi, SPIDEV_MMCSD, false);
mmcsd_semgive(&slot->sem, spi);
mmcsd_semgive(slot);
return -EIO;
}
@ -1724,7 +1741,7 @@ static int mmcsd_mediainitialize(FAR struct mmcsd_slot_s *slot)
{
fdbg("mmcsd_getcsd(CMD9) failed: %d\n", result);
SPI_SELECT(spi, SPIDEV_MMCSD, false);
mmcsd_semgive(&slot->sem, spi);
mmcsd_semgive(slot);
return -EIO;
}
@ -1797,7 +1814,7 @@ static void mmcsd_mediachanged(void *arg)
/* Save the current slot state and reassess the new state */
mmcsd_semtake(&slot->sem, spi);
mmcsd_semtake(slot);
oldstate = slot->state;
/* Check if media was removed or inserted */
@ -1833,8 +1850,8 @@ static void mmcsd_mediachanged(void *arg)
slot->state |= MMCSD_SLOTSTATUS_MEDIACHGD;
}
}
mmcsd_semgive(&slot->sem, spi);
mmcsd_semgive(slot);
}
/****************************************************************************
@ -1889,12 +1906,13 @@ int mmcsd_spislotinitialize(int minor, int slotno, FAR struct spi_dev_s *spi)
/* Bind the SPI port to the slot */
slot->spi = spi;
slot->spispeed = MMCSD_IDMODE_CLOCK;
/* Ininitialize for the media in the slot (if any) */
mmcsd_semtake(&slot->sem, spi);
mmcsd_semtake(slot);
ret = mmcsd_mediainitialize(slot);
mmcsd_semgive(&slot->sem, spi);
mmcsd_semgive(slot);
if (ret == 0)
{
fvdbg("mmcsd_mediainitialize returned OK\n");

View File

@ -607,15 +607,27 @@ static inline int usbmsc_cmdinquiry(FAR struct usbmsc_dev_s *priv,
memset(response->vendorid, ' ', 8+16+4);
len = strlen(g_mscvendorstr);
DEBUGASSERT(len <= 8);
if (len > 8)
{
len = 8;
}
memcpy(response->vendorid, g_mscvendorstr, len);
len = strlen(g_mscproductstr);
DEBUGASSERT(len <= 16);
if (len > 16)
{
len = 16;
}
memcpy(response->productid, g_mscproductstr, len);
len = strlen(g_mscserialstr);
DEBUGASSERT(len <= 4);
if (len > 4)
{
len = 4;
}
memcpy(response->revision, g_mscserialstr, len);
}
}