Dataflash_WaitWhileBusy() now always ensures that the dataflash is ready for the...
authorDean Camera <dean@fourwalledcubicle.com>
Mon, 29 Jun 2009 09:30:06 +0000 (09:30 +0000)
committerDean Camera <dean@fourwalledcubicle.com>
Mon, 29 Jun 2009 09:30:06 +0000 (09:30 +0000)
Added new DATAFLASH_CHIP_MASK() macro to the Dataflash driver, which returns the Dataflash select mask for the given chip index.

Updated MassStorage device block write routines to use ping-pong Dataflash buffering to increase throughput by around 30%.

Demos/Device/ClassDriver/MassStorage/Lib/DataflashManager.c
Demos/Device/LowLevel/MassStorage/Lib/DataflashManager.c
LUFA/Drivers/Board/Dataflash.h
LUFA/ManPages/ChangeLog.txt
LUFA/ManPages/FutureChanges.txt
LUFA/Scheduler/Scheduler.h

index 326f660..2335a5e 100644 (file)
@@ -43,7 +43,6 @@
  *  the pre-selected data OUT endpoint. This routine reads in OS sized blocks from the endpoint and writes\r
  *  them to the dataflash in Dataflash page sized blocks.\r
  *\r
  *  the pre-selected data OUT endpoint. This routine reads in OS sized blocks from the endpoint and writes\r
  *  them to the dataflash in Dataflash page sized blocks.\r
  *\r
- *  \param[in] MSInterfaceInfo  Pointer to a Mass Storage class state structure for the Mass Storage interface being used\r
  *  \param[in] BlockAddress  Data block starting address for the write sequence\r
  *  \param[in] TotalBlocks   Number of blocks of data to write\r
  */\r
  *  \param[in] BlockAddress  Data block starting address for the write sequence\r
  *  \param[in] TotalBlocks   Number of blocks of data to write\r
  */\r
@@ -52,11 +51,14 @@ void DataflashManager_WriteBlocks(USB_ClassInfo_MS_Device_t* MSInterfaceInfo, co
        uint16_t CurrDFPage          = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);\r
        uint16_t CurrDFPageByte      = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);\r
        uint8_t  CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);\r
        uint16_t CurrDFPage          = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);\r
        uint16_t CurrDFPageByte      = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);\r
        uint8_t  CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);\r
+       bool     UsingSecondBuffer   = false;\r
 \r
        /* Copy selected dataflash's current page contents to the dataflash buffer */\r
        Dataflash_SelectChipFromPage(CurrDFPage);\r
 \r
        /* Copy selected dataflash's current page contents to the dataflash buffer */\r
        Dataflash_SelectChipFromPage(CurrDFPage);\r
+#if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)\r
        Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);\r
        Dataflash_SendAddressBytes(CurrDFPage, 0);\r
        Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);\r
        Dataflash_SendAddressBytes(CurrDFPage, 0);\r
+#endif\r
        Dataflash_WaitWhileBusy();\r
 \r
        /* Send the dataflash buffer write command */\r
        Dataflash_WaitWhileBusy();\r
 \r
        /* Send the dataflash buffer write command */\r
