Add logic to un-protect blocks to the SST25 driver

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4873 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2012-06-26 23:23:08 +00:00
parent b96e5cf7f7
commit 9be225d32d
2 changed files with 149 additions and 27 deletions

View File

@ -867,9 +867,11 @@ Where <subdir> is one of the following:
CONFIG_NSH_DISABLE_WGET=y
NOTES: (1) It takes many seconds to boot the sytem using the NXFFS
file system because the entire FLASH must be verified on power up.
(2) FAT does not have this delay and this configuration can be
modified to use the (larger) FAT file system as described below:
file system because the entire FLASH must be verified on power up
(a probably several minutes the first time that NXFFS comes up and
had to format the file system). (2) FAT does not have these delays
and this configuration can be modified to use the (larger) FAT file
system as described below:
fat:
There is no FAT configuration, but the nxffx configuration can be used

View File

@ -186,7 +186,7 @@ struct sst25_dev_s
uint16_t nsectors; /* Number of erase sectors */
uint8_t sectorshift; /* Log2 of erase sector size */
#ifdef CONFIG_SST25_SECTOR512 /* Simulate a 512 byte sector */
#if defined(CONFIG_SST25_SECTOR512) && !defined(CONFIG_SST25_READONLY)
uint8_t flags; /* Buffered sector flags */
uint16_t esectno; /* Erase sector number in the cache*/
FAR uint8_t *sector; /* Allocated sector data */
@ -202,6 +202,9 @@ struct sst25_dev_s
static void sst25_lock(FAR struct spi_dev_s *dev);
static inline void sst25_unlock(FAR struct spi_dev_s *dev);
static inline int sst25_readid(FAR struct sst25_dev_s *priv);
#ifndef CONFIG_SST25_READONLY
static void sst25_unprotect(FAR struct spi_dev_s *dev);
#endif
static void sst25_waitwritecomplete(FAR struct sst25_dev_s *priv);
static inline void sst25_wren(FAR struct sst25_dev_s *priv);
static inline void sst25_wrdi(FAR struct sst25_dev_s *priv);
@ -209,8 +212,14 @@ static void sst25_sectorerase(FAR struct sst25_dev_s *priv, off_t offset);
static inline int sst25_chiperase(FAR struct sst25_dev_s *priv);
static void sst25_byteread(FAR struct sst25_dev_s *priv, FAR uint8_t *buffer,
off_t address, size_t nbytes);
#ifndef CONFIG_SST25_READONLY
#ifdef CONFIG_SST25_SLOWWRITE
static void sst32_bytewrite(FAR struct sst25_dev_s *priv, FAR const uint8_t *buffer,
off_t address, size_t nbytes);
#else
static void sst32_wordwrite(FAR struct sst25_dev_s *priv, FAR const uint8_t *buffer,
off_t address, size_t nwords);
off_t address, size_t nbytes);
#endif
#ifdef CONFIG_SST25_SECTOR512
static void sst25_cacheflush(struct sst25_dev_s *priv);
static FAR uint8_t *sst25_cacheread(struct sst25_dev_s *priv, off_t sector);
@ -218,6 +227,7 @@ static void sst25_cacheerase(struct sst25_dev_s *priv, off_t sector);
static void sst32_cachewrite(FAR struct sst25_dev_s *priv, FAR const uint8_t *buffer,
off_t sector, size_t nsectors);
#endif
#endif
/* MTD driver methods */
@ -327,6 +337,38 @@ static inline int sst25_readid(struct sst25_dev_s *priv)
return -ENODEV;
}
/************************************************************************************
* Name: sst25_unprotect
************************************************************************************/
#ifndef CONFIG_SST25_READONLY
static void sst25_unprotect(FAR struct spi_dev_s *dev)
{
/* Select this FLASH part */
SPI_SELECT(dev, SPIDEV_FLASH, true);
/* Send "Write enable status (EWSR)" */
SPI_SEND(dev, SST25_EWSR);
/* Re-select this FLASH part (This might not be necessary... but is it shown in
* the timing diagrams)
*/
SPI_SELECT(dev, SPIDEV_FLASH, false);
SPI_SELECT(dev, SPIDEV_FLASH, true);
/* Send "Write enable status (EWSR)" */
SPI_SEND(dev, SST25_WRSR);
/* Following by the new status value */
SPI_SEND(dev, 0);
}
#endif
/************************************************************************************
* Name: sst25_waitwritecomplete
************************************************************************************/
@ -416,7 +458,6 @@ static inline void sst25_wren(struct sst25_dev_s *priv)
/* Deselect the FLASH */
SPI_SELECT(priv->dev, SPIDEV_FLASH, false);
fvdbg("Enabled\n");
}
/************************************************************************************
@ -476,7 +517,6 @@ static void sst25_sectorerase(struct sst25_dev_s *priv, off_t sector)
/* Deselect the FLASH */
SPI_SELECT(priv->dev, SPIDEV_FLASH, false);
fvdbg("Erased\n");
}
/************************************************************************************
@ -529,7 +569,11 @@ static void sst25_byteread(FAR struct sst25_dev_s *priv, FAR uint8_t *buffer,
/* Send "Read from Memory " instruction */
#ifdef CONFIG_SST25_SLOWREAD
(void)SPI_SEND(priv->dev, SST25_READ);
#else
(void)SPI_SEND(priv->dev, SST25_FAST_READ);
#endif
/* Send the address high byte first. */
@ -539,7 +583,9 @@ static void sst25_byteread(FAR struct sst25_dev_s *priv, FAR uint8_t *buffer,
/* Send a dummy byte */
#ifndef CONFIG_SST25_SLOWREAD
(void)SPI_SEND(priv->dev, SST25_DUMMY);
#endif
/* Then read all of the requested bytes */
@ -550,13 +596,66 @@ static void sst25_byteread(FAR struct sst25_dev_s *priv, FAR uint8_t *buffer,
SPI_SELECT(priv->dev, SPIDEV_FLASH, false);
}
/************************************************************************************
* Name: sst32_bytewrite
************************************************************************************/
#if defined(CONFIG_SST25_SLOWWRITE) && !defined(CONFIG_SST25_READONLY)
static void sst32_bytewrite(struct sst25_dev_s *priv, FAR const uint8_t *buffer,
off_t address, size_t nbytes)
{
fvdbg("address: %08lx nwords: %d\n", (long)address, (int)nbytes);
DEBUGASSERT(priv && buffer);
/* Write each byte individually */
for (; nbytes > 0; nbytes--)
{
/* Wait for any preceding write or erase operation to complete. */
sst25_waitwritecomplete(priv);
/* Enable write access to the FLASH */
sst25_wren(priv);
/* Select this FLASH part */
SPI_SELECT(priv->dev, SPIDEV_FLASH, true);
/* Send "Byte Program (BP)" command */
(void)SPI_SEND(priv->dev, SST25_BP);
/* Send the byte address high byte first. */
(void)SPI_SEND(priv->dev, (address >> 16) & 0xff);
(void)SPI_SEND(priv->dev, (address >> 8) & 0xff);
(void)SPI_SEND(priv->dev, address & 0xff);
/* Then write the single byte */
(void)SPI_SEND(priv->dev, *buffer);
/* Deselect the FLASH and setup for the next pass through the loop */
SPI_SELECT(priv->dev, SPIDEV_FLASH, false);
buffer++;
address++;
}
}
#endif
/************************************************************************************
* Name: sst32_wordwrite
************************************************************************************/
#if !defined(CONFIG_SST25_SLOWWRITE) && !defined(CONFIG_SST25_READONLY)
static void sst32_wordwrite(struct sst25_dev_s *priv, FAR const uint8_t *buffer,
off_t address, size_t nwords)
off_t address, size_t nbytes)
{
size_t nwords = (nbytes + 1) >> 1;
fvdbg("address: %08lx nwords: %d\n", (long)address, (int)nwords);
DEBUGASSERT(priv && buffer);
@ -564,7 +663,7 @@ static void sst32_wordwrite(struct sst25_dev_s *priv, FAR const uint8_t *buffer,
sst25_waitwritecomplete(priv);
/* Enable the write access to the FLASH */
/* Enable write access to the FLASH */
sst25_wren(priv);
@ -576,7 +675,7 @@ static void sst32_wordwrite(struct sst25_dev_s *priv, FAR const uint8_t *buffer,
(void)SPI_SEND(priv->dev, SST25_AAI);
/* Send the page address high byte first. */
/* Send the word address high byte first. */
(void)SPI_SEND(priv->dev, (address >> 16) & 0xff);
(void)SPI_SEND(priv->dev, (address >> 8) & 0xff);
@ -597,14 +696,14 @@ static void sst32_wordwrite(struct sst25_dev_s *priv, FAR const uint8_t *buffer,
for (nwords--; nwords > 0; nwords--)
{
/* Select this FLASH part */
SPI_SELECT(priv->dev, SPIDEV_FLASH, true);
/* Wait for the preceding write to complete. */
sst25_waitwritecomplete(priv);
/* Select this FLASH part */
SPI_SELECT(priv->dev, SPIDEV_FLASH, true);
/* Send "Auto Address Increment (AAI)" command with no address */
(void)SPI_SEND(priv->dev, SST25_AAI);
@ -622,14 +721,14 @@ static void sst32_wordwrite(struct sst25_dev_s *priv, FAR const uint8_t *buffer,
/* Disable writing */
sst25_wrdi(priv);
fvdbg("Written\n");
}
#endif
/************************************************************************************
* Name: sst25_cacheflush
************************************************************************************/
#ifdef CONFIG_SST25_SECTOR512
#if defined(CONFIG_SST25_SECTOR512) && !defined(CONFIG_SST25_READONLY)
static void sst25_cacheflush(struct sst25_dev_s *priv)
{
/* If the cached is dirty (meaning that it no longer matches the old FLASH contents)
@ -641,8 +740,13 @@ static void sst25_cacheflush(struct sst25_dev_s *priv)
{
/* Write entire erase block to FLASH */
#ifdef CONFIG_SST25_SLOWWRITE
sst32_bytewrite(priv, priv->sector, (off_t)priv->esectno << priv->sectorshift,
(1 << priv->sectorshift));
#else
sst32_wordwrite(priv, priv->sector, (off_t)priv->esectno << priv->sectorshift,
(1 << (priv->sectorshift - 1)));
(1 << priv->sectorshift));
#endif
/* The case is no long dirty and the FLASH is no longer erased */
@ -656,7 +760,7 @@ static void sst25_cacheflush(struct sst25_dev_s *priv)
* Name: sst25_cacheread
************************************************************************************/
#ifdef CONFIG_SST25_SECTOR512
#if defined(CONFIG_SST25_SECTOR512) && !defined(CONFIG_SST25_READONLY)
static FAR uint8_t *sst25_cacheread(struct sst25_dev_s *priv, off_t sector)
{
off_t esectno;
@ -707,7 +811,7 @@ static FAR uint8_t *sst25_cacheread(struct sst25_dev_s *priv, off_t sector)
* Name: sst25_cacheerase
************************************************************************************/
#ifdef CONFIG_SST25_SECTOR512
#if defined(CONFIG_SST25_SECTOR512) && !defined(CONFIG_SST25_READONLY)
static void sst25_cacheerase(struct sst25_dev_s *priv, off_t sector)
{
FAR uint8_t *dest;
@ -746,7 +850,7 @@ static void sst25_cacheerase(struct sst25_dev_s *priv, off_t sector)
* Name: sst25_cachewrite
************************************************************************************/
#ifdef CONFIG_SST25_SECTOR512
#if defined(CONFIG_SST25_SECTOR512) && !defined(CONFIG_SST25_READONLY)
static void sst32_cachewrite(FAR struct sst25_dev_s *priv, FAR const uint8_t *buffer,
off_t sector, size_t nsectors)
{
@ -797,6 +901,9 @@ static void sst32_cachewrite(FAR struct sst25_dev_s *priv, FAR const uint8_t *bu
static int sst25_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks)
{
#ifdef CONFIG_SST25_READONLY
return -EACESS
#else
FAR struct sst25_dev_s *priv = (FAR struct sst25_dev_s *)dev;
size_t blocksleft = nblocks;
@ -826,6 +933,7 @@ static int sst25_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nbloc
sst25_unlock(priv->dev);
return (int)nblocks;
#endif
}
/************************************************************************************
@ -874,6 +982,9 @@ static ssize_t sst25_bread(FAR struct mtd_dev_s *dev, off_t startblock, size_t n
static ssize_t sst25_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks,
FAR const uint8_t *buffer)
{
#ifdef CONFIG_SST25_READONLY
return -EACCESS;
#else
FAR struct sst25_dev_s *priv = (FAR struct sst25_dev_s *)dev;
fvdbg("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
@ -881,17 +992,20 @@ static ssize_t sst25_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t
/* Lock the SPI bus and write all of the pages to FLASH */
sst25_lock(priv->dev);
#ifdef CONFIG_SST25_SECTOR512
#if defined(CONFIG_SST25_SECTOR512)
sst32_cachewrite(priv, buffer, startblock, nblocks);
#elif defined(CONFIG_SST25_SLOWWRITE)
sst32_bytewrite(priv, buffer, startblock << priv->sectorshift,
nblocks << priv->sectorshift);
#else
{
size_t nwords = (nblocks << (priv->sectorshift - 1));
sst32_wordwrite(priv, buffer, startblock << priv->sectorshift, nwords);
}
sst32_wordwrite(priv, buffer, startblock << priv->sectorshift,
nblocks << priv->sectorshift);
#endif
sst25_unlock(priv->dev);
return nblocks;
#endif
}
/************************************************************************************
@ -1034,9 +1148,15 @@ FAR struct mtd_dev_s *sst25_initialize(FAR struct spi_dev_s *dev)
kfree(priv);
priv = NULL;
}
#ifdef CONFIG_SST25_SECTOR512 /* Simulate a 512 byte sector */
else
{
/* Make sure the the FLASH is unprotected so that we can write into it */
#ifndef CONFIG_SST25_READONLY
sst25_unprotect(priv->dev);
#endif
#ifdef CONFIG_SST25_SECTOR512 /* Simulate a 512 byte sector */
/* Allocate a buffer for the erase block cache */
priv->sector = (FAR uint8_t *)kmalloc(1 << priv->sectorshift);
@ -1048,9 +1168,9 @@ FAR struct mtd_dev_s *sst25_initialize(FAR struct spi_dev_s *dev)
kfree(priv);
priv = NULL;
}
}
#endif
}
}
/* Return the implementation-specific state structure as the MTD device */