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 * configs/ekk-lm3s9b96/ostest and nsh: All EKK-LM3S9B96 configurations
converted to use the mconf configuration tool. converted to use the mconf configuration tool.
* configs/zkit-arm-1769: Add support for Zilogic System's ARM development * 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 * 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 * 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 * 2013-02-27: All configurations for the Cortex-M0 NuTINY-SDK-NUC120
appear to be functional and stable. appear to be functional and stable.
* configs/zkit-arm-1769/nsh: Add an NSH configuration for the * 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); up_mdelay(50);
#endif #endif
/* Clear the EPDISD interrupt */ /* Clear the EPDISD interrupt indication */
stm32_putreg(OTGFS_DOEPINT_EPDISD, STM32_OTGFS_DOEPINT(privep->epphy)); 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); regaddr = STM32_OTGFS_DIEPINT(privep->epphy);
while ((stm32_getreg(regaddr) & OTGFS_DIEPINT_INEPNE) == 0); while ((stm32_getreg(regaddr) & OTGFS_DIEPINT_INEPNE) == 0);
/* Clear the INEPNE interrupt indication */
stm32_putreg(OTGFS_DIEPINT_INEPNE, regaddr); stm32_putreg(OTGFS_DIEPINT_INEPNE, regaddr);
#endif #endif
@ -4146,7 +4149,7 @@ static void stm32_epin_disable(FAR struct stm32_ep_s *privep)
regaddr = STM32_OTGFS_DIEPINT(privep->epphy); regaddr = STM32_OTGFS_DIEPINT(privep->epphy);
while ((stm32_getreg(regaddr) & OTGFS_DIEPINT_EPDISD) == 0); 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)); 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); spi_putreg(priv, STM32_SPI_CR1_OFFSET, cr1);
} }
/**************************************************************************** /************************************************************************************
* Name: spi_lock * Name: spi_lock
* *
* Description: * Description:
@ -796,7 +796,7 @@ static void spi_modifycr1(FAR struct stm32_spidev_s *priv, uint16_t setbits, uin
* Returned Value: * Returned Value:
* None * None
* *
****************************************************************************/ ************************************************************************************/
#ifndef CONFIG_SPI_OWNBUS #ifndef CONFIG_SPI_OWNBUS
static int spi_lock(FAR struct spi_dev_s *dev, bool lock) 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; return;
} }
spi_modifycr1(priv, setbits, clrbits); spi_modifycr1(priv, 0, SPI_CR1_SPE);
spi_modifycr1(priv, setbits, clrbits);
/* Save the selection so the subsequence re-configurations will be faster */ spi_modifycr1(priv, SPI_CR1_SPE, 0);
/* Save the selection so the subsequence re-configurations will be faster */
#ifndef CONFIG_SPI_OWNBUS #ifndef CONFIG_SPI_OWNBUS
priv->nbits = nbits; priv->nbits = nbits;
} }
#endif #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) 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; FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev;
uint32_t regval;
uint16_t ret; uint16_t ret;
DEBUGASSERT(priv && priv->spibase); 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); spi_writeword(priv, wd);
ret = spi_readword(priv); 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; return ret;
} }
/************************************************************************* /************************************************************************************
* Name: spi_exchange (no DMA) * Name: spi_exchange (no DMA)
* *
* Description: * Description:

View file

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