@@ -88,34 +90,36 @@ void DataflashManager_WriteBlocks(USB_ClassInfo_MS_Device_t* MSInterfaceInfo, co
                        if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))\r
                        {\r
                                /* Write the dataflash buffer contents back to the dataflash page */\r
                        if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))\r
                        {\r
                                /* Write the dataflash buffer contents back to the dataflash page */\r
-                               Dataflash_ToggleSelectedChipCS();\r
-                               Dataflash_SendByte(DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
+                               Dataflash_WaitWhileBusy();\r
+                               Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
                                Dataflash_SendAddressBytes(CurrDFPage, 0);\r
 \r
                                /* Reset the dataflash buffer counter, increment the page counter */\r
                                CurrDFPageByteDiv16 = 0;\r
                                CurrDFPage++;\r
 \r
                                Dataflash_SendAddressBytes(CurrDFPage, 0);\r
 \r
                                /* Reset the dataflash buffer counter, increment the page counter */\r
                                CurrDFPageByteDiv16 = 0;\r
                                CurrDFPage++;\r
 \r
+                               /* Once all the dataflash ICs have had their first buffers filled, switch buffers to maintain throughput */\r
+                               if (Dataflash_GetSelectedChip() == DATAFLASH_CHIP_MASK(DATAFLASH_TOTALCHIPS))\r
+                                 UsingSecondBuffer = !(UsingSecondBuffer);\r
+\r
                                /* Select the next dataflash chip based on the new dataflash page index */\r
                                Dataflash_SelectChipFromPage(CurrDFPage);\r
                                /* Select the next dataflash chip based on the new dataflash page index */\r
                                Dataflash_SelectChipFromPage(CurrDFPage);\r
-                               Dataflash_WaitWhileBusy();\r
 \r
 #if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)\r
                                /* If less than one dataflash page remaining, copy over the existing page to preserve trailing data */\r
                                if ((TotalBlocks * (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) < (DATAFLASH_PAGE_SIZE >> 4))\r
                                {\r
                                        /* Copy selected dataflash's current page contents to the dataflash buffer */\r
 \r
 #if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)\r
                                /* If less than one dataflash page remaining, copy over the existing page to preserve trailing data */\r
                                if ((TotalBlocks * (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) < (DATAFLASH_PAGE_SIZE >> 4))\r
                                {\r
                                        /* Copy selected dataflash's current page contents to the dataflash buffer */\r
-                                       Dataflash_ToggleSelectedChipCS();\r
-                                       Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);\r
+                                       Dataflash_WaitWhileBusy();\r
+                                       Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_MAINMEMTOBUFF2 : DF_CMD_MAINMEMTOBUFF1);\r
                                        Dataflash_SendAddressBytes(CurrDFPage, 0);\r
                                        Dataflash_WaitWhileBusy();\r
                                }\r
 #endif\r
 \r
                                /* Send the dataflash buffer write command */\r
                                        Dataflash_SendAddressBytes(CurrDFPage, 0);\r
                                        Dataflash_WaitWhileBusy();\r
                                }\r
 #endif\r
 \r
                                /* Send the dataflash buffer write command */\r
-                               Dataflash_ToggleSelectedChipCS();\r
-                               Dataflash_SendByte(DF_CMD_BUFF1WRITE);\r
-                               Dataflash_SendAddressBytes(0, 0);\r
+                               Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2WRITE : DF_CMD_BUFF1WRITE);\r
+                               Dataflash_SendAddressBytes(0, 0);                               \r
                        }\r
 \r
                        /* Write one 16-byte chunk of data to the dataflash */\r
                        }\r
 \r
                        /* Write one 16-byte chunk of data to the dataflash */\r
@@ -152,8 +156,8 @@ void DataflashManager_WriteBlocks(USB_ClassInfo_MS_Device_t* MSInterfaceInfo, co
        }\r
 \r
        /* Write the dataflash buffer contents back to the dataflash page */\r
        }\r
 \r
        /* Write the dataflash buffer contents back to the dataflash page */\r
-       Dataflash_ToggleSelectedChipCS();\r
-       Dataflash_SendByte(DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
+       Dataflash_WaitWhileBusy();\r
+       Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
        Dataflash_SendAddressBytes(CurrDFPage, 0x00);\r
        Dataflash_WaitWhileBusy();\r
 \r
        Dataflash_SendAddressBytes(CurrDFPage, 0x00);\r
        Dataflash_WaitWhileBusy();\r
 \r
@@ -169,7 +173,6 @@ void DataflashManager_WriteBlocks(USB_ClassInfo_MS_Device_t* MSInterfaceInfo, co
  *  the pre-selected data IN endpoint. This routine reads in Dataflash page sized blocks from the Dataflash\r
  *  and writes them in OS sized blocks to the endpoint.\r
  *\r
  *  the pre-selected data IN endpoint. This routine reads in Dataflash page sized blocks from the Dataflash\r
  *  and writes them in OS sized blocks to the endpoint.\r
  *\r
- *  \param[in] MSInterfaceInfo  Pointer to a Mass Storage class state structure for the Mass Storage interface being used\r
  *  \param[in] BlockAddress  Data block starting address for the read sequence\r
  *  \param[in] TotalBlocks   Number of blocks of data to read\r
  */\r
  *  \param[in] BlockAddress  Data block starting address for the read sequence\r
  *  \param[in] TotalBlocks   Number of blocks of data to read\r
  */\r
@@ -282,11 +285,14 @@ void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress, uint16_t Tota
        uint16_t CurrDFPage          = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);\r
        uint16_t CurrDFPageByte      = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);\r
        uint8_t  CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);\r
        uint16_t CurrDFPage          = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);\r
        uint16_t CurrDFPageByte      = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);\r
        uint8_t  CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);\r
