/********************************************************************* * * FLASH memory * ********************************************************************* * FileName: FLASH_memory.h * Processor: PIC32 * Compiler: MPLAB C32 * * Developer: Bert De Deckere * * Software License Agreement: * * The software is owned by the Developer, and is protected under a * applicable copyright laws. All rights are reserved. * Any use in violation of the foregoing restrictions may subject the * user to criminal sanctions under applicable laws, as well as to * civil liability for the breach of the terms and conditions of this * license. * * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES, * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE DEVELOPER SHALL NOT, * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. * * Author Date Comment *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Bert De Deckere 7/08/2010 ********************************************************************/ #define SFLASH_WRSR 0x01 // Write status register #define SFLASH_WRITE 0x02 // Page program #define SFLASH_READ 0x03 // Read data bytes #define SFLASH_WRDI 0x04 // Write disable #define SFLASH_RDSR 0x05 // Read status register #define SFLASH_WREN 0x06 // Write enable #define SFLASH_RDID 0x9F // Read identification #define SFLASH_RDPD 0xAB // Release from deep power down #define SFLASH_DPD 0xB9 // Deep power down #define SFLASH_ERASE 0xC7 // Bulk erase #define SFLASH_SER 0xD8 // Sector erase #define SFLASHCSLow() _LATB9 = 0; #define SFLASHCSHigh() _LATB9 = 1; #define FOSC 80 // oscillator frequency (MHz) /************************************************************************ * Function: Delayus( unsigned int b) * * Overview: this function creates a delay of x ms * * Input: delay-value * * Output: none * ************************************************************************/ void Delayms( unsigned int a) { a = (a * (FOSC*13)); // multiply with integer value to get 1ms delay while (a--) { } } /************************************************************************ * Function: Delayus( unsigned int b) * * Overview: this function creates a delay of x µs * * Input: delay-value * * Output: none * ************************************************************************/ void Delayus( unsigned int b) { b = (b * (FOSC/80)); while (b--) // approximately 1us delay { } } /************************************************************************ * Function: SFLASHInit * * Overview: this function setup SPI and IOs connected to SFLASH * * Input: none * * Output: none * ************************************************************************/ void SFLASHInit() { // Initialize SPI2 SPI2STAT = 0; // First clear all registers SPI2CON = 0; SPI2BRG = 0; SPI2CONbits.MSTEN = 1; // Enable master mode SPI2CONbits.CKP = 1; // Idle state for clock is a high level; active state is a low level SPI2CONbits.CKE = 0; // Serial output data changes on transition from Idle clock state to active clock state SPI2CONbits.SMP = 0; // Input data sampled at middle of data output time SPI2BRG = 1; // Set baud-rate generator SPI2CONbits.ON = 1; // Set SPI2 module on SPI2STATbits.SPIROV = 0; // Set IOs directions for SFLASH SPI _LATB9 = 1; // Deselect FLASH-memory _TRISB9 = 0; // CS-pin is now an output _TRISG6 = 0; // Serial Clock pin _TRISG7 = 1; // MISO input _TRISG8 = 0; // MOSI output } /************************************************************************ * Function SPIPut(BYTE data) * * Overview: this function sends a byte * * Input: byte to be sent * * Output: none * ************************************************************************/ unsigned char SPIPut(unsigned char data) { while(!SPI2STATbits.SPITBE); // Wait for all previous data bytes to be transmitted SPI2BUF = data; // Transmit new data while(!SPI2STATbits.SPIRBF); // Wait for all data bytes to be received return SPI2BUF; // Return tranceive buffer } /************************************************************************ * Function: unsigned char SFLASHReadSR() * * Overview: this function reads status register * * Input: none * * Output: non zero if busy * ************************************************************************/ unsigned char SFLASHReadSR() { unsigned char temp; // Variable to store register value SFLASHCSLow(); // Select chip SPIPut(SFLASH_RDSR); // Send command "Read Status Register" SPI2STATbits.SPIRBF = 0; // Clear read buffer flag bit temp = SPIPut(0); // Save received byte SFLASHCSHigh(); // Deselect chip return (temp); // Return status register value } /************************************************************************ * Function: unsigned int SFLASHReadID() * * Overview: this function reads the Manufacturer ID code * (only available on 110nm technology chip) * * Input: none * * Output: data read * ************************************************************************/ unsigned int SFLASHReadID() { unsigned int temp; // Declare temporary variable while(SFLASHReadSR() & 0x01); // Wait until all previous write/erase operations are terminated SFLASHCSLow(); // Select chip SPIPut(SFLASH_RDID); // Send command "Read ID" temp = SPIPut(0); // Manufacturer ID temp <<= 8; // Shift manufacturer ID to the middle temp = SPIPut(0); // Device ID temp <<= 8; // Shift manufacturer ID to the MSB temp = SPIPut(0); // UID + CFI data SFLASHCSHigh(); // Deselect chip return temp; // Return previous read ID } /************************************************************************ * Function: SFLASHReadByte(unsigned int address) * * Overview: this function reads a byte from the address specified * * Input: address * * Output: data read * ************************************************************************/ unsigned char SFLASHReadByte(unsigned int address) { unsigned char temp; // Declare temporary variable to store data byte SPI2STATbits.SPIROV = 0; // Prevent previous data collision to halt the data receipt while(SFLASHReadSR() & 0x01); // Wait for write end SFLASHCSLow(); // Select chip SPIPut(SFLASH_READ); // Send "Read" command SPIPut(address >> 16); // Transmit the page address you want to read (MSB first) SPIPut(address >> 8); SPIPut(address); temp = SPIPut(0); // Read the received byte SFLASHCSHigh(); // Deselect chip return temp; // Return previous read Byte } /************************************************************************ * Function: SFLASHWriteEnable() * * Overview: this function allows write/erase SFLASH. Must be called * before every write/erase command. * * Input: none * * Output: none * ************************************************************************/ void SFLASHWriteEnable() { SFLASHCSLow(); // Select chip SPIPut(SFLASH_WREN); // Send command "Write Enable" while(!SPI2STATbits.SPITBE); // Wait for free buffer SFLASHCSHigh(); // Deselect chip } /************************************************************************ * Function: void SFLASHResetWriteDisable() * * Overview: this function disables write/erase commands * * Input: none * * Output: none * ************************************************************************/ void SFLASHResetWriteDisable() { while(SFLASHReadSR() & 0x01); // Wait until all previous write/erase operations are terminated SFLASHCSLow(); // Select chip SPIPut(SFLASH_WRDI); // Send command "Write Disable" while(!SPI2STATbits.SPITBE); // Wait for free buffer SFLASHCSHigh(); // Deselect chip } /************************************************************************ * Function: void SFLASHWriteByte(unsigned char data, unsigned int address) * * Overview: this function writes a byte to the address specified * * Input: data to be written and address * * Output: none * ************************************************************************/ void SFLASHWriteByte(unsigned char data, unsigned int address) { while(SFLASHReadSR() & 0x01); // Wait until all previous write/erase operations are terminated SFLASHWriteEnable(); // Enable read/write commands SFLASHCSLow(); // Select chip SPIPut(SFLASH_WRITE); // Prepare FLASH-memory to receive data SPIPut(address >> 16); // Transmit the memory address (MSB first) SPIPut(address >> 8); SPIPut(address); // LSB SPIPut(data); // Send the byte while(!SPI2STATbits.SPITBE); // Wait for free buffer SFLASHCSHigh(); // Deselect chip } /************************************************************************ * Function: SFLASHWriteArray(unsigned int address, unsigned char *Data, * unsigned int Count) * * Overview: this function writes a data array at the address specified * * Input: flash memory address, pointer to the data array, data number * * Output: none * ************************************************************************/ void SFLASHWriteArray(unsigned int address, unsigned char *Data, unsigned int Count) { while(SFLASHReadSR() & 0x01); // Wait until all previous write/erase operations are terminated SFLASHWriteEnable(); // Enable read/write commands SFLASHCSLow(); // Select chip SPIPut(SFLASH_WRITE); // Prepare FLASH-memory to receive data SPIPut(address >> 16); // Transmit the memory address (MSB first) SPIPut(address >> 8); SPIPut(address); // LSB while(Count--) // Keep running through the loop until all bytes are send (Count == 0) { SPIPut(*Data++); // Send the byte and fetch next one address++; if(!(address % 256)) // after 256 bytes start a new data sequence { while(!SPI2STATbits.SPITBE); // Wait for free buffer SFLASHCSHigh(); // Deselect chip while(SFLASHReadSR() & 0x01); // Wait until all previous write/erase operations are terminated SFLASHWriteEnable(); // Enable read/write commands SFLASHCSLow(); // Select chip SPIPut(SFLASH_WRITE); // Prepare FLASH-memory to receive data SPIPut(address >> 16); // Transmit the memory address (MSB first) SPIPut(address >> 8); SPIPut(address); // LSB } } while(!SPI2STATbits.SPITBE); // Wait for free buffer SFLASHCSHigh(); // Deselect chip } /************************************************************************ * Function: SFLASHReadArray(unsigned int address, unsigned char *Data, * unsigned int Count) * * Overview: this function reads data into buffer specified * * Input: flash memory address, pointer to the data buffer, data number * ************************************************************************/ void SFLASHReadArray(unsigned int address, unsigned char *Data, unsigned int Count) { while(SFLASHReadSR() & 0x01); // Wait until all previous write/erase operations are terminated SFLASHCSLow(); // Select chip SPIPut(SFLASH_READ); // Send "Read" command SPIPut(address >> 16); // Transmit the page address you want to read (MSB first) SPIPut(address >> 8); SPIPut(address); // Address will be automatically incremented while(Count--) // Keep running through the loop until Count = 0 { *Data++ = SPIPut(0); // Save the received data } while(!SPI2STATbits.SPITBE); // Wait for free buffer SFLASHCSHigh(); // Deselect chip } /************************************************************************ * Function: void SFLASHChipErase(void) * * Overview: chip erase * * Input: none * ************************************************************************/ void SFLASHChipErase(void) { while(SFLASHReadSR() & 0x01); // Wait until all previous write/erase operations are terminated SFLASHWriteEnable(); // Send "Write Enable" command SFLASHCSLow(); // Select chip SPIPut(SFLASH_ERASE); // Send erase command while(!SPI2STATbits.SPITBE); // Wait for free buffer SFLASHCSHigh(); // deselect chip } /************************************************************************ * Function: void SFLASHSectorErase(DWORD address) * * Overview: this function erases a 65KB sector * * Input: address within sector needs to be erased * * Output: none * ************************************************************************/ void SFLASHSectorErase(unsigned int address) { while(SFLASHReadSR() & 0x01); // Wait until all previous write/erase operations are terminated SFLASHWriteEnable(); // Enable write/erase commands SFLASHCSLow(); // Select chip SPIPut(SFLASH_SER); // Send sector erase SPIPut(address >> 16); // Transmit the sector-address you want to erase (MSB first) SPIPut(address >> 8); SPIPut(address); while(!SPI2STATbits.SPITBE); // Wait until all data is sent SFLASHCSHigh(); // Deselect chip } /************************************************************************ * Function: SFLASHPowerDown * * Overview: this function puts the FLASH memory in power down state * * Input: none * * Output: none * ************************************************************************/ void SFLASHPowerDown() { while(SFLASHReadSR() & 0x01); // Wait until all previous write/erase operations are terminated SFLASHCSLow(); // Select chip SPIPut(SFLASH_DPD); // Send "deap power down" command while(!SPI2STATbits.SPITBE); // Wait until all data is sent SFLASHCSHigh(); // Deselect chip Delayus(3); // Wait 3 µs to execute instruction } /************************************************************************ * Function: unsigned char SFLASHPowerUp * * Overview: this function releases the FLASH memory from the power down state * * Input: none * * Output: Electronic signature * ************************************************************************/ unsigned char SFLASHPowerUp() { unsigned char temp; // Declare temporary variable to store electronic signature while(SFLASHReadSR() & 0x01); // Wait until all previous write/erase operations are terminated SFLASHCSLow(); // Select chip SPIPut(SFLASH_RDPD); // Send "power down" command SPIPut(0); // Send 3 dummy bytes SPIPut(0); SPIPut(0); temp = SPIPut(0); // Receive electronic signature while(!SPI2STATbits.SPITBE); // Wait until all data is sent SFLASHCSHigh(); // Deselect chip return temp; }