Fix up the incomplete Webserver project so that it integrates with the uIP stack...
[pub/USBasp.git] / Demos / Device / LowLevel / MassStorage / Lib / DataflashManager.c
index c5035fe..4bfe757 100644 (file)
@@ -1,21 +1,21 @@
 /*\r
              LUFA Library\r
-     Copyright (C) Dean Camera, 2009.\r
+     Copyright (C) Dean Camera, 2010.\r
               \r
   dean [at] fourwalledcubicle [dot] com\r
       www.fourwalledcubicle.com\r
 */\r
 \r
 /*\r
-  Copyright 2009  Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
-  Permission to use, copy, modify, and distribute this software\r
-  and its documentation for any purpose and without fee is hereby\r
-  granted, provided that the above copyright notice appear in all\r
-  copies and that both that the copyright notice and this\r
-  permission notice and warranty disclaimer appear in supporting\r
-  documentation, and that the name of the author not be used in\r
-  advertising or publicity pertaining to distribution of the\r
+  Copyright 2010  Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+  Permission to use, copy, modify, distribute, and sell this \r
+  software and its documentation for any purpose is hereby granted\r
+  without fee, provided that the above copyright notice appear in \r
+  all copies and that both that the copyright notice and this\r
+  permission notice and warranty disclaimer appear in supporting \r
+  documentation, and that the name of the author not be used in \r
+  advertising or publicity pertaining to distribution of the \r
   software without specific, written prior permission.\r
 \r
   The author disclaim all warranties with regard to this\r
@@ -51,21 +51,26 @@ 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
+       bool     UsingSecondBuffer   = false;\r
 \r
-       /* Copy selected dataflash's current page contents to the dataflash buffer */\r
+       /* Select the correct starting Dataflash IC for the block requested */\r
        Dataflash_SelectChipFromPage(CurrDFPage);\r
+\r
+#if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)\r
+       /* Copy selected dataflash's current page contents to the dataflash buffer */\r
        Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);\r
        Dataflash_SendAddressBytes(CurrDFPage, 0);\r
        Dataflash_WaitWhileBusy();\r
+#endif\r
 \r
        /* Send the dataflash buffer write command */\r
-       Dataflash_ToggleSelectedChipCS();\r
        Dataflash_SendByte(DF_CMD_BUFF1WRITE);\r
        Dataflash_SendAddressBytes(0, CurrDFPageByte);\r
 \r
        /* Wait until endpoint is ready before continuing */\r
-       while (!(Endpoint_IsReadWriteAllowed()));\r
-\r
+       if (Endpoint_WaitUntilReady())\r
+         return;\r
+       \r
        while (TotalBlocks)\r
        {\r
                uint8_t BytesInBlockDiv16 = 0;\r
@@ -80,41 +85,44 @@ void DataflashManager_WriteBlocks(const uint32_t BlockAddress, uint16_t TotalBlo
                                Endpoint_ClearOUT();\r
                                \r
                                /* Wait until the host has sent another packet */\r
-                               while (!(Endpoint_IsReadWriteAllowed()));\r
+                               if (Endpoint_WaitUntilReady())\r
+                                 return;\r
                        }\r
 \r
                        /* Check if end of dataflash page reached */\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
+                               /* 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
-                               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
-                                       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_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
@@ -151,8 +159,8 @@ void DataflashManager_WriteBlocks(const uint32_t BlockAddress, uint16_t TotalBlo
        }\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
@@ -177,8 +185,10 @@ void DataflashManager_ReadBlocks(const uint32_t BlockAddress, uint16_t TotalBloc
        uint16_t CurrDFPageByte      = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);\r
        uint8_t  CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);\r
 \r
-       /* Send the dataflash main memory page read command */\r
+       /* Select the correct starting Dataflash IC for the block requested */\r
        Dataflash_SelectChipFromPage(CurrDFPage);\r
+\r
+       /* Send the dataflash main memory page read command */\r
        Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);\r
        Dataflash_SendAddressBytes(CurrDFPage, CurrDFPageByte);\r
        Dataflash_SendByte(0x00);\r