+       bool     UsingSecondBuffer   = false;\r
 \r
        /* Copy selected dataflash's current page contents to the dataflash buffer */\r
        Dataflash_SelectChipFromPage(CurrDFPage);\r
 \r
        /* Copy selected dataflash's current page contents to the dataflash buffer */\r
        Dataflash_SelectChipFromPage(CurrDFPage);\r
+#if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)\r
        Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);\r
        Dataflash_SendAddressBytes(CurrDFPage, 0);\r
        Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);\r
        Dataflash_SendAddressBytes(CurrDFPage, 0);\r
+#endif\r
        Dataflash_WaitWhileBusy();\r
 \r
        /* Send the dataflash buffer write command */\r
        Dataflash_WaitWhileBusy();\r
 \r
        /* Send the dataflash buffer write command */\r
@@ -305,25 +311,28 @@ void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress, uint16_t Tota
                        if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))\r
                        {\r
                                /* Write the dataflash buffer contents back to the dataflash page */\r
                        if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))\r
                        {\r
                                /* Write the dataflash buffer contents back to the dataflash page */\r
-                               Dataflash_ToggleSelectedChipCS();\r
-                               Dataflash_SendByte(DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
+                               Dataflash_WaitWhileBusy();\r
+                               Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
                                Dataflash_SendAddressBytes(CurrDFPage, 0);\r
 \r
                                /* Reset the dataflash buffer counter, increment the page counter */\r
                                CurrDFPageByteDiv16 = 0;\r
                                CurrDFPage++;\r
 \r
                                Dataflash_SendAddressBytes(CurrDFPage, 0);\r
 \r
                                /* Reset the dataflash buffer counter, increment the page counter */\r
                                CurrDFPageByteDiv16 = 0;\r
                                CurrDFPage++;\r
 \r
+                               /* Once all the dataflash ICs have had their first buffers filled, switch buffers to maintain throughput */\r
+                               if (Dataflash_GetSelectedChip() == DATAFLASH_CHIP_MASK(DATAFLASH_TOTALCHIPS))\r
+                                 UsingSecondBuffer = !(UsingSecondBuffer);\r
+\r
                                /* Select the next dataflash chip based on the new dataflash page index */\r
                                Dataflash_SelectChipFromPage(CurrDFPage);\r
                                /* Select the next dataflash chip based on the new dataflash page index */\r
                                Dataflash_SelectChipFromPage(CurrDFPage);\r
-                               Dataflash_WaitWhileBusy();\r
 \r
 #if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)\r
                                /* If less than one dataflash page remaining, copy over the existing page to preserve trailing data */\r
                                if ((TotalBlocks * (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) < (DATAFLASH_PAGE_SIZE >> 4))\r
                                {\r
                                        /* Copy selected dataflash's current page contents to the dataflash buffer */\r
 \r
 #if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)\r
                                /* If less than one dataflash page remaining, copy over the existing page to preserve trailing data */\r
                                if ((TotalBlocks * (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) < (DATAFLASH_PAGE_SIZE >> 4))\r
                                {\r
                                        /* Copy selected dataflash's current page contents to the dataflash buffer */\r
-                                       Dataflash_ToggleSelectedChipCS();\r
-                                       Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);\r
+                                       Dataflash_WaitWhileBusy();\r
+                                       Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_MAINMEMTOBUFF2 : DF_CMD_MAINMEMTOBUFF1);\r
                                        Dataflash_SendAddressBytes(CurrDFPage, 0);\r
                                        Dataflash_WaitWhileBusy();\r
                                }\r
                                        Dataflash_SendAddressBytes(CurrDFPage, 0);\r
                                        Dataflash_WaitWhileBusy();\r
                                }\r
@@ -351,8 +360,8 @@ void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress, uint16_t Tota
        }\r
 \r
        /* Write the dataflash buffer contents back to the dataflash page */\r
        }\r
 \r
        /* Write the dataflash buffer contents back to the dataflash page */\r
