mirror of
				https://github.com/mfulz/qmk_firmware.git
				synced 2025-11-04 07:12:33 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			535 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			535 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
             LUFA Library
 | 
						|
     Copyright (C) Dean Camera, 2013.
 | 
						|
 | 
						|
  dean [at] fourwalledcubicle [dot] com
 | 
						|
           www.lufa-lib.org
 | 
						|
*/
 | 
						|
 | 
						|
/*
 | 
						|
  Copyright 2013  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;
 | 
						|
 | 
						|
		/* 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_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;
 | 
						|
 | 
						|
		/* 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();
 | 
						|
}
 | 
						|
 | 
						|
/** Performs a simple test on the attached Dataflash IC(s) to ensure that they are working.
 | 
						|
 *
 | 
						|
 *  \return Boolean true if all media chips are working, 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;
 | 
						|
}
 | 
						|
 |