summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2013-12-04 07:41:29 -0600
committerGregory Nutt <gnutt@nuttx.org>2013-12-04 07:41:29 -0600
commitcfb48ddeb95a8e9a5f1fbd5ae0f7e08f6f6b5429 (patch)
tree49fe08006df62dc20afc4718b07680d8825f08d8
parent35f099dcfae84f69d08ab94b5c471872833309c7 (diff)
downloadnuttx-cfb48ddeb95a8e9a5f1fbd5ae0f7e08f6f6b5429.tar.gz
nuttx-cfb48ddeb95a8e9a5f1fbd5ae0f7e08f6f6b5429.tar.bz2
nuttx-cfb48ddeb95a8e9a5f1fbd5ae0f7e08f6f6b5429.zip
SAMA5 NAND: Do not perform DMA on small transfers
-rw-r--r--nuttx/arch/arm/src/sama5/Kconfig22
-rw-r--r--nuttx/arch/arm/src/sama5/sam_nand.c18
-rw-r--r--nuttx/arch/arm/src/sama5/sam_nand.h18
3 files changed, 49 insertions, 9 deletions
diff --git a/nuttx/arch/arm/src/sama5/Kconfig b/nuttx/arch/arm/src/sama5/Kconfig
index 12513c5c0..ea4b0b729 100644
--- a/nuttx/arch/arm/src/sama5/Kconfig
+++ b/nuttx/arch/arm/src/sama5/Kconfig
@@ -3348,8 +3348,26 @@ config SAMA5_NAND_DMA
default y
depends on SAMA5_DMAC0
---help---
- Use DMA to perform NAND data transfers. NOTE that DMAC0 must be
- selected (DMAC1 cannot access NFC SRAM). (highly recommended)
+ Use memory-to-memory DMA to perform NAND data transfers. NOTE that
+ DMAC0 must be selected (DMAC1 cannot access NFC SRAM).
+
+config SAMA5_NAND_DMA_THRESHOLD
+ int "DMA threshold"
+ default 784
+ depends on SAMA5_NAND_DMA
+ ---help---
+ Defines a threshold value for performing memory-to-memory DMA.
+
+ If memory-to-memory DMAs are used, then two context switches will
+ occur: (1) when the NAND logic waits for the DMA to complete, and
+ (2) again when the DMA completes and the NAND logic is re-awakened.
+ Each context switch will required saving and restoring a set of
+ registers defining the task state. Those register include the PSR,
+ 16 general purpose registers, and 32 floating point registers or
+ about 196 bytes per task state. That is then 392*2 bytes per
+ context and 784 bytes for both. Plus there is processing overhead.
+ So certainly, there is no reason to use a memory-to-memory DMA
+ transfer for much smaller blocks of data.
config SAMA5_NAND_READYBUSY
bool "NAND Ready/Busy"
diff --git a/nuttx/arch/arm/src/sama5/sam_nand.c b/nuttx/arch/arm/src/sama5/sam_nand.c
index 6fecea58f..b5865be8c 100644
--- a/nuttx/arch/arm/src/sama5/sam_nand.c
+++ b/nuttx/arch/arm/src/sama5/sam_nand.c
@@ -1599,11 +1599,13 @@ static int nand_read(struct sam_nandcs_s *priv, bool nfcsram,
}
#ifdef CONFIG_SAMA5_NAND_DMA
- /* Then perform the transfer via DMA or not, depending on if we have
- * a DMA channel assigned.
+ /* Then perform the transfer via memory-to-memory DMA or not, depending
+ * on if we have a DMA channel assigned and if the transfer is
+ * sufficiently large. Small DMAs (e.g., for spare data) are not peformed
+ * because the DMA context switch can take more time that the DMA itself.
*/
- if (priv->dma)
+ if (priv->dma && buflen > CONFIG_SAMA5_NAND_DMA_THRESHOLD)
{
/* Transfer using DMA */
@@ -1909,12 +1911,14 @@ static int nand_write(struct sam_nandcs_s *priv, bool nfcsram,
dest += offset;
- /* Then perform the transfer via DMA or not, depending on if we have
- * a DMA channel assigned.
+#ifdef CONFIG_SAMA5_NAND_DMA
+ /* Then perform the transfer via memory-to-memory DMA or not, depending
+ * on if we have a DMA channel assigned and if the transfer is
+ * sufficiently large. Small DMAs (e.g., for spare data) are not peformed
+ * because the DMA context switch can take more time that the DMA itself.
*/
-#ifdef CONFIG_SAMA5_NAND_DMA
- if (priv->dma)
+ if (priv->dma && buflen > CONFIG_SAMA5_NAND_DMA_THRESHOLD)
{
/* Transfer using DMA */
diff --git a/nuttx/arch/arm/src/sama5/sam_nand.h b/nuttx/arch/arm/src/sama5/sam_nand.h
index cd282c6a9..ca1d8fd81 100644
--- a/nuttx/arch/arm/src/sama5/sam_nand.h
+++ b/nuttx/arch/arm/src/sama5/sam_nand.h
@@ -74,6 +74,24 @@
# endif
#endif
+/* If memory-to-memory DMAs are used, then two context switches will occur:
+ * (1) when the NAND logic waits for the DMA to complete, and (2) again when
+ * the DMA completes and the NAND logic is re-awakened. Each context switch
+ * will required saving and restoring a set of registers defining the task
+ * state. Those register include the PSR, 16 general purpose registers, and
+ * 32 floating point registers or about 196 bytes per task state. That is
+ * then 392*2 bytes per context and 784 bytes for both. Plus there is
+ * processing overhead. So certainly, there is no reason to use a memory-to-
+ * memory DMA transfer for much smaller blocks of data.
+ */
+
+#ifdef CONFIG_SAMA5_NAND_DMA
+# ifndef CONFIG_SAMA5_NAND_DMA_THRESHOLD
+# define CONFIG_SAMA5_NAND_DMA_THRESHOLD 784
+# endif
+#endif
+
+
/* Hardware ECC types. These are extensions to the NANDECC_HWECC value
* defined in include/nuttx/mtd/nand_raw.h.
*