-       Dataflash_ToggleSelectedChipCS();\r
-       Dataflash_SendByte(DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
+       Dataflash_WaitWhileBusy();\r
+       Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
        Dataflash_SendAddressBytes(CurrDFPage, 0x00);\r
        Dataflash_WaitWhileBusy();\r
 \r
        Dataflash_SendAddressBytes(CurrDFPage, 0x00);\r
        Dataflash_WaitWhileBusy();\r
 \r
@@ -367,7 +376,7 @@ void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress, uint16_t Tota
  *\r
  *  \param[in] BlockAddress  Data block starting address for the read sequence\r
  *  \param[in] TotalBlocks   Number of blocks of data to read\r
  *\r
  *  \param[in] BlockAddress  Data block starting address for the read sequence\r
  *  \param[in] TotalBlocks   Number of blocks of data to read\r
- *  \param[out] BufferPtr     Pointer to the data destination RAM buffer\r
+ *  \param[out] BufferPtr    Pointer to the data destination RAM buffer\r
  */\r
 void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks, uint8_t* BufferPtr)\r
 {\r
  */\r
 void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks, uint8_t* BufferPtr)\r
 {\r
index c5035fe..6dc5495 100644 (file)
@@ -51,11 +51,14 @@ void DataflashManager_WriteBlocks(const uint32_t BlockAddress, uint16_t TotalBlo
        uint16_t CurrDFPage          = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);\r
        uint16_t CurrDFPageByte      = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);\r
        uint8_t  CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);\r
        uint16_t CurrDFPage          = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);\r
        uint16_t CurrDFPageByte      = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);\r
        uint8_t  CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);\r
+       bool     UsingSecondBuffer   = false;\r
 \r
        /* Copy selected dataflash's current page contents to the dataflash buffer */\r
        Dataflash_SelectChipFromPage(CurrDFPage);\r
 \r
        /* Copy selected dataflash's current page contents to the dataflash buffer */\r
        Dataflash_SelectChipFromPage(CurrDFPage);\r
+#if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)\r
        Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);\r
        Dataflash_SendAddressBytes(CurrDFPage, 0);\r
        Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);\r
        Dataflash_SendAddressBytes(CurrDFPage, 0);\r
+#endif\r
        Dataflash_WaitWhileBusy();\r
 \r
        /* Send the dataflash buffer write command */\r
        Dataflash_WaitWhileBusy();\r
 \r
        /* Send the dataflash buffer write command */\r
