mirror of
https://github.com/apache/nuttx.git
synced 2026-06-06 00:14:22 +08:00
Fix to SST25 driver to permit faster write modes. From David Sidrane
This commit is contained in:
@@ -5945,4 +5945,12 @@
|
|||||||
from David Sidrane plugs the hole for now (2013-11-1).
|
from David Sidrane plugs the hole for now (2013-11-1).
|
||||||
* drivers/mtd/mtd_config.c: Reduce configuration header size. From
|
* drivers/mtd/mtd_config.c: Reduce configuration header size. From
|
||||||
Ken Pettit (2013-11-1).
|
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_SPIFREQUENCY=80000000
|
||||||
# CONFIG_SST25_READONLY is not set
|
# CONFIG_SST25_READONLY is not set
|
||||||
CONFIG_SST25_SECTOR512=y
|
CONFIG_SST25_SECTOR512=y
|
||||||
CONFIG_SST25_SLOWWRITE=y
|
# CONFIG_SST25_SLOWWRITE is not set
|
||||||
# CONFIG_SST25_SLOWREAD is not set
|
# CONFIG_SST25_SLOWREAD is not set
|
||||||
# CONFIG_MTD_SST39FV is not set
|
# CONFIG_MTD_SST39FV is not set
|
||||||
# CONFIG_MTD_W25 is not set
|
# CONFIG_MTD_W25 is not set
|
||||||
|
|||||||
@@ -439,7 +439,7 @@ CONFIG_SST25_SPIMODE=0
|
|||||||
CONFIG_SST25_SPIFREQUENCY=80000000
|
CONFIG_SST25_SPIFREQUENCY=80000000
|
||||||
# CONFIG_SST25_READONLY is not set
|
# CONFIG_SST25_READONLY is not set
|
||||||
CONFIG_SST25_SECTOR512=y
|
CONFIG_SST25_SECTOR512=y
|
||||||
CONFIG_SST25_SLOWWRITE=y
|
# CONFIG_SST25_SLOWWRITE is not set
|
||||||
# CONFIG_SST25_SLOWREAD is not set
|
# CONFIG_SST25_SLOWREAD is not set
|
||||||
# CONFIG_MTD_SST39FV is not set
|
# CONFIG_MTD_SST39FV is not set
|
||||||
# CONFIG_MTD_W25 is not set
|
# CONFIG_MTD_W25 is not set
|
||||||
|
|||||||
@@ -439,7 +439,7 @@ CONFIG_SST25_SPIMODE=0
|
|||||||
CONFIG_SST25_SPIFREQUENCY=80000000
|
CONFIG_SST25_SPIFREQUENCY=80000000
|
||||||
# CONFIG_SST25_READONLY is not set
|
# CONFIG_SST25_READONLY is not set
|
||||||
CONFIG_SST25_SECTOR512=y
|
CONFIG_SST25_SECTOR512=y
|
||||||
CONFIG_SST25_SLOWWRITE=y
|
# CONFIG_SST25_SLOWWRITE is not set
|
||||||
# CONFIG_SST25_SLOWREAD is not set
|
# CONFIG_SST25_SLOWREAD is not set
|
||||||
# CONFIG_MTD_SST39FV is not set
|
# CONFIG_MTD_SST39FV is not set
|
||||||
# CONFIG_MTD_W25 is not set
|
# CONFIG_MTD_W25 is not set
|
||||||
|
|||||||
+7
-1
@@ -259,7 +259,13 @@ config SST25_SECTOR512
|
|||||||
|
|
||||||
config SST25_SLOWWRITE
|
config SST25_SLOWWRITE
|
||||||
bool
|
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
|
config SST25_SLOWREAD
|
||||||
bool
|
bool
|
||||||
|
|||||||
+38
-45
@@ -82,17 +82,6 @@
|
|||||||
# define CONFIG_SST25_SPIFREQUENCY 20000000
|
# define CONFIG_SST25_SPIFREQUENCY 20000000
|
||||||
#endif
|
#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 ***************************************************************/
|
/* SST25 Instructions ***************************************************************/
|
||||||
/* Command Value Description Addr Data */
|
/* Command Value Description Addr Data */
|
||||||
/* Dummy */
|
/* 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 void sst25_unlock(FAR struct spi_dev_s *dev);
|
||||||
static inline int sst25_readid(FAR struct sst25_dev_s *priv);
|
static inline int sst25_readid(FAR struct sst25_dev_s *priv);
|
||||||
#ifndef CONFIG_SST25_READONLY
|
#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
|
#endif
|
||||||
static uint8_t sst25_waitwritecomplete(FAR struct sst25_dev_s *priv);
|
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);
|
static inline void sst25_wren(FAR struct sst25_dev_s *priv);
|
||||||
#if !defined(CONFIG_SST25_SLOWWRITE) && !defined(CONFIG_SST25_READONLY)
|
#if !defined(CONFIG_SST25_SLOWWRITE) && !defined(CONFIG_SST25_READONLY)
|
||||||
static inline void sst25_wrdi(FAR struct sst25_dev_s *priv);
|
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
|
#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)" */
|
/* 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
|
/* Send "Write enable status (WRSR)" */
|
||||||
* the timing diagrams)
|
|
||||||
*/
|
|
||||||
|
|
||||||
SPI_SELECT(dev, SPIDEV_FLASH, false);
|
SPI_SELECT(priv->dev, SPIDEV_FLASH, true);
|
||||||
SPI_SELECT(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
|
#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 */
|
/* Select this FLASH part */
|
||||||
|
|
||||||
SPI_SELECT(priv->dev, SPIDEV_FLASH, true);
|
SPI_SELECT(priv->dev, SPIDEV_FLASH, true);
|
||||||
|
|
||||||
/* Send "Write Enable (WREN)" command */
|
/* Send command */
|
||||||
|
|
||||||
(void)SPI_SEND(priv->dev, SST25_WREN);
|
(void)SPI_SEND(priv->dev, cmd);
|
||||||
|
|
||||||
/* Deselect the FLASH */
|
/* Deselect the FLASH */
|
||||||
|
|
||||||
SPI_SELECT(priv->dev, SPIDEV_FLASH, false);
|
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
|
* Name: sst25_wrdi
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
#if !defined(CONFIG_SST25_SLOWWRITE) && !defined(CONFIG_SST25_READONLY)
|
#if !defined(CONFIG_SST25_SLOWWRITE) && !defined(CONFIG_SST25_READONLY)
|
||||||
static inline void sst25_wrdi(struct sst25_dev_s *priv)
|
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 */
|
/* Send "Write Disable (WRDI)" command */
|
||||||
|
|
||||||
(void)SPI_SEND(priv->dev, SST25_WRDI);
|
sst25_cmd(priv, SST25_WRDI);
|
||||||
|
|
||||||
/* Deselect the FLASH */
|
|
||||||
|
|
||||||
SPI_SELECT(priv->dev, SPIDEV_FLASH, false);
|
|
||||||
}
|
}
|
||||||
#endif
|
#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);
|
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 */
|
/* Decrement the word count and advance the write position */
|
||||||
|
|
||||||
nwords--;
|
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[0] != SST25_ERASED_STATE ||
|
||||||
buffer[1] != 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 */
|
/* 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);
|
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 */
|
/* Decrement the word count and advance the write position */
|
||||||
|
|
||||||
nwords--;
|
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 */
|
/* Make sure that the FLASH is unprotected so that we can write into it */
|
||||||
|
|
||||||
#ifndef CONFIG_SST25_READONLY
|
#ifndef CONFIG_SST25_READONLY
|
||||||
sst25_unprotect(priv->dev);
|
sst25_unprotect(priv);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SST25_SECTOR512 /* Simulate a 512 byte sector */
|
#ifdef CONFIG_SST25_SECTOR512 /* Simulate a 512 byte sector */
|
||||||
|
|||||||
Reference in New Issue
Block a user