//***************************************************************************** // // COPYRIGHT (c) ATMEL Norway, 1996-2000 // // The copyright to the document(s) herein is the property of // ATMEL Norway, Norway. // // The document(s) may be used and/or copied only with the written // permission from ATMEL Norway or in accordance with the terms and // conditions stipulated in the agreement/contract under which the // document(s) have been supplied. // //***************************************************************************** // // File........: DFLASH.C // // Author(s)...: Terje Frostad // // Target(s)...: All AVRs with SRAM // // Description.: This file contains routines for the AT45Dx021 DataFlash // // Revisions...: // // YYYYMMDD - VER. - COMMENT - SIGN. // // 20030512 - 1.10 - Modified or general AVRs and added comments - TF // 20010923 - 1.00 - Release 1st revision - TF // 20010818 - 0.10 - Generated file - TF // //***************************************************************************** // Include files //#include "IO8515.H" // NOTE!! This file must be changed for other AVRs #include "DFLASH.H" // This function initializes the ports and resets the DataFlash to // SPI mode 3 void DFlashInit(void) // Not tested { // Initialize DataFlash port pins INIT_DFCS; INIT_DFCK; INIT_DFSI; INIT_DFSO; // Make sure that SPI mode 3 is used, i.e. enable flash when DFCK is high CLR_DFCS; SET_DFCS; } // DFlashInit // This function copies one page from the flash memory to one of // the page buffers void GetPageToBufferDF(unsigned int Page, unsigned char Buffer) // Tested OK! 20010917 TF { // Always wait until DataFlash is ready first ReadyBusyDF(); // Enable dataflash CLR_DFCS; // Send command for either buffer1 or buffer2 if(Buffer) SendByte(MEM_TO_BUFFER2); else SendByte(MEM_TO_BUFFER1); // Send 5 reserved bits + 3 MSB of page address SendByte((unsigned char) (Page >> 7)); // Send 7 LSB of page address + 1 don't care bit SendByte((unsigned char) (Page << 1)); // Send 8 don't care bits SendByte(0); // Disable dataflash SET_DFCS; } // GetPageToBufferDF // This function write one of the page buffers to the flash memory void WriteBufferToPageDF(unsigned int Page, unsigned char Buffer) // Tested OK! 20010917 TF { // Always wait until DataFlash is ready first ReadyBusyDF(); // Enable dataflash CLR_DFCS; // Send command for either buffer1 or buffer2 if(Buffer) SendByte(BUFFER2_TO_MEM_WE); else SendByte(BUFFER1_TO_MEM_WE); // Send 5 reserved bits + 3 MSB of page address SendByte((unsigned char) (Page >> 7)); // Send 7 LSB of page address + 1 don't care bit SendByte((unsigned char) (Page << 1)); // Send 8 don't care bits SendByte(0); // Disable dataflash SET_DFCS; } // WriteBufferToPageDF // This function writes one byte to one of the page buffers void WriteBufferDF(unsigned int Address, unsigned char Data, unsigned char Buffer) // Tested OK! 20010917 TF { // Always wait until DataFlash is ready first ReadyBusyDF(); // Enable dataflash CLR_DFCS; // Send command for either buffer1 or buffer2 if(Buffer) SendByte(WRITE_BUFFER2); else SendByte(WRITE_BUFFER1); // Send 8 don't care bits SendByte(0); // Send 7 don't care bits + 1 MSB of buffer address SendByte((unsigned char) (Address >> 8)); // Send 8 LSB of buffer address SendByte((unsigned char) (Address)); // Send one byte of data to buffer SendByte(Data); // Disable dataflash SET_DFCS; } // WriteBufferDF // This function reads one byte from one of the page buffers unsigned char ReadBufferDF(unsigned int Address, unsigned char Buffer) // Tested OK! 20010917 TF { register unsigned char Data; // Always wait until DataFlash is ready first ReadyBusyDF(); // Enable dataflash CLR_DFCS; // Send command for either buffer1 or buffer2 if(Buffer) SendByte(READ_BUFFER2); else SendByte(READ_BUFFER1); // Send 8 don't care bits SendByte(0); // Send 7 don't care bits + 1 MSB of buffer address SendByte((unsigned char) (Address >> 8)); // Send 8 LSB of buffer address SendByte((unsigned char) (Address)); // Send 8 don't care bits SendByte(0); // Get one byte of data from buffer Data = SendGetByte(0); // Disable dataflash SET_DFCS; return (Data); } // ReadBufferDF // This function reads one byte directly from the flash memory // without going through any of the page buffers unsigned char ReadFlashDF(unsigned int Page, unsigned int Byte) // Tested OK! 20010923 TF { register unsigned char Data; // Always wait until DataFlash is ready first ReadyBusyDF(); // Enable dataflash CLR_DFCS; // Send command SendByte(MEM_PAGE_READ); // Send 5 reserved bits + 3 MSB of page address SendByte((unsigned char) (Page >> 7)); // Send 7 LSB of page address + 1 MSB of buffer address SendByte((unsigned char) (Page << 1) | (unsigned char) (Byte >> 8)); // Send 8 LSB of buffer address SendByte((unsigned char) (Byte)); // Send 32 don't care bits SendByte(0); SendByte(0); SendByte(0); SendByte(0); // Get one byte of data from buffer Data = SendGetByte(0); // Disable dataflash SET_DFCS; return (Data); } // ReadFlashDF // This function performes a block erase of the data flash. // Note!! The address variable is only a byte since this is // enough to address all blocks. This done to save code space // and speed. void BlockEraseDF(void) // Not Tested yet 20021109-TF { unsigned char BlockCount; for ( BlockCount = 0; BlockCount < 127; ++BlockCount) { // Always wait until DataFlash is ready first ReadyBusyDF(); // Enable dataflash CLR_DFCS; // Send command SendByte(BLOCK_ERASE); // Send 5 reserved bits + 3 MSB of block address SendByte((unsigned char) (BlockCount >> 4)); // Send 4 LSB of block address SendByte((unsigned char) (BlockCount << 4)); // Send 8 don't care bits SendByte(0); // Disable dataflash SET_DFCS; } } // BlockEraseDF // This function will check if the DF is ready. This done by // shifting out the first (MSB) bit of the DF status register // and loop on it intil the device is ready void ReadyBusyDF(void) // Tested OK! 20010917 TF { // Enable dataflash CLR_DFCS; // Send command Read Status Register SendByte(READ_STATUS); // Shift out ReadyBusy bit PULSE_DFCK; // Wait until DataFlash is ready while (!GET_DFSO) {}; // while(SPSR.7) {} // Disable dataflash SET_DFCS; } // ReadyBusyDF // This function read the contents of the status register // and return it to the caller. unsigned char GetStatusDF(void) // Not tested { register unsigned char Received; // Enable dataflash CLR_DFCS; // Send command Read Status Register SendByte(READ_STATUS); Received = SendGetByte(0); // Disable dataflash SET_DFCS; return (Received); } // ReadyBusyDF // This function send out one byte. It does not read anything back // This is done to save some clock cycles. void SendByte(unsigned char Send) // Tested OK! 20010917 TF { register unsigned char BitCount = 8; do { // Send bit to DataFlash (DFSI), MSB first if (Send & 0x80) { SET_DFSI; } else { CLR_DFSI; } // Toggle DFCK pin to send current bit PULSE_DFCK; // Get next bit to send Send <<= 1; }while (--BitCount); } // SendByte // This function send one byte and read one byte back. // It uses a separate varibel for transmit and receive. unsigned char SendGetByte(unsigned char Send) // Tested OK! 20010917 TF { register unsigned char Receive; register unsigned char BitCount = 8; do { // Need to Shift Receive buffer first Receive <<= 1; // Send bit to DataFlash (DFSI), MSB first if (Send & 0x80) { SET_DFSI; } else { CLR_DFSI; } // Toggle DFCK pin to send/get current bit PULSE_DFCK; // Get a bit from DataFlash (DFSO), sent MSB first if (GET_DFSO) { ++Receive; } // Get next bit to send Send <<= 1; }while (--BitCount); return (Receive); } // SendGetByte // This function sends one byte and read one byte back. // It uses one varibel for both transmit and receive. unsigned char SendGetByte2(unsigned char Data) // Not Tested { register unsigned char BitCount = 8; do { // Send bit to DataFlash (DFSI), MSB first if (Data & 0x80) { SET_DFSI; } else { CLR_DFSI; } // Toggle DFCK pin to send/get current bit PULSE_DFCK; // Get next bit to send Data <<= 1; // Get a bit from DataFlash (DFSO), sent MSB first if (GET_DFSO) { ++Data; } }while (--BitCount); return (Data); } // SendGetByte2 //**[ End Of DFLASH.C ]**