@@ -87,34 +90,36 @@ void DataflashManager_WriteBlocks(const uint32_t BlockAddress, uint16_t TotalBlo
                        if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))\r
                        {\r
                                /* Write the dataflash buffer contents back to the dataflash page */\r
                        if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))\r
                        {\r
                                /* Write the dataflash buffer contents back to the dataflash page */\r
-                               Dataflash_ToggleSelectedChipCS();\r
-                               Dataflash_SendByte(DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
+                               Dataflash_WaitWhileBusy();\r
+                               Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
                                Dataflash_SendAddressBytes(CurrDFPage, 0);\r
 \r
                                /* Reset the dataflash buffer counter, increment the page counter */\r
                                CurrDFPageByteDiv16 = 0;\r
                                CurrDFPage++;\r
 \r
                                Dataflash_SendAddressBytes(CurrDFPage, 0);\r
 \r
                                /* Reset the dataflash buffer counter, increment the page counter */\r
                                CurrDFPageByteDiv16 = 0;\r
                                CurrDFPage++;\r
 \r
+                               /* Once all the dataflash ICs have had their first buffers filled, switch buffers to maintain throughput */\r
+                               if (Dataflash_GetSelectedChip() == DATAFLASH_CHIP_MASK(DATAFLASH_TOTALCHIPS))\r
+                                 UsingSecondBuffer = !(UsingSecondBuffer);\r
+\r
                                /* Select the next dataflash chip based on the new dataflash page index */\r
                                Dataflash_SelectChipFromPage(CurrDFPage);\r
                                /* Select the next dataflash chip based on the new dataflash page index */\r
                                Dataflash_SelectChipFromPage(CurrDFPage);\r
-                               Dataflash_WaitWhileBusy();\r
 \r
 #if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)\r
                                /* If less than one dataflash page remaining, copy over the existing page to preserve trailing data */\r
                                if ((TotalBlocks * (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) < (DATAFLASH_PAGE_SIZE >> 4))\r
                                {\r
                                        /* Copy selected dataflash's current page contents to the dataflash buffer */\r
 \r
 #if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)\r
                                /* If less than one dataflash page remaining, copy over the existing page to preserve trailing data */\r
                                if ((TotalBlocks * (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) < (DATAFLASH_PAGE_SIZE >> 4))\r
                                {\r
                                        /* Copy selected dataflash's current page contents to the dataflash buffer */\r
-                                       Dataflash_ToggleSelectedChipCS();\r
-                                       Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);\r
+                                       Dataflash_WaitWhileBusy();\r
+                                       Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_MAINMEMTOBUFF2 : DF_CMD_MAINMEMTOBUFF1);\r
                                        Dataflash_SendAddressBytes(CurrDFPage, 0);\r
                                        Dataflash_WaitWhileBusy();\r
                                }\r
 #endif\r
 \r
                                /* Send the dataflash buffer write command */\r
                                        Dataflash_SendAddressBytes(CurrDFPage, 0);\r
                                        Dataflash_WaitWhileBusy();\r
                                }\r
 #endif\r
 \r
                                /* Send the dataflash buffer write command */\r
-                               Dataflash_ToggleSelectedChipCS();\r
-                               Dataflash_SendByte(DF_CMD_BUFF1WRITE);\r
-                               Dataflash_SendAddressBytes(0, 0);\r
+                               Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2WRITE : DF_CMD_BUFF1WRITE);\r
+                               Dataflash_SendAddressBytes(0, 0);                               \r
                        }\r
 \r
                        /* Write one 16-byte chunk of data to the dataflash */\r
                        }\r
 \r
                        /* Write one 16-byte chunk of data to the dataflash */\r
@@ -151,8 +156,8 @@ void DataflashManager_WriteBlocks(const uint32_t BlockAddress, uint16_t TotalBlo
        }\r
 \r
        /* Write the dataflash buffer contents back to the dataflash page */\r
        }\r
 \r
        /* Write the dataflash buffer contents back to the dataflash page */\r
-       Dataflash_ToggleSelectedChipCS();\r
-       Dataflash_SendByte(DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
+       Dataflash_WaitWhileBusy();\r
+       Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
        Dataflash_SendAddressBytes(CurrDFPage, 0x00);\r
        Dataflash_WaitWhileBusy();\r
 \r
        Dataflash_SendAddressBytes(CurrDFPage, 0x00);\r
        Dataflash_WaitWhileBusy();\r
 \r
@@ -280,11 +285,14 @@ void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress, uint16_t Tota
        uint16_t CurrDFPage          = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);\r
        uint16_t CurrDFPageByte      = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);\r
        uint8_t  CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);\r
        uint16_t CurrDFPage          = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);\r
        uint16_t CurrDFPageByte      = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);\r
        uint8_t  CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);\r
+       bool     UsingSecondBuffer   = false;\r
 \r
        /* Copy selected dataflash's current page contents to the dataflash buffer */\r
        Dataflash_SelectChipFromPage(CurrDFPage);\r
 \r
        /* Copy selected dataflash's current page contents to the dataflash buffer */\r
        Dataflash_SelectChipFromPage(CurrDFPage);\r
+#if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)\r
        Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);\r
        Dataflash_SendAddressBytes(CurrDFPage, 0);\r
        Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);\r
        Dataflash_SendAddressBytes(CurrDFPage, 0);\r
+#endif\r
        Dataflash_WaitWhileBusy();\r
 \r
        /* Send the dataflash buffer write command */\r
        Dataflash_WaitWhileBusy();\r
 \r
        /* Send the dataflash buffer write command */\r
