* 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 MSInterfaceInfo Pointer to a Mass Storage class state structure for the Mass Storage interface being used\r
- * \param BlockAddress Data block starting address for the write sequence\r
- * \param TotalBlocks Number of blocks of data to write\r
+ * \param[in] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state\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
-void DataflashManager_WriteBlocks(USB_ClassInfo_MS_t* MSInterfaceInfo, const uint32_t BlockAddress, uint16_t TotalBlocks)\r
+void DataflashManager_WriteBlocks(USB_ClassInfo_MS_Device_t* MSInterfaceInfo, const uint32_t BlockAddress, uint16_t TotalBlocks)\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
+ 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
+ if (Endpoint_WaitUntilReady())\r
+ return;\r
\r
while (TotalBlocks)\r
{\r
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
BytesInBlockDiv16++;\r
\r
/* Check if the current command is being aborted by the host */\r
- if (MSInterfaceInfo->IsMassStoreReset)\r
+ if (MSInterfaceInfo->State.IsMassStoreReset)\r
return; \r
}\r
\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
* 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 MSInterfaceInfo Pointer to a Mass Storage class state structure for the Mass Storage interface being used\r
- * \param BlockAddress Data block starting address for the read sequence\r
- * \param TotalBlocks Number of blocks of data to read\r
+ * \param[in] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state\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
-void DataflashManager_ReadBlocks(USB_ClassInfo_MS_t* MSInterfaceInfo, const uint32_t BlockAddress, uint16_t TotalBlocks)\r
+void DataflashManager_ReadBlocks(USB_ClassInfo_MS_Device_t* MSInterfaceInfo, const uint32_t BlockAddress, uint16_t TotalBlocks)\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
\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
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
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
BytesInBlockDiv16++;\r
\r
/* Check if the current command is being aborted by the host */\r
- if (MSInterfaceInfo->IsMassStoreReset)\r
+ if (MSInterfaceInfo->State.IsMassStoreReset)\r
return;\r
}\r
\r
* dataflash in Dataflash page sized blocks. This can be linked to FAT libraries to write files to the\r
* dataflash.\r
*\r
- * \param BlockAddress Data block starting address for the write sequence\r
- * \param TotalBlocks Number of blocks of data to write\r
- * \param BufferPtr Pointer to the data source RAM buffer\r
+ * \param[in] BlockAddress Data block starting address for the write sequence\r
+ * \param[in] TotalBlocks Number of blocks of data to write\r
+ * \param[in] BufferPtr Pointer to the data source RAM buffer\r
*/\r
void DataflashManager_WriteBlocks_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
+ 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
+ \r
while (TotalBlocks)\r
{\r
uint8_t BytesInBlockDiv16 = 0;\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
}\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
* and writes them in OS sized blocks to the given buffer. This can be linked to FAT libraries to read\r
* the files stored on the dataflash.\r
*\r
- * \param BlockAddress Data block starting address for the read sequence\r
- * \param TotalBlocks Number of blocks of data to read\r
- * \param BufferPtr Pointer to the data destination RAM buffer\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
*/\r
void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks, uint8_t* BufferPtr)\r
{\r
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
/* 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