@@ -187,7 +197,8 @@ void DataflashManager_ReadBlocks(const uint32_t BlockAddress, uint16_t TotalBloc
        Dataflash_SendByte(0x00);\r
        \r
        /* Wait until endpoint is ready before continuing */\r
-       while (!(Endpoint_IsReadWriteAllowed()));\r
+       if (Endpoint_WaitUntilReady())\r
+         return;\r
        \r
        while (TotalBlocks)\r
        {\r
@@ -203,7 +214,8 @@ void DataflashManager_ReadBlocks(const uint32_t BlockAddress, uint16_t TotalBloc
                                Endpoint_ClearIN();\r
                                \r
                                /* Wait until the endpoint is ready for more data */\r
-                               while (!(Endpoint_IsReadWriteAllowed()));\r
+                               if (Endpoint_WaitUntilReady())\r
+                                 return;\r
                        }\r
                        \r
                        /* Check if end of dataflash page reached */\r
@@ -280,15 +292,19 @@ 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
+       bool     UsingSecondBuffer   = false;\r
 \r
-       /* Copy selected dataflash's current page contents to the dataflash buffer */\r
+       /* Select the correct starting Dataflash IC for the block requested */\r
        Dataflash_SelectChipFromPage(CurrDFPage);\r
+\r
+#if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)\r
+       /* Copy selected dataflash's current page contents to the dataflash buffer */\r
        Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);\r
        Dataflash_SendAddressBytes(CurrDFPage, 0);\r
        Dataflash_WaitWhileBusy();\r
+#endif\r
 \r
        /* Send the dataflash buffer write command */\r
-       Dataflash_ToggleSelectedChipCS();\r
        Dataflash_SendByte(DF_CMD_BUFF1WRITE);\r
        Dataflash_SendAddressBytes(0, CurrDFPageByte);\r
 \r
@@ -303,25 +319,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
-                               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
+                               /* 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
-                               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
-                                       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
@@ -341,11 +360,7 @@ void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress, uint16_t Tota
                        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
@@ -353,8 +368,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
-       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
@@ -377,8 +392,10 @@ void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress, uint16_t Total
        uint16_t CurrDFPageByte      = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);\r
        uint8_t  CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);\r
 \r
-       /* Send the dataflash main memory page read command */\r
+       /* Select the correct starting Dataflash IC for the block requested */\r
        Dataflash_SelectChipFromPage(CurrDFPage);\r
+\r
+       /* Send the dataflash main memory page read command */\r
        Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);\r
        Dataflash_SendAddressBytes(CurrDFPage, CurrDFPageByte);\r
        Dataflash_SendByte(0x00);\r
@@ -421,10 +438,6 @@ void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress, uint16_t Total
                        \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
@@ -475,3 +488,36 @@ void DataflashManager_ResetDataflashProtections(void)
        /* Deselect current dataflash chip */\r
        Dataflash_DeselectChip();\r
 }\r
+\r
+/** Performs a simple test on the attached Dataflash IC(s) to ensure that they are working.\r
+ *\r
+ *  \return Boolean true if all media chips are working, false otherwise\r
+ */\r
+bool DataflashManager_CheckDataflashOperation(void)\r
+{\r
+       uint8_t ReturnByte;\r
+\r
+       /* Test first Dataflash IC is present and responding to commands */\r
+       Dataflash_SelectChip(DATAFLASH_CHIP1);\r
+       Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO);\r
+       ReturnByte = Dataflash_ReceiveByte();\r
+       Dataflash_DeselectChip();\r
+\r
+       /* If returned data is invalid, fail the command */\r
+       if (ReturnByte != DF_MANUFACTURER_ATMEL)\r
+         return false;\r
+\r
+       #if (DATAFLASH_TOTALCHIPS == 2)\r
+       /* Test second Dataflash IC is present and responding to commands */\r
+       Dataflash_SelectChip(DATAFLASH_CHIP2);\r
+       Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO);\r
+       ReturnByte = Dataflash_ReceiveByte();\r
+       Dataflash_DeselectChip();\r
+\r
+       /* If returned data is invalid, fail the command */\r
+       if (ReturnByte != DF_MANUFACTURER_ATMEL)\r
+         return false;\r
+       #endif\r
+       \r
+       return true;\r
+}\r