@@ -303,25 +311,28 @@ void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress, uint16_t Tota
                        if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))\r
                        {\r
                                /* Write the dataflash buffer contents back to the dataflash page */\r
                        if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))\r
                        {\r
                                /* Write the dataflash buffer contents back to the dataflash page */\r
-                               Dataflash_ToggleSelectedChipCS();\r
-                               Dataflash_SendByte(DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
+                               Dataflash_WaitWhileBusy();\r
+                               Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
                                Dataflash_SendAddressBytes(CurrDFPage, 0);\r
 \r
                                /* Reset the dataflash buffer counter, increment the page counter */\r
                                CurrDFPageByteDiv16 = 0;\r
                                CurrDFPage++;\r
 \r
                                Dataflash_SendAddressBytes(CurrDFPage, 0);\r
 \r
                                /* Reset the dataflash buffer counter, increment the page counter */\r
                                CurrDFPageByteDiv16 = 0;\r
                                CurrDFPage++;\r
 \r
+                               /* Once all the dataflash ICs have had their first buffers filled, switch buffers to maintain throughput */\r
+                               if (Dataflash_GetSelectedChip() == DATAFLASH_CHIP_MASK(DATAFLASH_TOTALCHIPS))\r
+                                 UsingSecondBuffer = !(UsingSecondBuffer);\r
+\r
                                /* Select the next dataflash chip based on the new dataflash page index */\r
                                Dataflash_SelectChipFromPage(CurrDFPage);\r
                                /* Select the next dataflash chip based on the new dataflash page index */\r
                                Dataflash_SelectChipFromPage(CurrDFPage);\r
-                               Dataflash_WaitWhileBusy();\r
 \r
 #if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)\r
                                /* If less than one dataflash page remaining, copy over the existing page to preserve trailing data */\r
                                if ((TotalBlocks * (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) < (DATAFLASH_PAGE_SIZE >> 4))\r
                                {\r
                                        /* Copy selected dataflash's current page contents to the dataflash buffer */\r
 \r
 #if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)\r
                                /* If less than one dataflash page remaining, copy over the existing page to preserve trailing data */\r
                                if ((TotalBlocks * (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) < (DATAFLASH_PAGE_SIZE >> 4))\r
                                {\r
                                        /* Copy selected dataflash's current page contents to the dataflash buffer */\r
-                                       Dataflash_ToggleSelectedChipCS();\r
-                                       Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);\r
+                                       Dataflash_WaitWhileBusy();\r
+                                       Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_MAINMEMTOBUFF2 : DF_CMD_MAINMEMTOBUFF1);\r
                                        Dataflash_SendAddressBytes(CurrDFPage, 0);\r
                                        Dataflash_WaitWhileBusy();\r
                                }\r
                                        Dataflash_SendAddressBytes(CurrDFPage, 0);\r
                                        Dataflash_WaitWhileBusy();\r
                                }\r
@@ -341,11 +352,7 @@ void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress, uint16_t Tota
                        CurrDFPageByteDiv16++;\r
 \r
                        /* Increment the block 16 byte block counter */\r
                        CurrDFPageByteDiv16++;\r
 \r
                        /* Increment the block 16 byte block counter */\r
-                       BytesInBlockDiv16++;\r
-\r
-                       /* Check if the current command is being aborted by the host */\r
-                       if (IsMassStoreReset)\r
-                         return;                       \r
+                       BytesInBlockDiv16++;            \r
                }\r
                        \r
                /* Decrement the blocks remaining counter and reset the sub block counter */\r
                }\r
                        \r
                /* Decrement the blocks remaining counter and reset the sub block counter */\r
@@ -353,8 +360,8 @@ void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress, uint16_t Tota
        }\r
 \r
        /* Write the dataflash buffer contents back to the dataflash page */\r
        }\r
 \r
        /* Write the dataflash buffer contents back to the dataflash page */\r
