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:
parent
d0f21192e0
commit
7d20a67179
19
ChangeLog
19
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.
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user