diff options
Diffstat (limited to 'Demos/Device/ClassDriver/VirtualSerialMassStorage/Lib/DataflashManager.c')
| -rw-r--r-- | Demos/Device/ClassDriver/VirtualSerialMassStorage/Lib/DataflashManager.c | 534 | 
1 files changed, 534 insertions, 0 deletions
| diff --git a/Demos/Device/ClassDriver/VirtualSerialMassStorage/Lib/DataflashManager.c b/Demos/Device/ClassDriver/VirtualSerialMassStorage/Lib/DataflashManager.c new file mode 100644 index 0000000000..c0fd16ccc4 --- /dev/null +++ b/Demos/Device/ClassDriver/VirtualSerialMassStorage/Lib/DataflashManager.c @@ -0,0 +1,534 @@ +/* +             LUFA Library +     Copyright (C) Dean Camera, 2017. + +  dean [at] fourwalledcubicle [dot] com +           www.lufa-lib.org +*/ + +/* +  Copyright 2017  Dean Camera (dean [at] fourwalledcubicle [dot] com) + +  Permission to use, copy, modify, distribute, and sell this +  software and its documentation for any purpose is hereby granted +  without fee, provided that the above copyright notice appear in +  all copies and that both that the copyright notice and this +  permission notice and warranty disclaimer appear in supporting +  documentation, and that the name of the author not be used in +  advertising or publicity pertaining to distribution of the +  software without specific, written prior permission. + +  The author disclaims all warranties with regard to this +  software, including all implied warranties of merchantability +  and fitness.  In no event shall the author be liable for any +  special, indirect or consequential damages or any damages +  whatsoever resulting from loss of use, data or profits, whether +  in an action of contract, negligence or other tortious action, +  arising out of or in connection with the use or performance of +  this software. +*/ + +/** \file + * + *  Functions to manage the physical Dataflash media, including reading and writing of + *  blocks of data. These functions are called by the SCSI layer when data must be stored + *  or retrieved to/from the physical storage media. If a different media is used (such + *  as a SD card or EEPROM), functions similar to these will need to be generated. + */ + +#define  INCLUDE_FROM_DATAFLASHMANAGER_C +#include "DataflashManager.h" + +/** Writes blocks (OS blocks, not Dataflash pages) to the storage medium, the board Dataflash IC(s), from + *  the pre-selected data OUT endpoint. This routine reads in OS sized blocks from the endpoint and writes + *  them to the Dataflash in Dataflash page sized blocks. + * + *  \param[in] MSInterfaceInfo  Pointer to a structure containing a Mass Storage Class configuration and state + *  \param[in] BlockAddress  Data block starting address for the write sequence + *  \param[in] TotalBlocks   Number of blocks of data to write + */ +void DataflashManager_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, +                                  const uint32_t BlockAddress, +                                  uint16_t TotalBlocks) +{ +	uint16_t CurrDFPage          = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE); +	uint16_t CurrDFPageByte      = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE); +	uint8_t  CurrDFPageByteDiv16 = (CurrDFPageByte >> 4); +	bool     UsingSecondBuffer   = false; + +	/* Select the correct starting Dataflash IC for the block requested */ +	Dataflash_SelectChipFromPage(CurrDFPage); + +#if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE) +	/* Copy selected dataflash's current page contents to the Dataflash buffer */ +	Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1); +	Dataflash_SendAddressBytes(CurrDFPage, 0); +	Dataflash_WaitWhileBusy(); +#endif + +	/* Send the Dataflash buffer write command */ +	Dataflash_SendByte(DF_CMD_BUFF1WRITE); +	Dataflash_SendAddressBytes(0, CurrDFPageByte); + +	/* Wait until endpoint is ready before continuing */ +	if (Endpoint_WaitUntilReady()) +	  return; + +	while (TotalBlocks) +	{ +		uint8_t BytesInBlockDiv16 = 0; + +		/* Write an endpoint packet sized data block to the Dataflash */ +		while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) +		{ +			/* Check if the endpoint is currently empty */ +			if (!(Endpoint_IsReadWriteAllowed())) +			{ +				/* Clear the current endpoint bank */ +				Endpoint_ClearOUT(); + +				/* Wait until the host has sent another packet */ +				if (Endpoint_WaitUntilReady()) +				  return; +			} + +			/* Check if end of Dataflash page reached */ +			if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4)) +			{ +				/* Write the Dataflash buffer contents back to the Dataflash page */ +				Dataflash_WaitWhileBusy(); +				Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE); +				Dataflash_SendAddressBytes(CurrDFPage, 0); + +				/* Reset the Dataflash buffer counter, increment the page counter */ +				CurrDFPageByteDiv16 = 0; +				CurrDFPage++; + +				/* Once all the Dataflash ICs have had their first buffers filled, switch buffers to maintain throughput */ +				if (Dataflash_GetSelectedChip() == DATAFLASH_CHIP_MASK(DATAFLASH_TOTALCHIPS)) +				  UsingSecondBuffer = !(UsingSecondBuffer); + +				/* Select the next Dataflash chip based on the new Dataflash page index */ +				Dataflash_SelectChipFromPage(CurrDFPage); + +#if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE) +				/* If less than one Dataflash page remaining, copy over the existing page to preserve trailing data */ +				if ((TotalBlocks * (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) < (DATAFLASH_PAGE_SIZE >> 4)) +				{ +					/* Copy selected dataflash's current page contents to the Dataflash buffer */ +					Dataflash_WaitWhileBusy(); +					Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_MAINMEMTOBUFF2 : DF_CMD_MAINMEMTOBUFF1); +					Dataflash_SendAddressBytes(CurrDFPage, 0); +					Dataflash_WaitWhileBusy(); +				} +#endif + +				/* Send the Dataflash buffer write command */ +				Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2WRITE : DF_CMD_BUFF1WRITE); +				Dataflash_SendAddressBytes(0, 0); +			} + +			/* Write one 16-byte chunk of data to the Dataflash */ +			Dataflash_SendByte(Endpoint_Read_8()); +			Dataflash_SendByte(Endpoint_Read_8()); +			Dataflash_SendByte(Endpoint_Read_8()); +			Dataflash_SendByte(Endpoint_Read_8()); +			Dataflash_SendByte(Endpoint_Read_8()); +			Dataflash_SendByte(Endpoint_Read_8()); +			Dataflash_SendByte(Endpoint_Read_8()); +			Dataflash_SendByte(Endpoint_Read_8()); +			Dataflash_SendByte(Endpoint_Read_8()); +			Dataflash_SendByte(Endpoint_Read_8()); +			Dataflash_SendByte(Endpoint_Read_8()); +			Dataflash_SendByte(Endpoint_Read_8()); +			Dataflash_SendByte(Endpoint_Read_8()); +			Dataflash_SendByte(Endpoint_Read_8()); +			Dataflash_SendByte(Endpoint_Read_8()); +			Dataflash_SendByte(Endpoint_Read_8()); + +			/* Increment the Dataflash page 16 byte block counter */ +			CurrDFPageByteDiv16++; + +			/* Increment the block 16 byte block counter */ +			BytesInBlockDiv16++; + +			/* Check if the current command is being aborted by the host */ +			if (MSInterfaceInfo->State.IsMassStoreReset) +			  return; +		} + +		/* Decrement the blocks remaining counter */ +		TotalBlocks--; +	} + +	/* Write the Dataflash buffer contents back to the Dataflash page */ +	Dataflash_WaitWhileBusy(); +	Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE); +	Dataflash_SendAddressBytes(CurrDFPage, 0x00); +	Dataflash_WaitWhileBusy(); + +	/* If the endpoint is empty, clear it ready for the next packet from the host */ +	if (!(Endpoint_IsReadWriteAllowed())) +	  Endpoint_ClearOUT(); + +	/* Deselect all Dataflash chips */ +	Dataflash_DeselectChip(); +} + +/** Reads blocks (OS blocks, not Dataflash pages) from the storage medium, the board Dataflash IC(s), into + *  the pre-selected data IN endpoint. This routine reads in Dataflash page sized blocks from the Dataflash + *  and writes them in OS sized blocks to the endpoint. + * + *  \param[in] MSInterfaceInfo  Pointer to a structure containing a Mass Storage Class configuration and state + *  \param[in] BlockAddress  Data block starting address for the read sequence + *  \param[in] TotalBlocks   Number of blocks of data to read + */ +void DataflashManager_ReadBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, +                                 const uint32_t BlockAddress, +                                 uint16_t TotalBlocks) +{ +	uint16_t CurrDFPage          = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE); +	uint16_t CurrDFPageByte      = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE); +	uint8_t  CurrDFPageByteDiv16 = (CurrDFPageByte >> 4); + +	/* Select the correct starting Dataflash IC for the block requested */ +	Dataflash_SelectChipFromPage(CurrDFPage); + +	/* Send the Dataflash main memory page read command */ +	Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD); +	Dataflash_SendAddressBytes(CurrDFPage, CurrDFPageByte); +	Dataflash_SendByte(0x00); +	Dataflash_SendByte(0x00); +	Dataflash_SendByte(0x00); +	Dataflash_SendByte(0x00); + +	/* Wait until endpoint is ready before continuing */ +	if (Endpoint_WaitUntilReady()) +	  return; + +	while (TotalBlocks) +	{ +		uint8_t BytesInBlockDiv16 = 0; + +		/* Read an endpoint packet sized data block from the Dataflash */ +		while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) +		{ +			/* Check if the endpoint is currently full */ +			if (!(Endpoint_IsReadWriteAllowed())) +			{ +				/* Clear the endpoint bank to send its contents to the host */ +				Endpoint_ClearIN(); + +				/* Wait until the endpoint is ready for more data */ +				if (Endpoint_WaitUntilReady()) +				  return; +			} + +			/* Check if end of Dataflash page reached */ +			if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4)) +			{ +				/* Reset the Dataflash buffer counter, increment the page counter */ +				CurrDFPageByteDiv16 = 0; +				CurrDFPage++; + +				/* Select the next Dataflash chip based on the new Dataflash page index */ +				Dataflash_SelectChipFromPage(CurrDFPage); + +				/* Send the Dataflash main memory page read command */ +				Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD); +				Dataflash_SendAddressBytes(CurrDFPage, 0); +				Dataflash_SendByte(0x00); +				Dataflash_SendByte(0x00); +				Dataflash_SendByte(0x00); +				Dataflash_SendByte(0x00); +			} + +			/* Read one 16-byte chunk of data from the Dataflash */ +			Endpoint_Write_8(Dataflash_ReceiveByte()); +			Endpoint_Write_8(Dataflash_ReceiveByte()); +			Endpoint_Write_8(Dataflash_ReceiveByte()); +			Endpoint_Write_8(Dataflash_ReceiveByte()); +			Endpoint_Write_8(Dataflash_ReceiveByte()); +			Endpoint_Write_8(Dataflash_ReceiveByte()); +			Endpoint_Write_8(Dataflash_ReceiveByte()); +			Endpoint_Write_8(Dataflash_ReceiveByte()); +			Endpoint_Write_8(Dataflash_ReceiveByte()); +			Endpoint_Write_8(Dataflash_ReceiveByte()); +			Endpoint_Write_8(Dataflash_ReceiveByte()); +			Endpoint_Write_8(Dataflash_ReceiveByte()); +			Endpoint_Write_8(Dataflash_ReceiveByte()); +			Endpoint_Write_8(Dataflash_ReceiveByte()); +			Endpoint_Write_8(Dataflash_ReceiveByte()); +			Endpoint_Write_8(Dataflash_ReceiveByte()); + +			/* Increment the Dataflash page 16 byte block counter */ +			CurrDFPageByteDiv16++; + +			/* Increment the block 16 byte block counter */ +			BytesInBlockDiv16++; + +			/* Check if the current command is being aborted by the host */ +			if (MSInterfaceInfo->State.IsMassStoreReset) +			  return; +		} + +		/* Decrement the blocks remaining counter */ +		TotalBlocks--; +	} + +	/* If the endpoint is full, send its contents to the host */ +	if (!(Endpoint_IsReadWriteAllowed())) +	  Endpoint_ClearIN(); + +	/* Deselect all Dataflash chips */ +	Dataflash_DeselectChip(); +} + +/** Writes blocks (OS blocks, not Dataflash pages) to the storage medium, the board Dataflash IC(s), from + *  the given RAM buffer. This routine reads in OS sized blocks from the buffer and writes them to the + *  Dataflash in Dataflash page sized blocks. This can be linked to FAT libraries to write files to the + *  Dataflash. + * + *  \param[in] BlockAddress  Data block starting address for the write sequence + *  \param[in] TotalBlocks   Number of blocks of data to write + *  \param[in] BufferPtr     Pointer to the data source RAM buffer + */ +void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress, +                                      uint16_t TotalBlocks, +                                      uint8_t* BufferPtr) +{ +	uint16_t CurrDFPage          = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE); +	uint16_t CurrDFPageByte      = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE); +	uint8_t  CurrDFPageByteDiv16 = (CurrDFPageByte >> 4); +	bool     UsingSecondBuffer   = false; + +	/* Select the correct starting Dataflash IC for the block requested */ +	Dataflash_SelectChipFromPage(CurrDFPage); + +#if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE) +	/* Copy selected dataflash's current page contents to the Dataflash buffer */ +	Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1); +	Dataflash_SendAddressBytes(CurrDFPage, 0); +	Dataflash_WaitWhileBusy(); +#endif + +	/* Send the Dataflash buffer write command */ +	Dataflash_SendByte(DF_CMD_BUFF1WRITE); +	Dataflash_SendAddressBytes(0, CurrDFPageByte); + +	while (TotalBlocks) +	{ +		uint8_t BytesInBlockDiv16 = 0; + +		/* Write an endpoint packet sized data block to the Dataflash */ +		while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) +		{ +			/* Check if end of Dataflash page reached */ +			if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4)) +			{ +				/* Write the Dataflash buffer contents back to the Dataflash page */ +				Dataflash_WaitWhileBusy(); +				Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE); +				Dataflash_SendAddressBytes(CurrDFPage, 0); + +				/* Reset the Dataflash buffer counter, increment the page counter */ +				CurrDFPageByteDiv16 = 0; +				CurrDFPage++; + +				/* Once all the Dataflash ICs have had their first buffers filled, switch buffers to maintain throughput */ +				if (Dataflash_GetSelectedChip() == DATAFLASH_CHIP_MASK(DATAFLASH_TOTALCHIPS)) +				  UsingSecondBuffer = !(UsingSecondBuffer); + +				/* Select the next Dataflash chip based on the new Dataflash page index */ +				Dataflash_SelectChipFromPage(CurrDFPage); + +#if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE) +				/* If less than one Dataflash page remaining, copy over the existing page to preserve trailing data */ +				if ((TotalBlocks * (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) < (DATAFLASH_PAGE_SIZE >> 4)) +				{ +					/* Copy selected dataflash's current page contents to the Dataflash buffer */ +					Dataflash_WaitWhileBusy(); +					Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_MAINMEMTOBUFF2 : DF_CMD_MAINMEMTOBUFF1); +					Dataflash_SendAddressBytes(CurrDFPage, 0); +					Dataflash_WaitWhileBusy(); +				} +#endif + +				/* Send the Dataflash buffer write command */ +				Dataflash_ToggleSelectedChipCS(); +				Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2WRITE : DF_CMD_BUFF1WRITE); +				Dataflash_SendAddressBytes(0, 0); +			} + +			/* Write one 16-byte chunk of data to the Dataflash */ +			for (uint8_t ByteNum = 0; ByteNum < 16; ByteNum++) +			  Dataflash_SendByte(*(BufferPtr++)); + +			/* Increment the Dataflash page 16 byte block counter */ +			CurrDFPageByteDiv16++; + +			/* Increment the block 16 byte block counter */ +			BytesInBlockDiv16++; +		} + +		/* Decrement the blocks remaining counter */ +		TotalBlocks--; +	} + +	/* Write the Dataflash buffer contents back to the Dataflash page */ +	Dataflash_WaitWhileBusy(); +	Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE); +	Dataflash_SendAddressBytes(CurrDFPage, 0x00); +	Dataflash_WaitWhileBusy(); + +	/* Deselect all Dataflash chips */ +	Dataflash_DeselectChip(); +} + +/** Reads blocks (OS blocks, not Dataflash pages) from the storage medium, the board Dataflash IC(s), into + *  the preallocated RAM buffer. This routine reads in Dataflash page sized blocks from the Dataflash + *  and writes them in OS sized blocks to the given buffer. This can be linked to FAT libraries to read + *  the files stored on the Dataflash. + * + *  \param[in] BlockAddress  Data block starting address for the read sequence + *  \param[in] TotalBlocks   Number of blocks of data to read + *  \param[out] BufferPtr    Pointer to the data destination RAM buffer + */ +void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress, +                                     uint16_t TotalBlocks, +                                     uint8_t* BufferPtr) +{ +	uint16_t CurrDFPage          = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE); +	uint16_t CurrDFPageByte      = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE); +	uint8_t  CurrDFPageByteDiv16 = (CurrDFPageByte >> 4); + +	/* Select the correct starting Dataflash IC for the block requested */ +	Dataflash_SelectChipFromPage(CurrDFPage); + +	/* Send the Dataflash main memory page read command */ +	Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD); +	Dataflash_SendAddressBytes(CurrDFPage, CurrDFPageByte); +	Dataflash_SendByte(0x00); +	Dataflash_SendByte(0x00); +	Dataflash_SendByte(0x00); +	Dataflash_SendByte(0x00); + +	while (TotalBlocks) +	{ +		uint8_t BytesInBlockDiv16 = 0; + +		/* Read an endpoint packet sized data block from the Dataflash */ +		while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) +		{ +			/* Check if end of Dataflash page reached */ +			if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4)) +			{ +				/* Reset the Dataflash buffer counter, increment the page counter */ +				CurrDFPageByteDiv16 = 0; +				CurrDFPage++; + +				/* Select the next Dataflash chip based on the new Dataflash page index */ +				Dataflash_SelectChipFromPage(CurrDFPage); + +				/* Send the Dataflash main memory page read command */ +				Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD); +				Dataflash_SendAddressBytes(CurrDFPage, 0); +				Dataflash_SendByte(0x00); +				Dataflash_SendByte(0x00); +				Dataflash_SendByte(0x00); +				Dataflash_SendByte(0x00); +			} + +			/* Read one 16-byte chunk of data from the Dataflash */ +			for (uint8_t ByteNum = 0; ByteNum < 16; ByteNum++) +			  *(BufferPtr++) = Dataflash_ReceiveByte(); + +			/* Increment the Dataflash page 16 byte block counter */ +			CurrDFPageByteDiv16++; + +			/* Increment the block 16 byte block counter */ +			BytesInBlockDiv16++; +		} + +		/* Decrement the blocks remaining counter */ +		TotalBlocks--; +	} + +	/* Deselect all Dataflash chips */ +	Dataflash_DeselectChip(); +} + +/** Disables the Dataflash memory write protection bits on the board Dataflash ICs, if enabled. */ +void DataflashManager_ResetDataflashProtections(void) +{ +	/* Select first Dataflash chip, send the read status register command */ +	Dataflash_SelectChip(DATAFLASH_CHIP1); +	Dataflash_SendByte(DF_CMD_GETSTATUS); + +	/* Check if sector protection is enabled */ +	if (Dataflash_ReceiveByte() & DF_STATUS_SECTORPROTECTION_ON) +	{ +		Dataflash_ToggleSelectedChipCS(); + +		/* Send the commands to disable sector protection */ +		Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[0]); +		Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[1]); +		Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[2]); +		Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[3]); +	} + +	/* Select second Dataflash chip (if present on selected board), send read status register command */ +	#if (DATAFLASH_TOTALCHIPS == 2) +	Dataflash_SelectChip(DATAFLASH_CHIP2); +	Dataflash_SendByte(DF_CMD_GETSTATUS); + +	/* Check if sector protection is enabled */ +	if (Dataflash_ReceiveByte() & DF_STATUS_SECTORPROTECTION_ON) +	{ +		Dataflash_ToggleSelectedChipCS(); + +		/* Send the commands to disable sector protection */ +		Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[0]); +		Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[1]); +		Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[2]); +		Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[3]); +	} +	#endif + +	/* Deselect current Dataflash chip */ +	Dataflash_DeselectChip(); +} + +/** Performs a simple test on the attached Dataflash IC(s) to ensure that they are working. + * + *  \return Boolean \c true if all media chips are working, \c false otherwise + */ +bool DataflashManager_CheckDataflashOperation(void) +{ +	uint8_t ReturnByte; + +	/* Test first Dataflash IC is present and responding to commands */ +	Dataflash_SelectChip(DATAFLASH_CHIP1); +	Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO); +	ReturnByte = Dataflash_ReceiveByte(); +	Dataflash_DeselectChip(); + +	/* If returned data is invalid, fail the command */ +	if (ReturnByte != DF_MANUFACTURER_ATMEL) +	  return false; + +	#if (DATAFLASH_TOTALCHIPS == 2) +	/* Test second Dataflash IC is present and responding to commands */ +	Dataflash_SelectChip(DATAFLASH_CHIP2); +	Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO); +	ReturnByte = Dataflash_ReceiveByte(); +	Dataflash_DeselectChip(); + +	/* If returned data is invalid, fail the command */ +	if (ReturnByte != DF_MANUFACTURER_ATMEL) +	  return false; +	#endif + +	return true; +} + | 
