Fix to SST25 driver to permit faster write modes. From David Sidrane
This commit is contained in:
parent
f3313a0f51
commit
a2b6d12271
10
ChangeLog
10
ChangeLog
@ -5945,4 +5945,12 @@
|
||||
from David Sidrane plugs the hole for now (2013-11-1).
|
||||
* drivers/mtd/mtd_config.c: Reduce configuration header size. From
|
||||
Ken Pettit (2013-11-1).
|
||||
|
||||
* drivers/mtd/sst25.c: Improved write performance by fixing a bug
|
||||
that prevented operation in the faster write mode. The code did
|
||||
not wait on the last write complete before issuing the WRDI The
|
||||
loop in general failed to wait on the fist 2 bytes after the
|
||||
SST25_AAI if the next 2 were FF FF, then it would reissue the
|
||||
address but not cancel the write. Reorganized to always wait for
|
||||
completion after and address with data write and on any data
|
||||
write so that the device is complete before WRDI is sent. From
|
||||
David Sidrane (2013-11-2).
|
||||
|
@ -465,7 +465,7 @@ CONFIG_SST25_SPIMODE=0
|
||||
CONFIG_SST25_SPIFREQUENCY=80000000
|
||||
# CONFIG_SST25_READONLY is not set
|
||||
CONFIG_SST25_SECTOR512=y
|
||||
CONFIG_SST25_SLOWWRITE=y
|
||||
# CONFIG_SST25_SLOWWRITE is not set
|
||||
# CONFIG_SST25_SLOWREAD is not set
|
||||
# CONFIG_MTD_SST39FV is not set
|
||||
# CONFIG_MTD_W25 is not set
|
||||
|
@ -439,7 +439,7 @@ CONFIG_SST25_SPIMODE=0
|
||||
CONFIG_SST25_SPIFREQUENCY=80000000
|
||||
# CONFIG_SST25_READONLY is not set
|
||||
CONFIG_SST25_SECTOR512=y
|
||||
CONFIG_SST25_SLOWWRITE=y
|
||||
# CONFIG_SST25_SLOWWRITE is not set
|
||||
# CONFIG_SST25_SLOWREAD is not set
|
||||
# CONFIG_MTD_SST39FV is not set
|
||||
# CONFIG_MTD_W25 is not set
|
||||
|
@ -439,7 +439,7 @@ CONFIG_SST25_SPIMODE=0
|
||||
CONFIG_SST25_SPIFREQUENCY=80000000
|
||||
# CONFIG_SST25_READONLY is not set
|
||||
CONFIG_SST25_SECTOR512=y
|
||||
CONFIG_SST25_SLOWWRITE=y
|
||||
# CONFIG_SST25_SLOWWRITE is not set
|
||||
# CONFIG_SST25_SLOWREAD is not set
|
||||
# CONFIG_MTD_SST39FV is not set
|
||||
# CONFIG_MTD_W25 is not set
|
||||
|
@ -259,7 +259,13 @@ config SST25_SECTOR512
|
||||
|
||||
config SST25_SLOWWRITE
|
||||
bool
|
||||
default y
|
||||
default n
|
||||
---help---
|
||||
There used to be a bug in the current code when using the higher speed AAI
|
||||
write sequence. The nature of the bug is that the WRDI instruction is not
|
||||
working. At the end of the AAI sequence, the status register continues to
|
||||
report that the SST25 is write enabled (WEL bit) and in AAI mode (AAI
|
||||
bit). This has been fixed by David Sidrane!
|
||||
|
||||
config SST25_SLOWREAD
|
||||
bool
|
||||
|
@ -82,17 +82,6 @@
|
||||
# define CONFIG_SST25_SPIFREQUENCY 20000000
|
||||
#endif
|
||||
|
||||
/* There is a bug in the current code when using the higher speed AAI write sequence.
|
||||
* The nature of the bug is that the WRDI instruction is not working. At the end
|
||||
* of the AAI sequence, the status register continues to report that the SST25 is
|
||||
* write enabled (WEL bit) and in AAI mode (AAI bit). This *must* be fixed in any
|
||||
* production code if you want to have proper write performance.
|
||||
*/
|
||||
|
||||
#warning "REVISIT"
|
||||
#undef CONFIG_SST25_SLOWWRITE
|
||||
#define CONFIG_SST25_SLOWWRITE 1
|
||||
|
||||
/* SST25 Instructions ***************************************************************/
|
||||
/* Command Value Description Addr Data */
|
||||
/* Dummy */
|
||||
@ -225,9 +214,10 @@ 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);
|
||||
static void sst25_unprotect(FAR struct sst25_dev_s *priv);
|
||||
#endif
|
||||
static uint8_t sst25_waitwritecomplete(FAR struct sst25_dev_s *priv);
|
||||
static inline void sst25_cmd(struct sst25_dev_s *priv, uint8_t cmd);
|
||||
static inline void sst25_wren(FAR struct sst25_dev_s *priv);
|
||||
#if !defined(CONFIG_SST25_SLOWWRITE) && !defined(CONFIG_SST25_READONLY)
|
||||
static inline void sst25_wrdi(FAR struct sst25_dev_s *priv);
|
||||
@ -377,30 +367,23 @@ static inline int sst25_readid(struct sst25_dev_s *priv)
|
||||
************************************************************************************/
|
||||
|
||||
#ifndef CONFIG_SST25_READONLY
|
||||
static void sst25_unprotect(FAR struct spi_dev_s *dev)
|
||||
static void sst25_unprotect(struct sst25_dev_s *priv)
|
||||
{
|
||||
/* Select this FLASH part */
|
||||
|
||||
SPI_SELECT(dev, SPIDEV_FLASH, true);
|
||||
|
||||
/* Send "Write enable status (EWSR)" */
|
||||
|
||||
SPI_SEND(dev, SST25_EWSR);
|
||||
sst25_cmd(priv, SST25_EWSR);
|
||||
|
||||
/* Re-select this FLASH part (This might not be necessary... but is it shown in
|
||||
* the timing diagrams)
|
||||
*/
|
||||
/* Send "Write enable status (WRSR)" */
|
||||
|
||||
SPI_SELECT(dev, SPIDEV_FLASH, false);
|
||||
SPI_SELECT(dev, SPIDEV_FLASH, true);
|
||||
SPI_SELECT(priv->dev, SPIDEV_FLASH, true);
|
||||
|
||||
/* Send "Write enable status (EWSR)" */
|
||||
SPI_SEND(priv->dev, SST25_WRSR);
|
||||
|
||||
SPI_SEND(dev, SST25_WRSR);
|
||||
/* Followed by the new status value */
|
||||
|
||||
/* Following by the new status value */
|
||||
SPI_SEND(priv->dev, 0);
|
||||
|
||||
SPI_SEND(dev, 0);
|
||||
SPI_SELECT(priv->dev, SPIDEV_FLASH, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -481,41 +464,45 @@ static uint8_t sst25_waitwritecomplete(struct sst25_dev_s *priv)
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
* Name: sst25_wren
|
||||
* Name: sst25_cmd
|
||||
************************************************************************************/
|
||||
|
||||
static inline void sst25_wren(struct sst25_dev_s *priv)
|
||||
static inline void sst25_cmd(struct sst25_dev_s *priv, uint8_t cmd)
|
||||
{
|
||||
/* Select this FLASH part */
|
||||
|
||||
SPI_SELECT(priv->dev, SPIDEV_FLASH, true);
|
||||
|
||||
/* Send "Write Enable (WREN)" command */
|
||||
/* Send command */
|
||||
|
||||
(void)SPI_SEND(priv->dev, cmd);
|
||||
|
||||
(void)SPI_SEND(priv->dev, SST25_WREN);
|
||||
|
||||
/* Deselect the FLASH */
|
||||
|
||||
SPI_SELECT(priv->dev, SPIDEV_FLASH, false);
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
* Name: sst25_wren
|
||||
************************************************************************************/
|
||||
|
||||
static inline void sst25_wren(struct sst25_dev_s *priv)
|
||||
{
|
||||
/* Send "Write Enable (WREN)" command */
|
||||
|
||||
sst25_cmd(priv, SST25_WREN);
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
* Name: sst25_wrdi
|
||||
************************************************************************************/
|
||||
|
||||
#if !defined(CONFIG_SST25_SLOWWRITE) && !defined(CONFIG_SST25_READONLY)
|
||||
static inline void sst25_wrdi(struct sst25_dev_s *priv)
|
||||
{
|
||||
/* Select this FLASH part */
|
||||
|
||||
SPI_SELECT(priv->dev, SPIDEV_FLASH, true);
|
||||
|
||||
/* Send "Write Disable (WRDI)" command */
|
||||
|
||||
(void)SPI_SEND(priv->dev, SST25_WRDI);
|
||||
|
||||
/* Deselect the FLASH */
|
||||
|
||||
SPI_SELECT(priv->dev, SPIDEV_FLASH, false);
|
||||
sst25_cmd(priv, SST25_WRDI);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -770,6 +757,11 @@ static void sst25_wordwrite(struct sst25_dev_s *priv, FAR const uint8_t *buffer,
|
||||
|
||||
SPI_SELECT(priv->dev, SPIDEV_FLASH, false);
|
||||
|
||||
/* Wait for the preceding write to complete. */
|
||||
|
||||
status = sst25_waitwritecomplete(priv);
|
||||
DEBUGASSERT((status & (SST25_SR_WEL|SST25_SR_BP_MASK|SST25_SR_AAI)) == (SST25_SR_WEL|SST25_SR_AAI));
|
||||
|
||||
/* Decrement the word count and advance the write position */
|
||||
|
||||
nwords--;
|
||||
@ -785,10 +777,6 @@ static void sst25_wordwrite(struct sst25_dev_s *priv, FAR const uint8_t *buffer,
|
||||
(buffer[0] != SST25_ERASED_STATE ||
|
||||
buffer[1] != SST25_ERASED_STATE))
|
||||
{
|
||||
/* Wait for the preceding write to complete. */
|
||||
|
||||
status = sst25_waitwritecomplete(priv);
|
||||
DEBUGASSERT((status & (SST25_SR_WEL|SST25_SR_BP_MASK|SST25_SR_AAI)) == (SST25_SR_WEL|SST25_SR_AAI));
|
||||
|
||||
/* Select this FLASH part */
|
||||
|
||||
@ -806,6 +794,11 @@ static void sst25_wordwrite(struct sst25_dev_s *priv, FAR const uint8_t *buffer,
|
||||
|
||||
SPI_SELECT(priv->dev, SPIDEV_FLASH, false);
|
||||
|
||||
/* Wait for the preceding write to complete. */
|
||||
|
||||
status = sst25_waitwritecomplete(priv);
|
||||
DEBUGASSERT((status & (SST25_SR_WEL|SST25_SR_BP_MASK|SST25_SR_AAI)) == (SST25_SR_WEL|SST25_SR_AAI));
|
||||
|
||||
/* Decrement the word count and advance the write position */
|
||||
|
||||
nwords--;
|
||||
@ -1251,7 +1244,7 @@ FAR struct mtd_dev_s *sst25_initialize(FAR struct spi_dev_s *dev)
|
||||
/* Make sure that the FLASH is unprotected so that we can write into it */
|
||||
|
||||
#ifndef CONFIG_SST25_READONLY
|
||||
sst25_unprotect(priv->dev);
|
||||
sst25_unprotect(priv);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SST25_SECTOR512 /* Simulate a 512 byte sector */
|
||||
|
Loading…
Reference in New Issue
Block a user