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%.
* 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
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
Dataflash_WaitWhileBusy();\r
\r
/* Send the dataflash buffer write command */\r
Dataflash_WaitWhileBusy();\r
\r
/* Send the dataflash buffer write command */\r
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
}\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
* 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
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
Dataflash_WaitWhileBusy();\r
\r
/* Send the dataflash buffer write command */\r
Dataflash_WaitWhileBusy();\r
\r
/* Send the dataflash buffer write command */\r
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
}\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
*\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
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
Dataflash_WaitWhileBusy();\r
\r
/* Send the dataflash buffer write command */\r
Dataflash_WaitWhileBusy();\r
\r
/* Send the dataflash buffer write command */\r
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
}\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
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
Dataflash_WaitWhileBusy();\r
\r
/* Send the dataflash buffer write command */\r
Dataflash_WaitWhileBusy();\r
\r
/* Send the dataflash buffer write command */\r
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
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
}\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
\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
#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
/* 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
* - 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
* 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
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