-       Dataflash_ToggleSelectedChipCS();\r
-       Dataflash_SendByte(DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
+       Dataflash_WaitWhileBusy();\r
+       Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
        Dataflash_SendAddressBytes(CurrDFPage, 0x00);\r
        Dataflash_WaitWhileBusy();\r
 \r
        Dataflash_SendAddressBytes(CurrDFPage, 0x00);\r
        Dataflash_WaitWhileBusy();\r
 \r
@@ -421,10 +428,6 @@ void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress, uint16_t Total
                        \r
                        /* Increment the block 16 byte block counter */\r
                        BytesInBlockDiv16++;\r
                        \r
                        /* Increment the block 16 byte block counter */\r
                        BytesInBlockDiv16++;\r
-\r
-                       /* Check if the current command is being aborted by the host */\r
-                       if (IsMassStoreReset)\r
-                         return;\r
                }\r
                \r
                /* Decrement the blocks remaining counter */\r
                }\r
                \r
                /* Decrement the blocks remaining counter */\r
index 57ce92d..e58828c 100644 (file)
                #endif\r
 \r
        /* Public Interface - May be used in end-application: */\r
                #endif\r
 \r
        /* Public Interface - May be used in end-application: */\r
+               /* Macros: */\r
+                       #if !defined(__DOXYGEN__)\r
+                               #define __GET_DATAFLASH_MASK2(x, y) x ## y\r
+                               #define __GET_DATAFLASH_MASK(x)     __GET_DATAFLASH_MASK2(DATAFLASH_CHIP,x)\r
+                       #endif\r
+       \r
+                       /* Retrieves the Dataflash chip select mask for the given Dataflash chip index.\r
+                        *\r
+                        * \param index  Index of the dataflash chip mask to retrieve\r
+                        */\r
+                       #define DATAFLASH_CHIP_MASK(index)      __GET_DATAFLASH_MASK(index)\r
+                       \r
                /* Pseudo-Function Macros: */\r
                        #if defined(__DOXYGEN__)\r
                                /** Determines the currently selected dataflash chip.\r
                /* Pseudo-Function Macros: */\r
                        #if defined(__DOXYGEN__)\r
                                /** Determines the currently selected dataflash chip.\r
                        #else\r
                                #error The selected board does not contain a dataflash IC.\r
                        #endif\r
                        #else\r
                                #error The selected board does not contain a dataflash IC.\r
                        #endif\r
-\r
+               \r
                /* Inline Functions: */\r
                        /** Initializes the dataflash driver (including the SPI driver) so that commands and data may be\r
                         *  sent to an attached dataflash IC.\r
                /* Inline Functions: */\r
                        /** Initializes the dataflash driver (including the SPI driver) so that commands and data may be\r
                         *  sent to an attached dataflash IC.\r
                                Dataflash_ToggleSelectedChipCS();\r
                                Dataflash_SendByte(DF_CMD_GETSTATUS);\r
                                while (!(Dataflash_ReceiveByte() & DF_STATUS_READY));\r
                                Dataflash_ToggleSelectedChipCS();\r
                                Dataflash_SendByte(DF_CMD_GETSTATUS);\r
                                while (!(Dataflash_ReceiveByte() & DF_STATUS_READY));\r
+                               Dataflash_ToggleSelectedChipCS();                               \r
                        }\r
 \r
                        /** Selects a dataflash IC from the given page number, which should range from 0 to\r
                        }\r
 \r
                        /** Selects a dataflash IC from the given page number, which should range from 0 to\r
index ea42ddf..519ac81 100644 (file)
   *  - Fixed MassStorage demo not clearing the reset flag when a Mass Storage Reset is issued while not processing a command\r
   *  - Fixed USB_Host_SendControlRequest() not re-suspending the USB bus when initial device ready-wait fails\r
   *  - Fixed USB Pad regulator not being disabled on some AVR models when the USB_OPT_REG_DISABLED option is used\r
   *  - Fixed MassStorage demo not clearing the reset flag when a Mass Storage Reset is issued while not processing a command\r
   *  - Fixed USB_Host_SendControlRequest() not re-suspending the USB bus when initial device ready-wait fails\r
   *  - Fixed USB Pad regulator not being disabled on some AVR models when the USB_OPT_REG_DISABLED option is used\r
+  *  - Dataflash_WaitWhileBusy() now always ensures that the dataflash is ready for the next command immediately after returning,\r
+  *    no need to call Dataflash_ToggleSelectedChipCS() afterwards\r
+  *  - Added new DATAFLASH_CHIP_MASK() macro to the Dataflash driver, which returns the Dataflash select mask for the given chip index\r
+  *  - Updated MassStorage device block write routines to use ping-pong Dataflash buffering to increase throughput by around 30%\r
   *\r
   *\r
   *  \section Sec_ChangeLog090605 Version 090605\r
   *\r
   *\r
   *  \section Sec_ChangeLog090605 Version 090605\r
index 5163ee6..51a4bab 100644 (file)
   *  or post your suggestion as an enhancement request to the project bug tracker.\r
   *\r
   *  <b>Targeted for This Release:</b>\r
   *  or post your suggestion as an enhancement request to the project bug tracker.\r
   *\r
   *  <b>Targeted for This Release:</b>\r
-  *  - Make new host class drivers\r
-  *  - Document new host class drivers\r
-  *  - Convert Host mode demos to class drivers\r
-  *  - Re-enable Host mode Class driver builds after completion\r
-  *  - Add standardized descriptor names to class driver structures, controlled by USE_NONSTANDARD_DESCRIPTOR_NAMES\r
-  *  - Update Host mode Class Driver demo .txt files\r
+  *  - Host Mode Class Drivers\r
+  *     -# Make new host class drivers\r
+  *     -# Document new host class drivers\r
+  *     -# Convert Host mode demos to class drivers\r
+  *     -# Re-enable Host mode Class driver builds after completion\r
+  *     -# Update Host mode Class Driver demo .txt files\r
+  *  - Add standardized descriptor names to device and host class driver structures, controlled by USE_NONSTANDARD_DESCRIPTOR_NAMES\r
   *  - Debug mode for pipe/endpoint calls\r
   *  - Test and document new FAST_STREAM_TRANSFERS compile time option\r
   *\r
   *  <b>Targeted for Future Releases:</b>\r
   *  - Remake AVRStudio project files\r
   *  - Debug mode for pipe/endpoint calls\r
   *  - Test and document new FAST_STREAM_TRANSFERS compile time option\r
   *\r
   *  <b>Targeted for Future Releases:</b>\r
   *  - Remake AVRStudio project files\r
-  *  - Detailed overviews of how each demo works\r
-  *  - Master LUFA include file\r
+  *  - Add detailed overviews of how each demo works\r
+  *  - Master LUFA include file rather than per-module includes\r
   *  - Stream reads - return number of bytes not read?\r
   *  - Add multiple-report HID demo to the library\r
   *  - Add dual role Mouse Host/Keyboard Device demo to the library\r
   *  - Add hub support to match Atmel's stack\r
   *  - Stream reads - return number of bytes not read?\r
   *  - Add multiple-report HID demo to the library\r
   *  - Add dual role Mouse Host/Keyboard Device demo to the library\r
   *  - Add hub support to match Atmel's stack\r
-  *  - Port LUFA to the AVR32 UC3B series microcontrollers\r
-  *  - Port LUFA to the Atmel ARM7 series microcontrollers\r
+  *  - Port LUFA to other architectures\r
+  *      -# AVR32 UC3B series microcontrollers\r
+  *      -# Atmel ARM7 series microcontrollers\r
   */\r
   */\r
index 51679eb..930c2a9 100644 (file)
                                Scheduler_TotalTasks = TotalTasks;\r
                        }\r
                \r
                                Scheduler_TotalTasks = TotalTasks;\r
                        }\r
                \r
-                       static inline void Scheduler_GoSchedule(const uint8_t TotalTasks) ATTR_NO_RETURN ATTR_ALWAYS_INLINE;\r
+                       static inline void Scheduler_GoSchedule(const uint8_t TotalTasks) ATTR_NO_RETURN ATTR_ALWAYS_INLINE ATTR_DEPRECATED;\r
                        static inline void Scheduler_GoSchedule(const uint8_t TotalTasks)\r
                        {\r
                                Scheduler_InitScheduler(TotalTasks);\r
                        static inline void Scheduler_GoSchedule(const uint8_t TotalTasks)\r
                        {\r
                                Scheduler_InitScheduler(TotalTasks);\r