diff options
| author | Dean Camera <dean@fourwalledcubicle.com> | 2010-05-08 03:12:14 +0000 | 
|---|---|---|
| committer | Dean Camera <dean@fourwalledcubicle.com> | 2010-05-08 03:12:14 +0000 | 
| commit | 071e02c6b6b4837fa9cf0b6d4c749994e02638d7 (patch) | |
| tree | 960446788703b69f0bb285450be80c5b3d8cc22c /Demos/Device/ClassDriver/MassStorageKeyboard/Lib/DataflashManager.c | |
| parent | e331b531c6e6d93eb0eee42b9002074e8090ad18 (diff) | |
| download | lufa-071e02c6b6b4837fa9cf0b6d4c749994e02638d7.tar.gz lufa-071e02c6b6b4837fa9cf0b6d4c749994e02638d7.tar.bz2 lufa-071e02c6b6b4837fa9cf0b6d4c749994e02638d7.zip  | |
Add svn:eol-style property to source files, so that the line endings are correctly converted to the target system's native end of line style.
Diffstat (limited to 'Demos/Device/ClassDriver/MassStorageKeyboard/Lib/DataflashManager.c')
| -rw-r--r-- | Demos/Device/ClassDriver/MassStorageKeyboard/Lib/DataflashManager.c | 984 | 
1 files changed, 492 insertions, 492 deletions
diff --git a/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/DataflashManager.c b/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/DataflashManager.c index 73b2191a3..89c426bf8 100644 --- a/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/DataflashManager.c +++ b/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/DataflashManager.c @@ -1,492 +1,492 @@ -/*
 -             LUFA Library
 -     Copyright (C) Dean Camera, 2010.
 -              
 -  dean [at] fourwalledcubicle [dot] com
 -      www.fourwalledcubicle.com
 -*/
 -
 -/*
 -  Copyright 2010  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 disclaim 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* 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_Byte());
 -			Dataflash_SendByte(Endpoint_Read_Byte());
 -			Dataflash_SendByte(Endpoint_Read_Byte());
 -			Dataflash_SendByte(Endpoint_Read_Byte());
 -			Dataflash_SendByte(Endpoint_Read_Byte());
 -			Dataflash_SendByte(Endpoint_Read_Byte());
 -			Dataflash_SendByte(Endpoint_Read_Byte());
 -			Dataflash_SendByte(Endpoint_Read_Byte());
 -			Dataflash_SendByte(Endpoint_Read_Byte());
 -			Dataflash_SendByte(Endpoint_Read_Byte());
 -			Dataflash_SendByte(Endpoint_Read_Byte());
 -			Dataflash_SendByte(Endpoint_Read_Byte());
 -			Dataflash_SendByte(Endpoint_Read_Byte());
 -			Dataflash_SendByte(Endpoint_Read_Byte());
 -			Dataflash_SendByte(Endpoint_Read_Byte());
 -			Dataflash_SendByte(Endpoint_Read_Byte());
 -			
 -			/* 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 and reset the sub block 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* 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;
 -		
 -		/* Write an endpoint packet sized data block to 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_Byte(Dataflash_ReceiveByte());
 -			Endpoint_Write_Byte(Dataflash_ReceiveByte());
 -			Endpoint_Write_Byte(Dataflash_ReceiveByte());
 -			Endpoint_Write_Byte(Dataflash_ReceiveByte());
 -			Endpoint_Write_Byte(Dataflash_ReceiveByte());
 -			Endpoint_Write_Byte(Dataflash_ReceiveByte());
 -			Endpoint_Write_Byte(Dataflash_ReceiveByte());
 -			Endpoint_Write_Byte(Dataflash_ReceiveByte());
 -			Endpoint_Write_Byte(Dataflash_ReceiveByte());
 -			Endpoint_Write_Byte(Dataflash_ReceiveByte());
 -			Endpoint_Write_Byte(Dataflash_ReceiveByte());
 -			Endpoint_Write_Byte(Dataflash_ReceiveByte());
 -			Endpoint_Write_Byte(Dataflash_ReceiveByte());
 -			Endpoint_Write_Byte(Dataflash_ReceiveByte());
 -			Endpoint_Write_Byte(Dataflash_ReceiveByte());
 -			Endpoint_Write_Byte(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 a 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(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 and reset the sub block 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 a 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;
 -		
 -		/* 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))
 -			{
 -				/* 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();
 -}
 +/* +             LUFA Library +     Copyright (C) Dean Camera, 2010. +               +  dean [at] fourwalledcubicle [dot] com +      www.fourwalledcubicle.com +*/ + +/* +  Copyright 2010  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 disclaim 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* 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_Byte()); +			Dataflash_SendByte(Endpoint_Read_Byte()); +			Dataflash_SendByte(Endpoint_Read_Byte()); +			Dataflash_SendByte(Endpoint_Read_Byte()); +			Dataflash_SendByte(Endpoint_Read_Byte()); +			Dataflash_SendByte(Endpoint_Read_Byte()); +			Dataflash_SendByte(Endpoint_Read_Byte()); +			Dataflash_SendByte(Endpoint_Read_Byte()); +			Dataflash_SendByte(Endpoint_Read_Byte()); +			Dataflash_SendByte(Endpoint_Read_Byte()); +			Dataflash_SendByte(Endpoint_Read_Byte()); +			Dataflash_SendByte(Endpoint_Read_Byte()); +			Dataflash_SendByte(Endpoint_Read_Byte()); +			Dataflash_SendByte(Endpoint_Read_Byte()); +			Dataflash_SendByte(Endpoint_Read_Byte()); +			Dataflash_SendByte(Endpoint_Read_Byte()); +			 +			/* 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 and reset the sub block 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* 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; +		 +		/* Write an endpoint packet sized data block to 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_Byte(Dataflash_ReceiveByte()); +			Endpoint_Write_Byte(Dataflash_ReceiveByte()); +			Endpoint_Write_Byte(Dataflash_ReceiveByte()); +			Endpoint_Write_Byte(Dataflash_ReceiveByte()); +			Endpoint_Write_Byte(Dataflash_ReceiveByte()); +			Endpoint_Write_Byte(Dataflash_ReceiveByte()); +			Endpoint_Write_Byte(Dataflash_ReceiveByte()); +			Endpoint_Write_Byte(Dataflash_ReceiveByte()); +			Endpoint_Write_Byte(Dataflash_ReceiveByte()); +			Endpoint_Write_Byte(Dataflash_ReceiveByte()); +			Endpoint_Write_Byte(Dataflash_ReceiveByte()); +			Endpoint_Write_Byte(Dataflash_ReceiveByte()); +			Endpoint_Write_Byte(Dataflash_ReceiveByte()); +			Endpoint_Write_Byte(Dataflash_ReceiveByte()); +			Endpoint_Write_Byte(Dataflash_ReceiveByte()); +			Endpoint_Write_Byte(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 a 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(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 and reset the sub block 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 a 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; +		 +		/* 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)) +			{ +				/* 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(); +}  | 
