From f1b1e3ba11994bcbb0a1ddad9f8e686a6a9ae475 Mon Sep 17 00:00:00 2001 From: patacongo Date: Thu, 28 Feb 2013 17:34:57 +0000 Subject: 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 --- nuttx/ChangeLog | 19 ++++++-- nuttx/arch/arm/src/stm32/stm32_otgfsdev.c | 7 ++- nuttx/arch/arm/src/stm32/stm32_spi.c | 23 +++++---- nuttx/drivers/mmcsd/mmcsd_spi.c | 80 +++++++++++++++++++------------ nuttx/drivers/usbdev/usbmsc_scsi.c | 18 +++++-- 5 files changed, 99 insertions(+), 48 deletions(-) (limited to 'nuttx') diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index dea9e937b..db909eab2 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -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. diff --git a/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c b/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c index 1aab2ebc9..ece965b01 100644 --- a/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c +++ b/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c @@ -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)); diff --git a/nuttx/arch/arm/src/stm32/stm32_spi.c b/nuttx/arch/arm/src/stm32/stm32_spi.c index 09c4c72aa..c8714e7df 100644 --- a/nuttx/arch/arm/src/stm32/stm32_spi.c +++ b/nuttx/arch/arm/src/stm32/stm32_spi.c @@ -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: diff --git a/nuttx/drivers/mmcsd/mmcsd_spi.c b/nuttx/drivers/mmcsd/mmcsd_spi.c index 9939fa9de..8c4eb4429 100644 --- a/nuttx/drivers/mmcsd/mmcsd_spi.c +++ b/nuttx/drivers/mmcsd/mmcsd_spi.c @@ -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"); diff --git a/nuttx/drivers/usbdev/usbmsc_scsi.c b/nuttx/drivers/usbdev/usbmsc_scsi.c index ccc967618..ff551871c 100644 --- a/nuttx/drivers/usbdev/usbmsc_scsi.c +++ b/nuttx/drivers/usbdev/usbmsc_scsi.c @@ -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); } } -- cgit v1.2.3