he estado leyendo el datasheet....lo único que yo y el inglés no nos llevamos muy bien :)
/*********************************************************************
*
* Data SPI EEPROM Access Routines
*
*********************************************************************
* FileName: SPIEEPROM.c
* Dependencies: None
* Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
* Compiler: Microchip C32 v1.05 or higher
* Microchip C30 v3.12 or higher
* Microchip C18 v3.30 or higher
* HI-TECH PICC-18 PRO 9.63PL2 or higher
* Company: Microchip Technology, Inc.
*
* Software License Agreement
*
* Copyright (C) 2002-2009 Microchip Technology Inc. All rights
* reserved.
*
* Microchip licenses to you the right to use, modify, copy, and
* distribute:
* (i) the Software when embedded on a Microchip microcontroller or
* digital signal controller product ("Device") which is
* integrated into Licensee's product; or
* (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h,
* ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device
* used in conjunction with a Microchip ethernet controller for
* the sole purpose of interfacing with the ethernet controller.
*
* You should refer to the license agreement accompanying this
* Software for additional information regarding your rights and
* obligations.
*
* THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
* WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
* LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
* PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
* BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
* THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
* SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
* (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
*
*
* Author Date Comment
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Nilesh Rajbharti 5/20/02 Original (Rev. 1.0)
* Howard Schlunder 9/01/04 Rewritten for SPI EEPROMs
* Howard Schlunder 8/10/06 Modified to control SPI module
* frequency whenever EEPROM accessed
* to allow bus sharing with different
* frequencies.
********************************************************************/
#define __SPIEEPROM_C
#include "HardwareProfile.h"
// If the CS line is not defined, SPIEEPROM.c's content will not be compiled.
// If you are using a serial EEPROM please define the CS pin as EEPROM_CS_TRIS
// in HardwareProfile.h
#if defined(EEPROM_CS_TRIS)
#include "TCPIP Stack/TCPIP.h"
// IMPORTANT SPI NOTE: The code in this file expects that the SPI interrupt
// flag (EEPROM_SPI_IF) be clear at all times. If the SPI is shared with
// other hardware, the other code should clear the EEPROM_SPI_IF when it is
// done using the SPI.
// SPI Serial EEPROM buffer size. To enhance performance while
// cooperatively sharing the SPI bus with other peripherals, bytes
// read and written to the memory are locally buffered. Legal
// sizes are 1 to the EEPROM page size.
#define EEPROM_BUFFER_SIZE (32)
// Must be the EEPROM write page size, or any binary power of 2 divisor. If
// using a smaller number, make sure it is at least EEPROM_BUFFER_SIZE big for
// max performance. Microchip 25LC256 uses 64 byte page size, 25LC1024 uses
// 256 byte page size, so 64 is compatible with both.
#define EEPROM_PAGE_SIZE (64)
// EEPROM SPI opcodes
#define OPCODE_READ 0x03 // Read data from memory array beginning at selected address
#define OPCODE_WRITE 0x02 // Write data to memory array beginning at selected address
#define OPCODE_WRDI 0x04 // Reset the write enable latch (disable write operations)
#define OPCODE_WREN 0x06 // Set the write enable latch (enable write operations)
#define OPCODE_RDSR 0x05 // Read Status register
#define OPCODE_WRSR 0x01 // Write Status register
#define EEPROM_MAX_SPI_FREQ (10000000ul) // Hz
#if defined (__18CXX)
#define ClearSPIDoneFlag() {EEPROM_SPI_IF = 0;}
#define WaitForDataByte() {while(!EEPROM_SPI_IF); EEPROM_SPI_IF = 0;}
#define SPI_ON_BIT (EEPROM_SPICON1bits.SSPEN)
#elif defined(__C30__)
#define ClearSPIDoneFlag()
static inline __attribute__((__always_inline__)) void WaitForDataByte( void )
{
while ((EEPROM_SPISTATbits.SPITBF == 1) || (EEPROM_SPISTATbits.SPIRBF == 0));
}
#define SPI_ON_BIT (EEPROM_SPISTATbits.SPIEN)
#elif defined( __PIC32MX__ )
#define ClearSPIDoneFlag()
static inline __attribute__((__always_inline__)) void WaitForDataByte( void )
{
while (!EEPROM_SPISTATbits.SPITBE || !EEPROM_SPISTATbits.SPIRBF);
}
#define SPI_ON_BIT (EEPROM_SPICON1bits.ON)
#else
#error Determine SPI flag mechanism
#endif
static void DoWrite(void);
static DWORD EEPROMAddress;
static BYTE EEPROMBuffer[EEPROM_BUFFER_SIZE];
static BYTE vBytesInBuffer;
/*********************************************************************
* Function: void XEEInit(unsigned char speed)
*
* PreCondition: None
*
* Input: speed - not used (included for compatibility only)
*
* Output: None
*
* Side Effects: None
*
* Overview: Initialize SPI module to communicate to serial
* EEPROM.
*
* Note: Code sets SPI clock to Fosc/16.
********************************************************************/
#if (defined(HPC_EXPLORER) || defined(PIC18_EXPLORER)) && !defined(__18F87J10) && !defined(__18F87J11) && !defined(__18F87J50)
#define PROPER_SPICON1 (0x20) /* SSPEN bit is set, SPI in master mode, FOSC/4, IDLE state is low level */
#elif defined(__PIC24F__)
#define PROPER_SPICON1 (0x0013 | 0x0120) /* 1:1 primary prescale, 4:1 secondary prescale, CKE=1, MASTER mode */
#elif defined(__dsPIC30F__)
#define PROPER_SPICON1 (0x0017 | 0x0120) /* 1:1 primary prescale, 3:1 secondary prescale, CKE=1, MASTER mode */
#elif defined(__dsPIC33F__) || defined(__PIC24H__)
#define PROPER_SPICON1 (0x0003 | 0x0120) /* 1:1 primary prescale, 8:1 secondary prescale, CKE=1, MASTER mode */
#elif defined(__PIC32MX__)
#define PROPER_SPICON1 (_SPI2CON_ON_MASK | _SPI2CON_FRZ_MASK | _SPI2CON_CKE_MASK | _SPI2CON_MSTEN_MASK)
#else
#define PROPER_SPICON1 (0x21) /* SSPEN bit is set, SPI in master mode, FOSC/16, IDLE state is low level */
#endif
void XEEInit(void)
{
EEPROM_CS_IO = 1;
EEPROM_CS_TRIS = 0; // Drive SPI EEPROM chip select pin
EEPROM_SCK_TRIS = 0; // Set SCK pin as an output
EEPROM_SDI_TRIS = 1; // Make sure SDI pin is an input
EEPROM_SDO_TRIS = 0; // Set SDO pin as an output
ClearSPIDoneFlag();
#if defined(__C30__)
EEPROM_SPICON1 = PROPER_SPICON1; // See PROPER_SPICON1 definition above
EEPROM_SPICON2 = 0;
EEPROM_SPISTAT = 0; // clear SPI
EEPROM_SPISTATbits.SPIEN = 1;
#elif defined(__C32__)
EEPROM_SPIBRG = (GetPeripheralClock()-1ul)/2ul/EEPROM_MAX_SPI_FREQ;
EEPROM_SPICON1 = PROPER_SPICON1;
#elif defined(__18CXX)
EEPROM_SPICON1 = PROPER_SPICON1; // See PROPER_SPICON1 definition above
EEPROM_SPISTATbits.CKE = 1; // Transmit data on rising edge of clock
EEPROM_SPISTATbits.SMP = 0; // Input sampled at middle of data output time
#endif
}
/*********************************************************************
* Function: XEE_RESULT XEEBeginRead(DWORD address)
*
* PreCondition: None
*
* Input: address - Address at which read is to be performed.
*
* Output: XEE_SUCCESS
*
* Side Effects: None
*
* Overview: Sets internal address counter to given address.
*
* Note: None
********************************************************************/
XEE_RESULT XEEBeginRead(DWORD address)
{
// Save the address and emptry the contents of our local buffer
EEPROMAddress = address;
vBytesInBuffer = 0;
return XEE_SUCCESS;
}
/*********************************************************************
* Function: BYTE XEERead(void)
*
* PreCondition: XEEInit() && XEEBeginRead() are already called.
*
* Input: None
*
* Output: BYTE that was read
*
* Side Effects: None
*
* Overview: Reads next byte from EEPROM; internal address
* is incremented by one.
*
* Note: None
********************************************************************/
BYTE XEERead(void)
{
// Check if no more bytes are left in our local buffer
if(vBytesInBuffer == 0u)
{
// Get a new set of bytes
XEEReadArray(EEPROMAddress, EEPROMBuffer, EEPROM_BUFFER_SIZE);
EEPROMAddress += EEPROM_BUFFER_SIZE;
vBytesInBuffer = EEPROM_BUFFER_SIZE;
}
// Return a byte from our local buffer
return EEPROMBuffer[EEPROM_BUFFER_SIZE - vBytesInBuffer--];
}
/*********************************************************************
* Function: XEE_RESULT XEEEndRead(void)
*
* PreCondition: None
*
* Input: None
*
* Output: XEE_SUCCESS
*
* Side Effects: None
*
* Overview: This function does nothing.
*
* Note: Function is used for backwards compatability with
* I2C EEPROM module.
********************************************************************/
XEE_RESULT XEEEndRead(void)
{
return XEE_SUCCESS;
}
/*********************************************************************
* Function: XEE_RESULT XEEReadArray(DWORD address,
* BYTE *buffer,
* WORD length)
*
* PreCondition: XEEInit() is already called.
*
* Input: address - Address from where array is to be read
* buffer - Caller supplied buffer to hold the data
* length - Number of bytes to read.
*
* Output: XEE_SUCCESS
*
* Side Effects: None
*
* Overview: Reads desired number of bytes in sequential mode.
* This function performs all necessary steps
* and releases the bus when finished.
*
* Note: None
********************************************************************/
XEE_RESULT XEEReadArray(DWORD address,
BYTE *buffer,
WORD length)
{
volatile BYTE Dummy;
BYTE vSPIONSave;
#if defined(__18CXX)
BYTE SPICON1Save;
#elif defined(__C30__)
WORD SPICON1Save;
#else
DWORD SPICON1Save;
#endif
// Save SPI state (clock speed)
SPICON1Save = EEPROM_SPICON1;
vSPIONSave = SPI_ON_BIT;
// Configure SPI
SPI_ON_BIT = 0;
EEPROM_SPICON1 = PROPER_SPICON1;
SPI_ON_BIT = 1;
EEPROM_CS_IO = 0;
// Send READ opcode
EEPROM_SSPBUF = OPCODE_READ;
WaitForDataByte();
Dummy = EEPROM_SSPBUF;
// Send address
#if defined(USE_EEPROM_25LC1024)
EEPROM_SSPBUF = ((DWORD_VAL*)&address)->v[2];
WaitForDataByte();
Dummy = EEPROM_SSPBUF;
#endif
EEPROM_SSPBUF = ((DWORD_VAL*)&address)->v[1];
WaitForDataByte();
Dummy = EEPROM_SSPBUF;
EEPROM_SSPBUF = ((DWORD_VAL*)&address)->v[0];
WaitForDataByte();
Dummy = EEPROM_SSPBUF;
while(length--)
{
EEPROM_SSPBUF = 0;
WaitForDataByte();
Dummy = EEPROM_SSPBUF;
if(buffer != NULL)
*buffer++ = Dummy;
};
EEPROM_CS_IO = 1;
// Restore SPI state
SPI_ON_BIT = 0;
EEPROM_SPICON1 = SPICON1Save;
SPI_ON_BIT = vSPIONSave;
return XEE_SUCCESS;
}
/*********************************************************************
* Function: XEE_RESULT XEEBeginWrite(DWORD address)
*
* PreCondition: None
*
* Input: address - address to be set for writing
*
* Output: XEE_SUCCESS
*
* Side Effects: None
*
* Overview: Modifies internal address counter of EEPROM.
*
* Note: Unlike XEESetAddr() in xeeprom.c for I2C EEPROM
* memories, this function is used only for writing
* to the EEPROM. Reads must use XEEBeginRead(),
* XEERead(), and XEEEndRead().
* This function does not use the SPI bus.
********************************************************************/
XEE_RESULT XEEBeginWrite(DWORD address)
{
vBytesInBuffer = 0;
EEPROMAddress = address;
return XEE_SUCCESS;
}
/*********************************************************************
* Function: XEE_RESULT XEEWrite(BYTE val)
*
* PreCondition: XEEInit() && XEEBeginWrite() are already called.
*
* Input: val - Byte to be written
*
* Output: XEE_SUCCESS
*
* Side Effects: None
*
* Overview: Writes a byte to the write cache, and if full,
* commits the write. Also, if a write boundary is
* reached the write is committed. When finished
* writing, XEEEndWrite() must be called to commit
* any unwritten bytes from the write cache.
*
* Note: None
********************************************************************/
XEE_RESULT XEEWrite(BYTE val)
{
EEPROMBuffer[vBytesInBuffer++] = val;
if(vBytesInBuffer >= sizeof(EEPROMBuffer))
DoWrite();
else if((((BYTE)EEPROMAddress + vBytesInBuffer) & (EEPROM_PAGE_SIZE-1)) == 0u)
DoWrite();
return XEE_SUCCESS;
}
/*****************************************************************************
Function:
XEE_RESULT XEEWriteArray(BYTE *val, WORD wLen)
Summary:
Writes an array of bytes to the EEPROM part.
Description:
This function writes an array of bytes to the EEPROM at the address
specified when XEEBeginWrite() was called. Page boundary crossing is
handled internally.
Precondition:
XEEInit() was called once and XEEBeginWrite() was called.
Parameters:
vData - The array to write to the next memory location
wLen - The length of the data to be written
Returns:
None
Remarks:
The internal write cache is flushed at completion, so it is unnecessary
to call XEEEndWrite() after calling this function. However, if you do
so, no harm will be done.
***************************************************************************/
void XEEWriteArray(BYTE *val, WORD wLen)
{
while(wLen--)
XEEWrite(*val++);
XEEEndWrite();
}
/*********************************************************************
* Function: XEE_RESULT XEEEndWrite(void)
*
* PreCondition: XEEInit() && XEEBeginWrite() are already called.
*
* Input: None
*
* Output: XEE_SUCCESS
*
* Side Effects: None
*
* Overview: Commits any last uncommitted bytes in cache to
* physical storage.
*
* Note: Call this function when you no longer need to
* write any more bytes at the selected address.
********************************************************************/
XEE_RESULT XEEEndWrite(void)
{
if(vBytesInBuffer)
DoWrite();
return XEE_SUCCESS;
}
static void DoWrite(void)
{
BYTE i;
volatile BYTE vDummy;
BYTE vSPIONSave;
#if defined(__18CXX)
BYTE SPICON1Save;
#elif defined(__C30__)
WORD SPICON1Save;
#else
DWORD SPICON1Save;
#endif
// Save SPI state
SPICON1Save = EEPROM_SPICON1;
vSPIONSave = SPI_ON_BIT;
// Configure SPI
SPI_ON_BIT = 0;
EEPROM_SPICON1 = PROPER_SPICON1;
SPI_ON_BIT = 1;
// Set the Write Enable latch
EEPROM_CS_IO = 0;
EEPROM_SSPBUF = OPCODE_WREN;
WaitForDataByte();
vDummy = EEPROM_SSPBUF;
EEPROM_CS_IO = 1;
// Send WRITE opcode
EEPROM_CS_IO = 0;
EEPROM_SSPBUF = OPCODE_WRITE;
WaitForDataByte();
vDummy = EEPROM_SSPBUF;
// Send address
#if defined(USE_EEPROM_25LC1024)
EEPROM_SSPBUF = ((DWORD_VAL*)&EEPROMAddress)->v[2];
WaitForDataByte();
vDummy = EEPROM_SSPBUF;
#endif
EEPROM_SSPBUF = ((DWORD_VAL*)&EEPROMAddress)->v[1];
WaitForDataByte();
vDummy = EEPROM_SSPBUF;
EEPROM_SSPBUF = ((DWORD_VAL*)&EEPROMAddress)->v[0];
WaitForDataByte();
vDummy = EEPROM_SSPBUF;
for(i = 0; i < vBytesInBuffer; i++)
{
// Send the byte to write
EEPROM_SSPBUF = EEPROMBuffer[i];
WaitForDataByte();
vDummy = EEPROM_SSPBUF;
}
// Begin the write
EEPROM_CS_IO = 1;
// Update write address and clear write cache
EEPROMAddress += vBytesInBuffer;
vBytesInBuffer = 0;
// Restore SPI State
SPI_ON_BIT = 0;
EEPROM_SPICON1 = SPICON1Save;
SPI_ON_BIT = vSPIONSave;
// Wait for write to complete
while( XEEIsBusy() );
}
/*********************************************************************
* Function: BOOL XEEIsBusy(void)
*
* PreCondition: XEEInit() is already called.
*
* Input: None
*
* Output: FALSE if EEPROM is not busy
* TRUE if EEPROM is busy
*
* Side Effects: None
*
* Overview: Reads the status register
*
* Note: None
********************************************************************/
BOOL XEEIsBusy(void)
{
volatile BYTE_VAL result;
BYTE vSPIONSave;
#if defined(__18CXX)
BYTE SPICON1Save;
#elif defined(__C30__)
WORD SPICON1Save;
#else
DWORD SPICON1Save;
#endif
// Save SPI state
SPICON1Save = EEPROM_SPICON1;
vSPIONSave = SPI_ON_BIT;
// Configure SPI
SPI_ON_BIT = 0;
EEPROM_SPICON1 = PROPER_SPICON1;
SPI_ON_BIT = 1;
EEPROM_CS_IO = 0;
// Send RDSR - Read Status Register opcode
EEPROM_SSPBUF = OPCODE_RDSR;
WaitForDataByte();
result.Val = EEPROM_SSPBUF;
// Get register contents
EEPROM_SSPBUF = 0;
WaitForDataByte();
result.Val = EEPROM_SSPBUF;
EEPROM_CS_IO = 1;
// Restore SPI State
SPI_ON_BIT = 0;
EEPROM_SPICON1 = SPICON1Save;
SPI_ON_BIT = vSPIONSave;
return result.bits.b0;
}
#endif //#if defined(EEPROM_CS_TRIS)
/*********************************************************************
*
* External serial data EEPROM Access Defs.
*
*********************************************************************
* FileName: XEEPROM.h
* Dependencies: None
* Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
* Compiler: Microchip C32 v1.05 or higher
* Microchip C30 v3.12 or higher
* Microchip C18 v3.30 or higher
* HI-TECH PICC-18 PRO 9.63PL2 or higher
* Company: Microchip Technology, Inc.
*
* Software License Agreement
*
* Copyright (C) 2002-2009 Microchip Technology Inc. All rights
* reserved.
*
* Microchip licenses to you the right to use, modify, copy, and
* distribute:
* (i) the Software when embedded on a Microchip microcontroller or
* digital signal controller product ("Device") which is
* integrated into Licensee's product; or
* (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h,
* ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device
* used in conjunction with a Microchip ethernet controller for
* the sole purpose of interfacing with the ethernet controller.
*
* You should refer to the license agreement accompanying this
* Software for additional information regarding your rights and
* obligations.
*
* THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
* WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
* LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
* PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
* BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
* THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
* SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
* (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
*
*
* Author Date Comment
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Nilesh Rajbharti 5/20/02 Original (Rev. 1.0)
********************************************************************/
#ifndef __XEEPROM_H
#define __XEEPROM_H
#include "HardwareProfile.h"
typedef BOOL XEE_RESULT;
#define XEE_SUCCESS FALSE
#if defined(EEPROM_CS_TRIS)
void XEEInit(void);
XEE_RESULT XEEBeginWrite(DWORD address);
XEE_RESULT XEEWrite(BYTE val);
void XEEWriteArray(BYTE *val, WORD wLen);
XEE_RESULT XEEEndWrite(void);
XEE_RESULT XEEBeginRead(DWORD address);
BYTE XEERead(void);
XEE_RESULT XEEReadArray(DWORD address, BYTE *buffer, WORD length);
XEE_RESULT XEEEndRead(void);
BOOL XEEIsBusy(void);
#else
// If you get any of these linker errors, it means that you either have an
// error in your HardwareProfile.h or TCPIPConfig.h definitions. The code
// is attempting to call a function that can't possibly work because you
// have not specified what pins and SPI module the physical SPI EEPROM chip
// is connected to. Alternatively, if you don't have an SPI EERPOM chip, it
// means you have enabled a stack feature that requires SPI EEPROM hardware.
// In this case, you need to edit TCPIPConfig.h and disable this stack
// feature. The linker error tells you which object file this error was
// generated from. It should be a clue as to what feature you need to
// disable.
void You_cannot_call_the_XEEInit_function_without_defining_EEPROM_CS_TRIS_in_HardwareProfile_h_first(void);
XEE_RESULT You_cannot_call_the_XEEBeginWrite_function_without_defining_EEPROM_CS_TRIS_in_HardwareProfile_h_first(void);
XEE_RESULT You_cannot_call_the_XEEWrite_function_without_defining_EEPROM_CS_TRIS_in_HardwareProfile_h_first(void);
void You_cannot_call_the_XEEWriteArray_function_without_defining_EEPROM_CS_TRIS_in_HardwareProfile_h_first(void);
XEE_RESULT You_cannot_call_the_XEEEndWrite_function_without_defining_EEPROM_CS_TRIS_in_HardwareProfile_h_first(void);
XEE_RESULT You_cannot_call_the_XEEBeginRead_function_without_defining_EEPROM_CS_TRIS_in_HardwareProfile_h_first(void);
BYTE You_cannot_call_the_XEERead_function_without_defining_EEPROM_CS_TRIS_in_HardwareProfile_h_first(void);
XEE_RESULT You_cannot_call_the_XEEReadArray_function_without_defining_EEPROM_CS_TRIS_in_HardwareProfile_h_first(void);
XEE_RESULT You_cannot_call_the_XEEEndRead_function_without_defining_EEPROM_CS_TRIS_in_HardwareProfile_h_first(void);
BOOL You_cannot_call_the_XEEIsBusy_function_without_defining_EEPROM_CS_TRIS_in_HardwareProfile_h_first(void);
#define XEEInit() You_cannot_call_the_XEEInit_function_without_defining_EEPROM_CS_TRIS_in_HardwareProfile_h_first()
#define XEEBeginWrite(a) You_cannot_call_the_XEEBeginWrite_function_without_defining_EEPROM_CS_TRIS_in_HardwareProfile_h_first()
#define XEEWrite(a) You_cannot_call_the_XEEWrite_function_without_defining_EEPROM_CS_TRIS_in_HardwareProfile_h_first()
#define XEEWriteArray(a,b) You_cannot_call_the_XEEWriteArray_function_without_defining_EEPROM_CS_TRIS_in_HardwareProfile_h_first()
#define XEEEndWrite() You_cannot_call_the_XEEEndWrite_function_without_defining_EEPROM_CS_TRIS_in_HardwareProfile_h_first()
#define XEEBeginRead(a) You_cannot_call_the_XEEBeginRead_function_without_defining_EEPROM_CS_TRIS_in_HardwareProfile_h_first()
#define XEERead(a) You_cannot_call_the_XEERead_function_without_defining_EEPROM_CS_TRIS_in_HardwareProfile_h_first()
#define XEEReadArray(a, b, c) You_cannot_call_the_XEEReadArray_function_without_defining_EEPROM_CS_TRIS_in_HardwareProfile_h_first()
#define XEEEndRead() You_cannot_call_the_XEEEndRead_function_without_defining_EEPROM_CS_TRIS_in_HardwareProfile_h_first()
#define XEEIsBusy() You_cannot_call_the_XEEIsBusy_function_without_defining_EEPROM_CS_TRIS_in_HardwareProfile_h_first()
#endif
#endif
/*********************************************************************
*
* Data SPI FLASH Access Routines
*
*********************************************************************
* FileName: SPIFLASH.c
* Dependencies: None
* Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32MX
* Compiler: Microchip C32 v1.00 or higher
* Microchip C30 v3.01 or higher
* Microchip C18 v3.13 or higher
* HI-TECH PICC-18 STD 9.50PL3 or higher
* Company: Microchip Technology, Inc.
*
* Software License Agreement
*
* Copyright © 2002-2007 Microchip Technology Inc. All rights
* reserved.
*
* Microchip licenses to you the right to use, modify, copy, and
* distribute:
* (i) the Software when embedded on a Microchip microcontroller or
* digital signal controller product (“Device”) which is
* integrated into Licensee’s product; or
* (ii) ONLY the Software driver source files ENC28J60.c and
* ENC28J60.h ported to a non-Microchip device used in
* conjunction with a Microchip ethernet controller for the
* sole purpose of interfacing with the ethernet controller.
*
* You should refer to the license agreement accompanying this
* Software for additional information regarding your rights and
* obligations.
*
* THE SOFTWARE AND DOCUMENTATION ARE PROVIDED “AS IS” WITHOUT
* WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
* LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
* PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
* BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
* THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
* SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
* (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
*
*
* Author Date Comment
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Nilesh Rajbharti 5/20/02 Original (Rev. 1.0)
* Howard Schlunder 9/01/04 Rewritten for SPI EEPROMs
* Howard Schlunder 8/10/06 Modified to control SPI module
* frequency whenever EEPROM accessed
* to allow bus sharing with different
* frequencies.
* Maurizio Spoto 13/02/08 readapt for SPI FLASH MACRONIX
* Maurizio Spoto 8/08/08 readapt for PIC32MX
* Maurizio Spoto 5/08/09 mount LBA for MyDB table partition
* Maurizio Spoto 10/10/08 adding method for LOW_RAM ,
* adding SWAP sector for LOW_RAM
* optimized and unifique Buffering RX and TX
* Maurizio Spoto 11/10/08 adding method use NAND FLASH
* with Dynamic NOR FLASH and automatic
* partition in sequencial skip sector
********************************************************************/
//#define __SPIFLASH_C
#include "RootProject.h"
#include "GenericTypeDefs.h"
#include "SPIflash.h"
// FLASH SPI opcodes
#define READ 0x03 // Read data from memory array beginning at selected address
#define WRITE 0x02 // Write data to memory array beginning at selected address
#define WRDI 0x04 // Reset the write enable latch (disable write operations)
#define WREN 0x06 // Set the write enable latch (enable write operations)
#define RDSR 0x05 // Read Status register
#define WRSR 0x01 // Write Status register
#define DYFM 0x00 // Dummy byte
#define RDID 0x9F // Read ID Manufactured
#define SEFM 0x20 // Erase Sector (500ms)
#define BEFM 0x52 // Erase Block (1sec)
#define CEFM 0x60 // Erase Chip (3sec)
#define FREAD 0x0B // Fast Read (max 50Mhz) es: FREAD > ADD1 > ADD2 > ADD3 > DYFM
#define ALL_OPEN 0x02 // Write Enable && no protect Blocks
//#define FLASH_HIGH_SPEED //read max 50Mhz (other operation 25Mhz)
#define FLASH_LOW_SPEED //read max 25Mhz (other operation 50Mhz)
#define FLASH_ST_VIRTUAL_SECTOR (0x000FF000)
#define FLASH_EN_VIRTUAL_SECTOR (0x00100000)
#define FLASH_BIT_SPEED (8E6) //8Mhz
#define FLASH_CS_WAIT (INSTR_FREQ / FLASH_BIT_SPEED)
#define FLASH_SMALL_RAM
//#define INCLUDE_EXTENDS_METHOD
#define _CONTROL_LBA_
/* PROTOTYPE */
#if defined (INCLUDE_EXTENDS_METHOD)
static void DoWriteF(void);
#endif
static void FLASHSetReg(void);
static void FLASHSetWEL(BYTE mode);
static BOOL LocalizeAddress(DWORD dwAddressL);
void DynamicWriteF(DWORD dwAddress);
void DynamicWriteLenF(DWORD dwAddress,WORD lenBuf);
void SetFSHSetting(void);
#if defined (FLASH_SMALL_RAM)
#define FLASH_BUFFER_SIZE ((WORD)(PAGE_LEN+1)) //LIMIT 256 Bytes
unsigned long tempVirtualAddress=0; //swap sector address
unsigned int iA=0,iB=0,iC=0,iD=0,iE=0; //unknowns
#else
#define FLASH_BUFFER_SIZE ((WORD)(SECTOR_LEN+1)) //LIMIT 4096 Bytes
#endif
#if defined(__PIC24F__)
#define PROPER_SPICON1 (0x013B) //1:1 (1ºpre) 2:1 (2ºpre) 8Mhz CKE=1, MASTER mode
#elif defined(__PIC32MX__)
#define PROPER_SPICON1 (_SPI2CON_ON_MASK | _SPI2CON_FRZ_MASK | _SPI2CON_CKE_MASK | _SPI2CON_MSTEN_MASK)
#else //24H
#define PROPER_SPICON1 (0x21)
#endif
//Dummy RAM
unsigned char DummyMaster=0;
unsigned char tmpOut=0;
unsigned char ctny=0;
BYTE XFSHRAMBuf[FLASH_BUFFER_SIZE]={0x0};
//read pointer
static WORD SPICON1Save;
static DWORD FLASHAddress=0;
static BYTE *FLASHBufferPtr=0;
unsigned int LimitBytesToWrite=0;
unsigned int BytesWritten=0;
unsigned int BlockNumber;
unsigned int SectorNumber;
unsigned int PageNumber;
unsigned int SectorIndex;
unsigned int myPtr=0;
DWORD StoredAddress;
DWORD BlockStart;
DWORD BlockEnd;
DWORD SectorStart;
DWORD SectorEnd;
DWORD PageStart;
DWORD PageEnd;
DWORD SaveSectorStart;
/* FAST MACROS */
/*
| These macros avoid the so-called "RCALL" and "CALL"
| saving instructions and increasing the speed
|__________________________________________________*/
#define CSON (0)
#define CSOFF (1)
#define SetCS(x) ctny=FLASH_CS_WAIT; \
if(x){ while(ctny--); FLASH_CS_IO=x; }else{ FLASH_CS_IO=x; while(ctny--);}
#if defined (__PIC32MX__)
static inline __attribute__((always_inline)) void putcSPI(unsigned int data_out)
{ mSPI2BusyWait(); putcSPI2(data_out);}
static inline __attribute__((always_inline)) unsigned int getcSPI(void)
{ mSPI2BusyWait(); return getcSPI2();}
#define writeXSFHSPI(x) putcSPI(x)
#define readXSFHSPI(x) x = getcSPI();
#else
//8bits method with flush buffer
#define writeXSFHSPI(x) \
FLASH_SSPBUF = x; \
while(!FLASH_SPI_IF); \
DummyMaster = FLASH_SSPBUF; \
FLASH_SPI_IF = 0;
//8bits method with flush buffer
#define readXSFHSPI(x) \
FLASH_SSPBUF =0; \
while(!FLASH_SPI_IF); \
x = FLASH_SSPBUF; \
FLASH_SPI_IF = 0;
#endif
//allows the simultaneous use of several devices on the same bus with different speeds
#define saveSPISPEED() SPICON1Save = FLASH_SPICON1; FLASH_SPICON1 = FLASH_SPICON1
#define restoreSPISPEED() FLASH_SPICON1 = SPICON1Save
#if defined (_CONTROL_LBA_)
/* MyDB LBA */
/*
| LBA control is executed at another level
|__________________________________________________*/
FSHSettings FSHSetting;
unsigned long FlashSPEED;
void SetFSHSetting(void)
{
FlashSPEED = FLASH_MAX_SPI_FREQ;
FSHSetting.FSHSWAPFLAGSADDRESS = (UInt32)(FSH_SWAP_FLAGS_ADDRESS);
FSHSetting.FSHSWAPSIZE = (UInt16)(FSH_SWAP_SIZE);
FSHSetting.FSHVIRTUALPAGEADDRESS = (UInt32)(FSH_VIRTUAL_PAGE_ADDRESS);
FSHSetting.FSHVIRTUALPAGESIZE = (UInt16)(FSH_VIRTUAL_PAGE_SIZE);
FSHSetting.FSHSETTINGADDRESS = (UInt32)(FSH_SETTING_ADDRESS);
FSHSetting.FSHSETTINGSIZE = (UInt16)(FSH_SETTING_SIZE);
FSHSetting.FSHBACKUPADDRESS = (UInt32)(FSH_BACKUP_ADDRESS);
FSHSetting.FSHBACKUPSIZE = (UInt16)(FSH_BACKUP_SIZE);
FSHSetting.FSHREGISTRYADDRESS = (UInt32)(FSH_REGISTRY_ADDRESS);
FSHSetting.FSHREGISTRYSIZE = (UInt16)(FSH_REGISTRY_SIZE);
FSHSetting.FSHLBAADDRESS = (UInt32)(FSH_LBA_ADDRESS);
FSHSetting.FSHLBASIZE = (UInt16)(FSH_LBA_SIZE);
#if defined (_LBA_FILESYSTEM_)
FSHSetting.FSHFSDATAADDRESS = (UInt32)(FSH_FS_DATA_ADDRESS);
FSHSetting.FSHFSDATASIZE = (UInt32)(FSH_FS_DATA_SIZE);
FSHSetting.FSHFSMAPADDRESS = (UInt32)(FSH_FS_MAP_ADDRESS);
FSHSetting.FSHFSMAPSIZE = (UInt32)(FSH_FS_MAP_SIZE);
#endif
}
#endif //defined (_CONTROL_LBA_)
/* XFSHInit(*perifericals frequency*) */
/*
| pbclk , use for PIC32
|__________________________________________________*/
void XFSHInit(int pbclk)
{
// SetFSHSetting(); //LBA set
FLASH_CS_TRIS = 0; // Drive SPI FLASH chip select pin
SetCS(CSOFF);
Setup_SCK(0); // Set SCK pin as an output
Setup_SDI(1); // Make sure SDI pin is an input
Setup_SDO(0); // Set SDO pin as an output
#if defined(__C30__)
FLASH_SPICON1 = PROPER_SPICON1; // See PROPER_SPICON1 definition above
FLASH_SPICON2 = 0;
FLASH_SPISTAT = 0; // clear SPI
SPI1CON1bits.MODE16 =0;
FLASH_SPISTATbits.SPIEN = 1;
#elif defined(__PIC32MX__)
FLASH_SPIBRG = (pbclk/8)/2ul/FLASH_MAX_SPI_FREQ;
FLASH_SPICON1bits.CKE = 1;
FLASH_SPICON1bits.MSTEN = 1;
FLASH_SPICON1bits.ON = 1;
#endif
//WP first set
FLASHSetReg();
}
/* XFSHBeginRead(*start address read*) */
/*
| start read with LBA control
|__________________________________________________*/
XFSH_RESULT XFSHBeginRead(unsigned long raddress)
{
#if defined (_CONTROL_LBA_)
// LBA_XFSHBeginRead(raddress); //control sectors partition
#endif
//read address storage
FLASHAddress = raddress;
//set limit of buffer
FLASHBufferPtr = XFSHRAMBuf + FLASH_BUFFER_SIZE;
return XFSH_SUCCESS;
}
/* XFSHRead() */
/*
|
|__________________________________________________*/
BYTE XFSHRead(void)
{
// Check if no more bytes are left in our local buffer
if( FLASHBufferPtr == (XFSHRAMBuf + FLASH_BUFFER_SIZE) )
{//if first call or read another page
// Get a new set of bytes
XFSHDynamicRead(FLASHAddress,XFSHRAMBuf,FLASH_BUFFER_SIZE);
FLASHAddress += FLASH_BUFFER_SIZE;
FLASHBufferPtr = XFSHRAMBuf;
breakpoint();
}
// Return a byte from our RAM buffer
return *FLASHBufferPtr++;
}
/* XFSHEndRead() */
/*
| end read with LBA control
|__________________________________________________*/
XFSH_RESULT XFSHEndRead(void)
{
#if defined (_CONTROL_LBA_)
// LBA_XFSHEndRead(raddress); //close open sectors
#endif
return XFSH_SUCCESS;
}
/* */
/*
|
|__________________________________________________*/
XFSH_RESULT XFSHDynamicRead(DWORD addressD,
BYTE *bufferD,
WORD lengthD)
{
while( XFSHIsBusy() );
SetCS(CSON);
#if defined(FLASH_HIGH_SPEED)
// Send FAST READ opcode
writeXSFHSPI(FREAD);
#else
// Send READ opcode
writeXSFHSPI(READ);
#endif
// Send address
writeXSFHSPI(((DWORD_VAL*)&addressD)->v[2]);
writeXSFHSPI(((DWORD_VAL*)&addressD)->v[1]);
writeXSFHSPI(((DWORD_VAL*)&addressD)->v[0]);
#if defined(FLASH_HIGH_SPEED)
// Send Dummy 8bit cycle opcode
writeXSFHSPI(DYFM);
#endif
while(lengthD--)
{
if(bufferD != 0){
readXSFHSPI(*bufferD);
*bufferD++;
}
};
SetCS(CSOFF);
restoreSPISPEED();
return XFSH_SUCCESS;
}
/* */
/*
|
|__________________________________________________*/
XFSH_RESULT XFSHBeginWrite(DWORD address)
{
#if defined (FLASH_SMALL_RAM)
unsigned int j;
unsigned long dym=0;
LocalizeAddress(address); //Localize Start Sector
//set limit byte in selected sector
LimitBytesToWrite = (SectorStart + (SECTOR_LEN+1)) - address;
BytesWritten=0;
FLASHEraseSector(FLASH_ST_VIRTUAL_SECTOR); //Erase Virtual(swap) Sector
//bytes saved, before starting to write
iA = (unsigned int)(address - SectorStart);
iE = (PAGE_LEN+1);
if(iA<=iE)
{//is first page
SectorIndex=0;
if(iA)
{
XFSHDynamicRead(SectorStart,
XFSHRAMBuf,
iA); //Export data in RAM
//volcate RAM in swap sector
DynamicWriteLenF(FLASH_ST_VIRTUAL_SECTOR,iA);
tempVirtualAddress = FLASH_ST_VIRTUAL_SECTOR + iA;
}else{
tempVirtualAddress = FLASH_ST_VIRTUAL_SECTOR;
}
}
else
{
//pages saved
iC = (unsigned int) floor(iA / iE);
//bytes to write in broken page
iD = (unsigned int) iA - ( iC * iE);
tempVirtualAddress = FLASH_ST_VIRTUAL_SECTOR;
PageStart=0;
for(j=0;j<iC;j++)
{
PageStart=dym + SectorStart;
SectorIndex=0;
XFSHDynamicRead(PageStart,
XFSHRAMBuf,
iE); //Export data in RAM
//volcate RAM in swap sector
DynamicWriteLenF(tempVirtualAddress,iE);
tempVirtualAddress += iE;
dym=(PAGE_LEN*(j+1))+(j+1);
}
if(iD)
{//if exist bytes in broken page
PageStart=dym + SectorStart;
SectorIndex=0;
XFSHDynamicRead(PageStart,
XFSHRAMBuf,
iD); //Export data in RAM
//volcate RAM in swap sector
DynamicWriteLenF(tempVirtualAddress,iD);
tempVirtualAddress += iD;
}
}
FLASHBufferPtr = XFSHRAMBuf;
return XFSH_SUCCESS;
#else
LocalizeAddress(address); //Localize Start Sector
XFSHDynamicRead(SectorStart,
XFSHRAMBuf,
(SECTOR_LEN+1)); //Save Sector in Buffer
FLASHEraseSector(SectorStart); //Erase Sector
return XFSH_SUCCESS;
#endif
}
/* */
/*
|
|__________________________________________________*/
XFSH_RESULT XFSHWrite(BYTE val)
{
#if defined (FLASH_SMALL_RAM)
if( FLASHBufferPtr == (XFSHRAMBuf + FLASH_BUFFER_SIZE) )
{
FLASHBufferPtr = XFSHRAMBuf;
//write in FLASH swap sector
DynamicWriteLenF(tempVirtualAddress,FLASH_BUFFER_SIZE);
tempVirtualAddress += FLASH_BUFFER_SIZE;
}
//control sector partition
if((BytesWritten++)>=LimitBytesToWrite)
{//format a new sector
XFSHEndWrite(); //close current sector
//SaveSectorStart = SectorStart;
XFSHBeginWrite(SectorStart); //start new sector
}
*FLASHBufferPtr++ = val;
return XFSH_SUCCESS;
#else
//write in ram
XFSHRAMBuf[SectorIndex] = val;
SectorIndex++;
return XFSH_SUCCESS;
#endif
}
/* */
/*
|
|__________________________________________________*/
XFSH_RESULT XFSHEndWrite(void)
{
#if defined (FLASH_SMALL_RAM)
unsigned int j;
unsigned long dym=0;
//pre STEP) volcate pending RAM buffer in FLASH Swap Sector
if( FLASHBufferPtr != (&XFSHRAMBuf[0]) )
{
//bytes in RAM buffer
iA = ((unsigned int) FLASHBufferPtr) - ((unsigned int)(&XFSHRAMBuf[0]));
//volcate RAM in FLASH swap sector
DynamicWriteLenF(tempVirtualAddress,iA);
tempVirtualAddress += iA;
}
//1º STEP) ORIGIN DATA FLASH SECTOR -> RAM -> SWAP DATA FLASH SECTOR
//bytes written
iA = (unsigned int)tempVirtualAddress - FLASH_ST_VIRTUAL_SECTOR;
//bytes to write
iB = (unsigned int)FLASH_EN_VIRTUAL_SECTOR - tempVirtualAddress;
if(tempVirtualAddress < FLASH_EN_VIRTUAL_SECTOR)
{
if(iB < (PAGE_LEN + 1))
{//if lack a single page
SectorIndex=0;
XFSHDynamicRead((DWORD)SectorStart+iA,
XFSHRAMBuf,
iB); //Export data in RAM
//volcate RAM in FLASH swap sector
DynamicWriteLenF(tempVirtualAddress,iB);
}
else
{
if(iA<=(PAGE_LEN+1))
{
//written only in broken page
iC = 1;
//bytes to write in broken page
iE = (unsigned int) (PAGE_LEN + 1) - iA;
}
else
{
//pages written
iC = (unsigned int) floor(iA / (PAGE_LEN + 1));
//bytes written in broken page
iD = (unsigned int) iA - ( iC * (PAGE_LEN + 1));
//bytes to write in broken page
iE = (unsigned int) (PAGE_LEN + 1) - iD;
}
if(iE)
{
if(iC>1)iC+=1;
SectorIndex=0;
XFSHDynamicRead((DWORD)SectorStart+iA,
XFSHRAMBuf,
iE); //Export data in RAM
//volcate RAM in FLASH swap sector
DynamicWriteLenF(tempVirtualAddress,iE);
tempVirtualAddress += iE;
}
iE = (PAGE_LEN+1);
dym = iE*iC;
for(j=iC;j<16;j++){
PageStart=dym + SectorStart;
SectorIndex=0;
XFSHDynamicRead(PageStart,
XFSHRAMBuf,
iE); //Export data in RAM
//volcate RAM in swap sector
DynamicWriteLenF(tempVirtualAddress,iE);
tempVirtualAddress += iE;
dym=(PAGE_LEN*(j+1))+(j+1);
}
}
}
//2º STEP) SWAP DATA FLASH SECTOR -> RAM -> DESTINY DATA FLASH SECTOR
FLASHEraseSector(SectorStart); //Erase Sector
PageStart=0;
dym=0;
for(j=0;j<16;j++)
{
PageStart=dym + FLASH_ST_VIRTUAL_SECTOR;
SectorIndex=0;
XFSHDynamicRead(PageStart,
XFSHRAMBuf,
iE); //Export data in RAM
//volcate RAM in destiny sector
DynamicWriteLenF(SectorStart,iE);
SectorStart += iE;
dym=(PAGE_LEN*(j+1))+(j+1);
}
return XFSH_SUCCESS;
#else
int j;
long dym=0;
PageStart=0;
for(j=0;j<16;j++){
PageStart=dym + SectorStart;
DynamicWriteF(PageStart);
dym=(PAGE_LEN*(j+1))+(j+1);
}
return XFSH_SUCCESS;
#endif
}
/* */
/*
|
|__________________________________________________*/
void DynamicWriteLenF(DWORD dwAddress,WORD lenBuf)
{
WORD DynamicBytes =lenBuf;
myPtr=0;
while(FLASHReadCheck()!=ALL_OPEN)
{FLASHSetWEL(1);}
saveSPISPEED();
SetCS(CSON); //ON
// Send WRITE opcode
writeXSFHSPI(WRITE);
// Send address
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[2]);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[1]);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[0]);
while(DynamicBytes--)
{
// Send the byte to write
writeXSFHSPI(XFSHRAMBuf[myPtr]);
myPtr++;
}
SetCS(CSOFF); //OFF
restoreSPISPEED();
// Wait for write to complete
while( XFSHIsBusy() );
}
/* NAND FLASH ALGORITHMIC FUNCTIONS */
/*
|
|__________________________________________________*/
BOOL FLASHReadID(void)
{
static BYTE tempB[3];
saveSPISPEED();
// Activate chip select
SetCS(CSON);// SetCS(CSON); //ON
//send Read ID opcode
writeXSFHSPI(RDID);
//Read ID Manufactured
readXSFHSPI(tempB[0]);
// Read Memory Type
readXSFHSPI(tempB[1]);
// Read Memory Density
readXSFHSPI(tempB[2]);
SetCS(CSOFF);
restoreSPISPEED();
if((tempB[0]==IDMF)&&(tempB[1]==TYMF)) //control ID & Type Memory
return TRUE;
else
return FALSE;
}
/*
|
|__________________________________________________*/
XFSH_RESULT FLASHEraseSector(DWORD dwAddress)
{
while(FLASHReadCheck()!=ALL_OPEN)
{FLASHSetWEL(1);}
saveSPISPEED();
// Activate chip select
SetCS(CSON); //ON
// Send Erase Sector opcode
writeXSFHSPI(SEFM);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[2]);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[1]);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[0]);
SetCS(CSOFF); //OFF
restoreSPISPEED();
while(XFSHIsBusy());
return XFSH_SUCCESS;
}
/*
|
|__________________________________________________*/
XFSH_RESULT FLASHEraseBlock(DWORD dwAddress)
{
while(FLASHReadCheck()!=ALL_OPEN)
{FLASHSetWEL(1);}
saveSPISPEED();
// Activate chip select
SetCS(CSON); //ON
// Send Erase Block opcode
writeXSFHSPI(BEFM);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[2]);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[1]);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[0]);
SetCS(CSOFF); //OFF
restoreSPISPEED();
while(XFSHIsBusy());
return XFSH_SUCCESS;
}
/*
|
|__________________________________________________*/
XFSH_RESULT FLASHEraseChip(void)
{
while(FLASHReadCheck()!=ALL_OPEN)
{FLASHSetWEL(1);}
saveSPISPEED();
// Activate chip select
SetCS(CSON); //ON
// Send Erase Chip opcode
writeXSFHSPI(CEFM);
SetCS(CSOFF); //OFF
restoreSPISPEED();
while(XFSHIsBusy());
return XFSH_SUCCESS;
}
/*
| 0x00 free after write action
| 0x02 free after others actions
|__________________________________________________*/
BOOL XFSHIsBusy(void)
{
if((FLASHReadCheck()==0x00)||(FLASHReadCheck()==0x02))
return 0;
return 1;
}
/*
|
|
|__________________________________________________*/
BYTE FLASHReadCheck(void)
{
BYTE Dummy;
saveSPISPEED();
SetCS(CSON);
// send Read Status register
writeXSFHSPI(RDSR);
// Read Registry Byte
readXSFHSPI(Dummy);
SetCS(CSOFF);
restoreSPISPEED();
return Dummy;
}
/*
|
|
|__________________________________________________*/
static void FLASHSetReg(void)
{
FLASHSetWEL(1);
saveSPISPEED();
SetCS(CSON);
// Send Write Status Register opcode
writeXSFHSPI(WRSR);
// Send All Memory Write permit
writeXSFHSPI(ALL_OPEN);
SetCS(CSOFF);
restoreSPISPEED();
}
/*
|
|
|__________________________________________________*/
static void FLASHSetWEL(BYTE mode)
{
saveSPISPEED();
SetCS(CSON);
if(mode)
{
// Send Enable Write Status Register opcode
writeXSFHSPI(WREN);
}
else
{
// Send Disable Write Status Register opcode
writeXSFHSPI(WRDI);
}
SetCS(CSOFF);
restoreSPISPEED();
}
/*
|
| !REVISE THIS CODE!
| !cambiar con divisor!
|__________________________________________________*/
static BOOL LocalizeAddress(DWORD dwAddressL)
{
int i;
if(dwAddressL<=MAX_CHIP_ADDRESS)
{
BlockNumber=1;
SectorNumber=1;
PageNumber=1;
SectorStart=0;
SectorEnd=0;
PageStart=0;
PageEnd=0;
myPtr=0;
SectorIndex=0;
for(i=0;i<16;i++){
BlockEnd = (long)(BLOCK_LEN * BlockNumber)+i;
if(dwAddressL<=BlockEnd)break;
BlockStart = BlockEnd + 1;
BlockNumber++;
}
BlockNumber -= 1;
for(i=0;i<256;i++){
SectorEnd = (long)(SECTOR_LEN * SectorNumber)+i;
if(dwAddressL<=SectorEnd)break;
SectorStart = SectorEnd + 1;
SectorNumber++;
}
SectorNumber -= 1;
PageStart += SectorStart;
for(i=0;i<16;i++){
PageEnd =(long)((PAGE_LEN * PageNumber)+i) + SectorStart;
if(dwAddressL<=PageEnd)break;
PageStart = PageEnd + 1;
PageNumber++;
}
PageNumber -= 1;
StoredAddress = dwAddressL;
SectorIndex = StoredAddress - SectorStart;
return TRUE;
}
else
{
return FALSE;
}
}
/* INCLUDE_EXTENDS_METHOD */
#if defined(INCLUDE_EXTENDS_METHOD)
/* XFSHReadArray() */
/*
| microchip method use for Microchip File System
| not use for MyKOS File System
|__________________________________________________*/
XFSH_RESULT XFSHReadArray(DWORD address,
BYTE *buffer,
BYTE length)
{
saveSPISPEED();
SetCS(CSON);
#if defined(FLASH_HIGH_SPEED)
// Send FAST READ opcode
writeXSFHSPI(FREAD);
#else
// Send READ opcode
writeXSFHSPI(READ);
#endif
// Send address
writeXSFHSPI(((DWORD_VAL*)&address)->v[2]);
writeXSFHSPI(((DWORD_VAL*)&address)->v[1]);
writeXSFHSPI(((DWORD_VAL*)&address)->v[0]);
#if defined(FLASH_HIGH_SPEED)
// Send Dummy 8bit cycle opcode
writeXSFHSPI(DYFM);
#endif
while(length--)
{
if(buffer != 0){
readXSFHSPI(*buffer);
*buffer++;
}
};
SetCS(CSOFF);
restoreSPISPEED();
return XFSH_SUCCESS;
}
/* */
/*
|
|__________________________________________________*/
BYTE XFSHReadByte(DWORD addressD)
{
BYTE Dummy;
while( XFSHIsBusy() );
SetCS(CSON);
#if defined(FLASH_HIGH_SPEED)
// Send FAST READ opcode
writeXSFHSPI(FREAD);
#else
// Send READ opcode
writeXSFHSPI(READ);
#endif
// Send address
writeXSFHSPI(((DWORD_VAL*)&addressD)->v[2]);
writeXSFHSPI(((DWORD_VAL*)&addressD)->v[1]);
writeXSFHSPI(((DWORD_VAL*)&addressD)->v[0]);
#if defined(FLASH_HIGH_SPEED)
// Send Dummy 8bit cycle opcode
writeXSFHSPI(DYFM);
#endif
readXSFHSPI(Dummy);
SetCS(CSOFF);
restoreSPISPEED();
return Dummy;
}
/* */
/*
|
|__________________________________________________*/
void DynamicWriteF(DWORD dwAddress)
{
WORD DynamicBytes =0x100;
while(FLASHReadCheck()!=ALL_OPEN)
{FLASHSetWEL(1);}
saveSPISPEED();
// Activate chip select
SetCS(CSON); //ON
// Send WRITE opcode
writeXSFHSPI(WRITE);
// Send address
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[2]);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[1]);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[0]);
while(DynamicBytes--)
{
// Send the byte to write
writeXSFHSPI(XFSHRAMBuf[myPtr]);
myPtr++;
}
SetCS(CSOFF); //OFF
restoreSPISPEED();
// Wait for write to complete
while( XFSHIsBusy() );
}
/* */
/*
|
|__________________________________________________*/
void XFSHWriteByte(DWORD dwAddress,BYTE wByte)
{
myPtr=0;
while(FLASHReadCheck()!=ALL_OPEN)
{FLASHSetWEL(1);}
saveSPISPEED();
// Activate chip select
SetCS(CSON); //ON
// Send WRITE opcode
writeXSFHSPI(WRITE);
// Send address
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[2]);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[1]);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[0]);
// Send the byte to write
writeXSFHSPI(wByte);
SetCS(CSOFF); //OFF
restoreSPISPEED();
// Wait for write to complete
while( XFSHIsBusy() );
}
/* */
/*
|
|__________________________________________________*/
static void DoWriteF(void)
{
BYTE BytesToWrite;
while(FLASHReadCheck()!=ALL_OPEN)
{FLASHSetWEL(1);}
saveSPISPEED();
SetCS(CSON); //ON
// Send WRITE opcode
writeXSFHSPI(WRITE);
// Send address
writeXSFHSPI(((DWORD_VAL*)&FLASHAddress)->v[2]);
writeXSFHSPI(((DWORD_VAL*)&FLASHAddress)->v[1]);
writeXSFHSPI(((DWORD_VAL*)&FLASHAddress)->v[0]);
BytesToWrite = (BYTE)(FLASHBufferPtr - XFSHRAMBuf);
FLASHAddress += BytesToWrite;
FLASHBufferPtr = XFSHRAMBuf;
while(BytesToWrite--)
{
// Send the byte to write
writeXSFHSPI(*FLASHBufferPtr++);
}
SetCS(CSOFF); //OFF
FLASHBufferPtr = XFSHRAMBuf;
restoreSPISPEED();
// Wait for write to complete
while( XFSHIsBusy() );
}
#endif //defined(INCLUDE_EXTENDS_METHOD)
void PartitionXFSHchargeLBA(void)
{
UInt8 ix=0;
XFSHBeginRead(MYDB_P_LBA_ADDRESS);
for(ix=0;ix<MYDB_P_LBA_FLAGS_SIZE;ix++)
{
MyDBXFlashLBA[ix] = XFSHRead();
}
XFSHEndRead();
...
}
...
dPointer = XFSHMYDBPartition.Tables[jx].RAMAddress;
XFSHBeginWrite(XFSHMYDBPartition.Tables[jx].XFSHAddress);
for(ix=0;ix<(XFSHMYDBPartition.Tables[jx].SizeTable);ix++)
{
XFSHWrite(*dPointer++);
}
XFSHEndWrite();
...
}
madre mia mirconoob!
me acabas de liar aun más!
que se supone que tengo que utilizar la librería que me has dejado?
¿pero esa librería funciona con 25lc1024?
/* EJEMPLO CON UN MICRO 32BITS (de microchip claro esta!) */
//SPI FLASH MACRONIX
//#define MX25L8005 //Macronix 8mbit (1Mb)
#define FLASH_CS_TRIS (TRISGbits.TRISG13)
#define FLASH_CS_IO (LATGbits.LATG13)
#define FLASH_SCK_TRIS (TRISGbits.TRISG6)
#define FLASH_SDI_TRIS (TRISGbits.TRISG7)
#define FLASH_SDO_TRIS (TRISGbits.TRISG8)
#define Setup_SCK(rw) FLASH_SCK_TRIS=rw
#define Setup_SDI(rw) FLASH_SDI_TRIS=rw
#define Setup_SDO(rw) FLASH_SDO_TRIS=rw
#define FLASH_SPI_IF (IFS1bits.SPI2RXIF)
#define FLASH_SSPBUF (SPI2BUF)
#define FLASH_SPICON1 (SPI2CON)
#define FLASH_SPICON1bits (SPI2CONbits)
#define FLASH_SPIBRG (SPI2BRG)
/* EJEMPLO CON UN MICRO 16BITS E PPS */
//SPI FLASH MACRONIX with PPS
// #define MX25L8005 //Macronix 8mbit (1Mb)
#define FLASH_CS_TRIS (TRISAbits.TRISA7)
#define FLASH_CS_IO (LATAbits.LATA7)
#define FLASH_SCK_TRIS (TRISBbits.TRISB13)
#define Setup_SCK(rw) TRISBbits.TRISB13=rw; RPOR6bits.RP13R = 8
#define FLASH_SDI_TRIS (TRISBbits.TRISB14)
#define Setup_SDI(rw) TRISBbits.TRISB14=rw; RPINR20bits.SDI1R = 14
#define FLASH_SDO_TRIS (TRISBbits.TRISB15)
#define Setup_SDO(rw) TRISBbits.TRISB15=rw; RPOR7bits.RP15R = 7
#define FLASH_SPI_IF (IFS0bits.SPI1IF)
#define FLASH_SSPBUF (SPI1BUF)
#define FLASH_SPICON1 (SPI1CON1)
#define FLASH_SPICON1bits (SPI1CON1bits)
#define FLASH_SPICON2 (SPI1CON2)
#define FLASH_SPISTAT (SPI1STAT)
#define FLASH_SPISTATbits (SPI1STATbits)
/* EJEMPLO CON UN MICRO 8BITS */
//SPI FLASH MACRONIX
// #define MX25L8005 //Macronix 8mbit (1Mb)
#define FLASH_CS_TRIS (TRISGbits.TRISG13)
#define FLASH_CS_IO (LATGbits.LATG13)
#define FLASH_SCK_TRIS (TRISGbits.TRISG6)
#define FLASH_SDI_TRIS (TRISGbits.TRISG7)
#define FLASH_SDO_TRIS (TRISGbits.TRISG8)
#define Setup_SCK(rw) FLASH_SCK_TRIS=rw
#define Setup_SDI(rw) FLASH_SDI_TRIS=rw
#define Setup_SDO(rw) FLASH_SDO_TRIS=rw
#define FLASH_SPI_IF (PIR1bits.SSPIF)
#define FLASH_SSPBUF (SSPBUF)
#define FLASH_SPISTAT (SSPSTAT)
#define FLASH_SPISTATbits (SSPSTATbits)
#define FLASH_SPICON1 (SSPCON1)
#define FLASH_SPICON1bits (SSPCON1bits)
#define FLASH_SPICON2 (SSPCON2)
#define MC25AA1024
// FLASH SPI opcodes
#define READ 0x03 // lectura
#define WRITE 0x02 // escritura
#define WRDI 0x04 // deshabilitamos la escritura
#define WREN 0x06 // habilitamos la escritura
#define RDSR 0x05 // registro de lectura
#define WRSR 0x01 // registro de escritura
#define DYFM 0x00 // byte nulo
#if defined(MC25AA1024)
#define RDID 0xAB // lettura ID de el fabricante
#define PEFM 0x42 // borrado de una pagina
#define SEFM 0xD8 // borrado de un sector
#define CEFM 0xC7 // borrado de el Chip
#else
#define RDID 0x9F // lettura ID de el fabricante
#define SEFM 0x20 // borrado de un sector
#define BEFM 0x52 // borrado de un block
#define CEFM 0x60 // borrado de el Chip
#define FREAD 0x0B // lectura rapida
#endif
#define ALL_OPEN 0x02 // escritura habilitada + zona protegida en modalidad abierta
//este define activa la alta velocidad de lectura en memoria que la permiten
//#define FLASH_HIGH_SPEED //lectura max 50Mhz (other operation 25Mhz)
#define FLASH_LOW_SPEED //lectura max 25Mhz (other operation 25Mhz)
//este define activa el processo de ottimizacion de la ram y hace que el driver gaste solo 256bytes de ram y no 4096bytes
#define FLASH_SMALL_RAM
#define XFSH_SUCCESS (1u)
#if defined(MC25AA1024)
#define FLASH_ST_VIRTUAL_SECTOR (0x0001F000)
#define FLASH_EN_VIRTUAL_SECTOR (0x0001FFFF)
#define FLASH_CS_WAIT (1u)
#else
#define FLASH_ST_VIRTUAL_SECTOR (0x000FF000)
#define FLASH_EN_VIRTUAL_SECTOR (0x00100000)
#define FLASH_BIT_SPEED (8E6) //8Mhz
#define FLASH_CS_WAIT (INSTR_FREQ / FLASH_BIT_SPEED)
#endif
#if defined(MX25L8005)
#define MAX_CHIP_ADDRESS (0x0FFFFF)
#define BLOCK_LEN (65535ul)
#define SECTOR_LEN (4095ul)
#define PAGE_LEN (255ul)
#define IDMF (0xC2) //MACRONIX
#define TYMF (0x20)
#define DSMF (0x14)
#elif defined(MC25AA1024)
#define MAX_CHIP_ADDRESS (0x01FFFF)
#define BLOCK_LEN (65535ul)
#define SECTOR_LEN (4095ul)
#define PAGE_LEN (255ul)
#define IDMF (0x29) //MICROCHIP
#define TYMF (0x20)
#define DSMF (0x14)
#else
#error "NOT DEFINE FLASH MODEL"
#endif
#if defined(__PIC24F__)
#define PROPER_SPICON1 (0x013B) //1:1 (1ºpre) 2:1 (2ºpre) 8Mhz CKE=1, MASTER mode
#elif defined(__PIC32MX__)
#define PROPER_SPICON1 (_SPI2CON_ON_MASK | _SPI2CON_FRZ_MASK | _SPI2CON_CKE_MASK | _SPI2CON_MSTEN_MASK)
#else //24H
#define PROPER_SPICON1 (0x21)
#endif
typedef unsigned char BYTE; // 8-bit
typedef unsigned short int WORD; // 16-bit
typedef unsigned long DWORD; // 32-bit
typedef enum _BOOL { FALSE = 0, TRUE } BOOL;
typedef BOOL XFSH_RESULT;
typedef struct
{
BYTE b0: 1;
BYTE b1: 1;
BYTE b2: 1;
BYTE b3: 1;
BYTE b4: 1;
BYTE b5: 1;
BYTE b6: 1;
BYTE b7: 1;
}BYTE_BITS;
typedef struct
{
WORD b0: 1;
WORD b1: 1;
WORD b2: 1;
WORD b3: 1;
WORD b4: 1;
WORD b5: 1;
WORD b6: 1;
WORD b7: 1;
WORD b8: 1;
WORD b9: 1;
WORD b10: 1;
WORD b11: 1;
WORD b12: 1;
WORD b13: 1;
WORD b14: 1;
WORD b15: 1;
}WORD_BITS;
typedef union _BYTE_VAL
{
BYTE_BITS bits;
BYTE Val;
} BYTE_VAL;
typedef union _WORD_VAL
{
WORD Val;
WORD_BITS bits;
struct
{
BYTE LB;
BYTE HB;
} byte;
struct
{
BYTE_VAL low;
BYTE_VAL high;
}byteUnion;
BYTE v[2];
} WORD_VAL;
typedef union _DWORD_VAL
{
DWORD Val;
struct
{
BYTE LB;
BYTE HB;
BYTE UB;
BYTE MB;
} byte;
struct
{
WORD LW;
WORD HW;
} word;
struct
{
WORD_VAL low;
WORD_VAL high;
}wordUnion;
struct
{
BYTE_VAL lowLSB;
BYTE_VAL lowMSB;
BYTE_VAL highLSB;
BYTE_VAL highMSB;
}byteUnion;
BYTE v[4];
WORD w[2];
} DWORD_VAL;
#if defined (FLASH_SMALL_RAM)
#define FLASH_BUFFER_SIZE ((WORD)(PAGE_LEN+1)) //LIMIT 256 Bytes
#else
#define FLASH_BUFFER_SIZE ((WORD)(SECTOR_LEN+1)) //LIMIT 4096 Bytes
#endif
#if defined (FLASH_SMALL_RAM)
unsigned long tempVirtualAddress=0; //swap sector address
unsigned int iA=0,iB=0,iC=0,iD=0,iE=0; //unknowns
#endif
//Dummy RAM
unsigned char DummyMaster=0;
unsigned char tmpOut=0;
unsigned char ctny=0;
static WORD SPICON1Save;
static DWORD FLASHAddress=0;
static BYTE *FLASHBufferPtr=0;
unsigned int LimitBytesToWrite=0;
unsigned int BytesWritten=0;
unsigned int BlockNumber;
unsigned int SectorNumber;
unsigned int PageNumber;
unsigned int SectorIndex;
unsigned int myPtr=0;
DWORD StoredAddress;
DWORD BlockStart;
DWORD BlockEnd;
DWORD SectorStart;
DWORD SectorEnd;
DWORD PageStart;
DWORD PageEnd;
DWORD SaveSectorStart;
#pragma idata sectionBUFFERS
BYTE XFSHRAMBuf[FLASH_BUFFER_SIZE]={0x0};
#define CSON (0)
#define CSOFF (1)
#if defined (__PIC32MX__)
#define SetCS(x) ctny=FLASH_CS_WAIT; \
if(x){ while(ctny--); FLASH_CS_IO=x; }else{ FLASH_CS_IO=x; while(ctny--);}
#else
#define SetCS(x) FLASH_CS_IO=x
#endif
#if defined (__PIC32MX__)
static inline __attribute__((always_inline)) void putcSPI(unsigned int data_out)
{ mSPI2BusyWait(); putcSPI2(data_out);}
static inline __attribute__((always_inline)) unsigned int getcSPI(void)
{ mSPI2BusyWait(); return getcSPI2();}
#define writeXSFHSPI(x) putcSPI(x)
#define readXSFHSPI(x) x = getcSPI()
#else
//8bits method with flush buffer
#define writeXSFHSPI(x) \
FLASH_SSPBUF = x; \
while(!FLASH_SPI_IF); \
DummyMaster = FLASH_SSPBUF; \
FLASH_SPI_IF = 0;
//8bits method with flush buffer
#define readXSFHSPI(x) \
FLASH_SSPBUF =0; \
while(!FLASH_SPI_IF); \
x = FLASH_SSPBUF; \
FLASH_SPI_IF = 0;
#endif
#define saveSPISPEED() SPICON1Save = FLASH_SPICON1; FLASH_SPICON1 = FLASH_SPICON1
#define restoreSPISPEED() FLASH_SPICON1 = SPICON1Save
static BOOL XFSHIsBusy(void);
static BYTE FLASHReadCheck(void);
static void FLASHSetReg(void);
static void FLASHSetWEL(BYTE mode);
static BOOL LocalizeAddress(DWORD dwAddressL);
void DynamicWriteF(DWORD dwAddress);
void DynamicWriteLenF(DWORD dwAddress,WORD lenBuf);
XFSH_RESULT XFSHDynamicRead(DWORD addressD,BYTE *bufferD,WORD lengthD);
void SetFSHSetting(void);
XFSH_RESULT XFSHEndWrite(void);
/*
| FUNCIÓN PARA DETERMINAR EL ESTADO DE NUESTRA MEMORIA
|
|__________________________________________________*/
static BOOL XFSHIsBusy(void)
{
// ESCRIBIENDO PROTEGIDA
if((FLASHReadCheck()==0x00)||(FLASHReadCheck()==0x02))
return 0;
return 1;
}
/*
| ESTE METODO NOS DEVUELVE LA LECTURA DEL REGISTRO
| DE NUESTRA MEMORIA
|
|__________________________________________________*/
static BYTE FLASHReadCheck(void)
{
BYTE Dummy;
saveSPISPEED();
SetCS(CSON);
// ENVIAMOS LECTURA DEL REGISTRO
writeXSFHSPI(RDSR);
// LEEMOS INFORMACION
readXSFHSPI(Dummy);
SetCS(CSOFF);
restoreSPISPEED();
return Dummy;
}
/*
| ESTA FUNCIÓN HABILITA LA ESCRITURA TOTAL DE LA
| MEMORIA FLASH INCLUYENDO LOS SECTORES PROTEGIDOS
|
|__________________________________________________*/
static void FLASHSetReg(void)
{
FLASHSetWEL(1);
saveSPISPEED();
SetCS(CSON);
// ENVIAMOS ESCRITURA DE REGISTRO
writeXSFHSPI(WRSR);
// TODO PERMITIDO
writeXSFHSPI(ALL_OPEN);
SetCS(CSOFF);
restoreSPISPEED();
}
/*
| ESTA FUNCIÓN CONFIGURA EL REGISTRO DE ESCRITURA
|
|__________________________________________________*/
static void FLASHSetWEL(BYTE mode)
{
saveSPISPEED();
SetCS(CSON);
if(mode)
{
// HABILITAMOS EL REGISTRO DE ESCRITURA
writeXSFHSPI(WREN);
}
else
{
// DESHABILITAMOS EL REGISTRO DE ESCRITURA
writeXSFHSPI(WRDI);
}
SetCS(CSOFF);
restoreSPISPEED();
}
/*
| ESTA FUNCIÓN SIRVE PARA LOCALIZAR UNA DIRECCIÓN
| Y DEVOLVER SU BLOCK , SECTOR Y PAGINA
|
| EN LA VERSIÓN 2 DE LA LIBRERÍA HAY UN MÉTODO OPTIMIZADO
| PERO MUY PESADO PARA UN MICROS DE 8 BITS
|__________________________________________________*/
static BOOL LocalizeAddress(DWORD dwAddressL)
{
int i;
if(dwAddressL<=MAX_CHIP_ADDRESS)
{
BlockNumber=1;
SectorNumber=1;
PageNumber=1;
SectorStart=0;
SectorEnd=0;
PageStart=0;
PageEnd=0;
myPtr=0;
SectorIndex=0;
for(i=0;i<16;i++){
BlockEnd = (long)(BLOCK_LEN * BlockNumber)+i;
if(dwAddressL<=BlockEnd)break;
BlockStart = BlockEnd + 1;
BlockNumber++;
}
BlockNumber -= 1;
for(i=0;i<256;i++){
SectorEnd = (long)(SECTOR_LEN * SectorNumber)+i;
if(dwAddressL<=SectorEnd)break;
SectorStart = SectorEnd + 1;
SectorNumber++;
}
SectorNumber -= 1;
PageStart += SectorStart;
for(i=0;i<16;i++){
PageEnd =(long)((PAGE_LEN * PageNumber)+i) + SectorStart;
if(dwAddressL<=PageEnd)break;
PageStart = PageEnd + 1;
PageNumber++;
}
PageNumber -= 1;
StoredAddress = dwAddressL;
SectorIndex = StoredAddress - SectorStart;
return TRUE;
}
else
{
return FALSE;
}
}
/*
| ESTA FUNCIÓN SIRVE PARA COMPROBAR LOS DATOS IDENTIFICATIVOS
| DE NUESTRA MEMORIA QUE CORRESPONDAN A LOS DECLARADOS
|__________________________________________________*/
BOOL FLASHReadID(void)
{
static BYTE tempB[3];
saveSPISPEED();
SetCS(CSON);
//ENVIAMOS RDID OPCODE
writeXSFHSPI(RDID);
//LEEMOS EL FABRICANTE
readXSFHSPI(tempB[0]);
//LEEMOS EL TIPO
readXSFHSPI(tempB[1]);
// LEEMOS LA DENSIDAD
readXSFHSPI(tempB[2]);
SetCS(CSOFF);
restoreSPISPEED();
if((tempB[0]==IDMF)&&(tempB[1]==TYMF))
return TRUE;
else
return FALSE;
}
/*
| BORRADO DE UN SECTOR
|__________________________________________________*/
XFSH_RESULT FLASHEraseSector(DWORD dwAddress)
{
while(FLASHReadCheck()!=ALL_OPEN)
{FLASHSetWEL(1);}
saveSPISPEED();
SetCS(CSON);
writeXSFHSPI(SEFM);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[2]);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[1]);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[0]);
SetCS(CSOFF);
restoreSPISPEED();
while(XFSHIsBusy());
return XFSH_SUCCESS;
}
/*
| BORRADO DE UN BLOCK
|__________________________________________________*/
XFSH_RESULT FLASHEraseBlock(DWORD dwAddress)
{
while(FLASHReadCheck()!=ALL_OPEN)
{FLASHSetWEL(1);}
saveSPISPEED();
SetCS(CSON);
writeXSFHSPI(BEFM);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[2]);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[1]);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[0]);
SetCS(CSOFF);
restoreSPISPEED();
while(XFSHIsBusy());
return XFSH_SUCCESS;
}
/*
| BORRADO DE EL CHIP
|__________________________________________________*/
XFSH_RESULT FLASHEraseChip(void)
{
while(FLASHReadCheck()!=ALL_OPEN)
{FLASHSetWEL(1);}
saveSPISPEED();
SetCS(CSON);
writeXSFHSPI(CEFM);
SetCS(CSOFF);
restoreSPISPEED();
while(XFSHIsBusy());
return XFSH_SUCCESS;
}
/*
| ESTA FUNCION PREPARA NUESTRO DRIVER A RECIVIR DATOS
| PARA ESCRIBIR EN NUSTRA MEMORIA
|__________________________________________________*/
XFSH_RESULT XFSHBeginWrite(DWORD address)
{
#if defined (FLASH_SMALL_RAM)
unsigned int j;
unsigned long dym=0;
LocalizeAddress(address); //LOCALIZAMOS EL SECTOR
//CONFIGURAMOS EL LIMITE DE ESTE SECTOR
LimitBytesToWrite = (SectorStart + (SECTOR_LEN+1)) - address;
BytesWritten=0;
FLASHEraseSector(FLASH_ST_VIRTUAL_SECTOR); //BORRAMOS EL SECTOR DE RESPALDO
//CALCULAMOS EL NUMERO DE BYTES A ESCRIBIR ANTES DE LA DIRECCION DE ORIGEN
iA = (unsigned int)(address - SectorStart);
iE = (PAGE_LEN+1);
if(iA<=iE)
{//SI ES LA PRIMERA PAGINA DEL SECTOR
SectorIndex=0;
if(iA)
{
XFSHDynamicRead(SectorStart,
XFSHRAMBuf,
iA); //IMPORTAMOS LOS DATOS EN RAM
//VOLCAMOS LOS DATOS EN RAM EN EL SECTOR DE RESPALDO
DynamicWriteLenF(FLASH_ST_VIRTUAL_SECTOR,iA);
tempVirtualAddress = FLASH_ST_VIRTUAL_SECTOR + iA;
}else{
tempVirtualAddress = FLASH_ST_VIRTUAL_SECTOR;
}
}
else
{
//CALCULAMOS LA PAGINAS GUARDADAS EN EL SECTOR DE RESPALDO
iC = (unsigned int) floor(iA / iE);
//CALCULAMOS EL NUMERO DE BYTE QUE TENEMOS QUE ESCRIBIR EN LA PAGINA ANTES DE LLEGAR A SU FIN
iD = (unsigned int) iA - ( iC * iE);
tempVirtualAddress = FLASH_ST_VIRTUAL_SECTOR;
PageStart=0;
for(j=0;j<iC;j++)
{
PageStart=dym + SectorStart;
SectorIndex=0;
XFSHDynamicRead(PageStart,
XFSHRAMBuf,
iE); //IMPORTAMOS LOS DATOS EN RAM
//VOLCAMOS LOS DATOS EN RAM EN EL SECTOR DE RESPALDO
DynamicWriteLenF(tempVirtualAddress,iE);
tempVirtualAddress += iE;
dym=(PAGE_LEN*(j+1))+(j+1);
}
if(iD)
{//SI HAY BYTES DA ESCRIBIR EN LA PAGINA
PageStart=dym + SectorStart;
SectorIndex=0;
XFSHDynamicRead(PageStart,
XFSHRAMBuf,
iD); //IMPORTAMOS LOS DATOS EN RAM
//VOLCAMOS LOS DATOS EN RAM EN EL SECTOR DE RESPALDO
DynamicWriteLenF(tempVirtualAddress,iD);
tempVirtualAddress += iD;
}
}
FLASHBufferPtr = XFSHRAMBuf;
return XFSH_SUCCESS;
#else //METODO FULL RAM
LocalizeAddress(address); //LOCALIZAMOS EL SECTOR
XFSHDynamicRead(SectorStart,
XFSHRAMBuf,
(SECTOR_LEN+1)); //GUARDAMOS EL SECTOR EN RAM
FLASHEraseSector(SectorStart); //BORRAMOS EL SECTOR
return XFSH_SUCCESS;
#endif
}
/*
| FUNCION DE ENTRADA PARA ESCRIBIR EN LA FLASH
|__________________________________________________*/
XFSH_RESULT XFSHWrite(BYTE val)
{
#if defined (FLASH_SMALL_RAM)
if( FLASHBufferPtr == (XFSHRAMBuf + FLASH_BUFFER_SIZE) )
{
FLASHBufferPtr = XFSHRAMBuf;
//ESCRIBIMOS EN EL SECTOR DE RESPALDO
DynamicWriteLenF(tempVirtualAddress,FLASH_BUFFER_SIZE);
tempVirtualAddress += FLASH_BUFFER_SIZE;
}
//CONTROLAMOS QUE LA DIRECCION NO EXCEDA DEL ACTUAL SECTOR
if((BytesWritten++)>=LimitBytesToWrite)
{//SI ES UN NUEVO SECTOR
XFSHEndWrite(); //CERRAMOS EL ACTUAL SECTOR
XFSHBeginWrite(SectorStart); //ARRANCAMOS UN NUEVO SECTOR
}
*FLASHBufferPtr++ = val;
return XFSH_SUCCESS;
#else
//ESCRIBIMOS EN RAM
XFSHRAMBuf[SectorIndex] = val;
SectorIndex++;
return XFSH_SUCCESS;
#endif
}
/*
| FUNCION DE FINALIZACION DE ESCRITURA
|__________________________________________________*/
XFSH_RESULT XFSHEndWrite(void)
{
#if defined (FLASH_SMALL_RAM)
unsigned int j;
unsigned long dym=0;
//PASO PREVIO) VOLCAMOS EL BUFFER EN EL SECTOR DE RESPALDO
if( FLASHBufferPtr != (&XFSHRAMBuf[0]) )
{
//BYTE QUE HAY EN RAM
iA = ((unsigned int) FLASHBufferPtr) - ((unsigned int)(&XFSHRAMBuf[0]));
//VOLCAMOS LA RAM EN EL SECTOR DE RESPALDO
DynamicWriteLenF(tempVirtualAddress,iA);
tempVirtualAddress += iA;
}
//1º PASO) SECTOR DE ORIGEN -> RAM -> SECTOR DE RESPALDO
//BYTES ESCRITOS
iA = (unsigned int)tempVirtualAddress - FLASH_ST_VIRTUAL_SECTOR;
//BYTES PARA ESCRIBIR
iB = (unsigned int)FLASH_EN_VIRTUAL_SECTOR - tempVirtualAddress;
if(tempVirtualAddress < FLASH_EN_VIRTUAL_SECTOR)
{
if(iB < (PAGE_LEN + 1))
{//SI ES SOLO UNA PAGINA
SectorIndex=0;
XFSHDynamicRead((DWORD)SectorStart+iA,
XFSHRAMBuf,
iB); //IMPORTAMOS LOS DATOS EN RAM
//VOLCAMOS LOS DATOS EN RAM EN EL SECTOR DE RESPALDO
DynamicWriteLenF(tempVirtualAddress,iB);
}
else
{
if(iA<=(PAGE_LEN+1))
{
//ESCRITOS EN LA PAGINA ACTUAL
iC = 1;
//PARA ESCRIBIR EN LA PAGINA ACTUAL
iE = (unsigned int) (PAGE_LEN + 1) - iA;
}
else
{
//PAGINAS ESCRITAS
iC = (unsigned int) floor(iA / (PAGE_LEN + 1));
//ESCRITOS EN LA PAGINA ACTUAL
iD = (unsigned int) iA - ( iC * (PAGE_LEN + 1));
//PARA ESCRIBIR EN LA PAGINA ACTUAL
iE = (unsigned int) (PAGE_LEN + 1) - iD;
}
if(iE)
{
if(iC>1)iC+=1;
SectorIndex=0;
XFSHDynamicRead((DWORD)SectorStart+iA,
XFSHRAMBuf,
iE); //IMPORTAMOS LOS DATOS EN RAM
//VOLCAMOS LOS DATOS EN RAM EN EL SECTOR DE RESPALDO
DynamicWriteLenF(tempVirtualAddress,iE);
tempVirtualAddress += iE;
}
iE = (PAGE_LEN+1);
dym = iE*iC;
for(j=iC;j<16;j++){
PageStart=dym + SectorStart;
SectorIndex=0;
XFSHDynamicRead(PageStart,
XFSHRAMBuf,
iE); //IMPORTAMOS LOS DATOS EN RAM
//VOLCAMOS LOS DATOS EN RAM EN EL SECTOR DE RESPALDO
DynamicWriteLenF(tempVirtualAddress,iE);
tempVirtualAddress += iE;
dym=(PAGE_LEN*(j+1))+(j+1);
}
}
}
//2º PASO) SECTOR DE RESPALDO-> RAM -> SECTOR DE DESTINACION
FLASHEraseSector(SectorStart); //BORADO DE SECTOR
PageStart=0;
dym=0;
for(j=0;j<16;j++)
{
PageStart=dym + FLASH_ST_VIRTUAL_SECTOR;
SectorIndex=0;
XFSHDynamicRead(PageStart,
XFSHRAMBuf,
iE); ////IMPORTAMOS LOS DATOS EN RAM
//VOLCAMOS LOS DATOS EN RAM EN EL SECTOR DE DESTINACION
DynamicWriteLenF(SectorStart,iE);
SectorStart += iE;
dym=(PAGE_LEN*(j+1))+(j+1);
}
return XFSH_SUCCESS;
#else
int j;
long dym=0;
PageStart=0;
for(j=0;j<16;j++){
PageStart=dym + SectorStart;
DynamicWriteF(PageStart);
dym=(PAGE_LEN*(j+1))+(j+1);
}
return XFSH_SUCCESS;
#endif
}
/*
| FUNCION DE ESCRITURA
|__________________________________________________*/
void DynamicWriteLenF(DWORD dwAddress,WORD lenBuf)
{
WORD DynamicBytes =lenBuf;
myPtr=0;
while(FLASHReadCheck()!=ALL_OPEN)
{FLASHSetWEL(1);}
saveSPISPEED();
SetCS(CSON);
// ENVIO WRITE OPCODE
writeXSFHSPI(WRITE);
// ENVIAMOS DIRECCION
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[2]);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[1]);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[0]);
while(DynamicBytes--)
{
//ENVIAMOS BYTE PARA ESCRIBIR
writeXSFHSPI(XFSHRAMBuf[myPtr]);
myPtr++;
}
SetCS(CSOFF);
restoreSPISPEED();
// ESPERAMOS QUE ACABE
while( XFSHIsBusy() );
}
/*
| FUNCION QUE PREPARA EL DRIVER PARA LEER DESDE
| LA MEMORIA
|__________________________________________________*/
XFSH_RESULT XFSHBeginRead(unsigned long raddress)
{
//GUARDAMOS LA DIRECCION
FLASHAddress = raddress;
//CONFIGURAMOS EL BUFFER EN RAM
FLASHBufferPtr = XFSHRAMBuf + FLASH_BUFFER_SIZE;
return XFSH_SUCCESS;
}
/*
| FUNCION DE SALIDA
|__________________________________________________*/
BYTE XFSHRead(void)
{
// CONTROLAMOS QUE NO HAY NADA EN EL BUFFER
if( FLASHBufferPtr == (XFSHRAMBuf + FLASH_BUFFER_SIZE) )
{//SI ES LA PRIMERA LLAMADA
// LEEMOS UNA PAGINA
XFSHDynamicRead(FLASHAddress,XFSHRAMBuf,FLASH_BUFFER_SIZE);
FLASHAddress += FLASH_BUFFER_SIZE;
FLASHBufferPtr = XFSHRAMBuf;
}
// DEVOLVEMOS UN BYTE DESDE LA RAM
return *FLASHBufferPtr++;
}
/*
| FUNCION CIERRE DE LECTURA
| ESTA FUNCION SE USA EN EL CASO DE DEBER UTILIZAR
| EL DRIVER EN UN RTOS CON SEMAFOROS
|__________________________________________________*/
XFSH_RESULT XFSHEndRead(void)
{
#if defined (_CONTROL_LBA_)
LBA_XFSHEndRead(raddress);
#endif
return XFSH_SUCCESS;
}
/*
| FUNCIÓN DE ESCRITURA EN LA MEMORIA
|__________________________________________________*/
XFSH_RESULT XFSHDynamicRead(DWORD addressD,
BYTE *bufferD,
WORD lengthD)
{
while( XFSHIsBusy() );
SetCS(CSON);
#if defined(FLASH_HIGH_SPEED)
// ENVIO FAST READ OPCODE
writeXSFHSPI(FREAD);
#else
// ENVIO READ OPCODE
writeXSFHSPI(READ);
#endif
// ENVIO DE LA DIRECCION
writeXSFHSPI(((DWORD_VAL*)&addressD)->v[2]);
writeXSFHSPI(((DWORD_VAL*)&addressD)->v[1]);
writeXSFHSPI(((DWORD_VAL*)&addressD)->v[0]);
#if defined(FLASH_HIGH_SPEED)
// DUMMY CYCLE
writeXSFHSPI(DYFM);
#endif
while(lengthD--)
{
if(bufferD != 0){
readXSFHSPI(*bufferD);
*bufferD++;
}
};
SetCS(CSOFF);
restoreSPISPEED();
return XFSH_SUCCESS;
}
void XFSHInit(int pbclk)
{
FLASH_CS_TRIS = 0;
SetCS(CSOFF);
Setup_SCK(0);
Setup_SDI(1);
Setup_SDO(0);
#if defined(__C30__)
FLASH_SPICON1 = PROPER_SPICON1;
FLASH_SPICON2 = 0;
FLASH_SPISTAT = 0;
SPI1CON1bits.MODE16 =0;
FLASH_SPISTATbits.SPIEN = 1;
#elif defined(__PIC32MX__)
FLASH_SPIBRG = (pbclk/8)/2ul/FLASH_MAX_SPI_FREQ;
FLASH_SPICON1bits.CKE = 1;
FLASH_SPICON1bits.MSTEN = 1;
FLASH_SPICON1bits.ON = 1;
#elif defined(__18CXX)
FLASH_SPICON1 = 0x21;
FLASH_SPI_IF = 0;
FLASH_SPISTATbits.CKE = 1;
FLASH_SPISTATbits.SMP = 0;
#endif
FLASHSetReg();
}
void main(void)
{
BYTE C,ix;
XFSHInit(0); //inicializamos el driver
FLASHReadID(); //para debug llamamos esta funcion para ver si nuestra memoria contesta
//ESCRIBIMOS 10 bytes
XFSHBeginWrite(0x00000000);
XFSHWrite('E');
XFSHWrite('S');
XFSHWrite('T');
XFSHWrite('O');
XFSHWrite('Y');
XFSHWrite(' ');
XFSHWrite('V');
XFSHWrite('I');
XFSHWrite('V');
XFSHWrite('A');
XFSHEndWrite();
//LEEMOS 10 bytes
XFSHBeginRead(0x00000000);
for(ix=0;ix<10;ix++)
{
C = XFSHRead();
//aqui envias el la variable "C" por una serial o lcd o lo que sea
}
XFSHEndRead();
for(;;){ };
}
/*********************************************************************
*
* Data SPI FLASH Access Routines
*
*********************************************************************
* FileName: SPIFLASH.c
* Dependencies: None
* Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32MX
* Compiler: Microchip C32 v1.00 or higher
* Microchip C30 v3.01 or higher
* Microchip C18 v3.13 or higher
* HI-TECH PICC-18 STD 9.50PL3 or higher
* Company: Microchip Technology, Inc.
*
* Software License Agreement
*
* Copyright © 2002-2007 Microchip Technology Inc. All rights
* reserved.
*
* Microchip licenses to you the right to use, modify, copy, and
* distribute:
* (i) the Software when embedded on a Microchip microcontroller or
* digital signal controller product (“Device”) which is
* integrated into Licensee’s product; or
* (ii) ONLY the Software driver source files ENC28J60.c and
* ENC28J60.h ported to a non-Microchip device used in
* conjunction with a Microchip ethernet controller for the
* sole purpose of interfacing with the ethernet controller.
*
* You should refer to the license agreement accompanying this
* Software for additional information regarding your rights and
* obligations.
*
* THE SOFTWARE AND DOCUMENTATION ARE PROVIDED “AS IS” WITHOUT
* WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
* LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
* PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
* BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
* THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
* SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
* (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
*
*
* Author Date Comment
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Nilesh Rajbharti 5/20/02 Original (Rev. 1.0)
* Howard Schlunder 9/01/04 Rewritten for SPI EEPROMs
* Howard Schlunder 8/10/06 Modified to control SPI module
* frequency whenever EEPROM accessed
* to allow bus sharing with different
* frequencies.
* Maurizio Spoto 13/02/08 readapt for SPI FLASH MACRONIX
* Maurizio Spoto 8/08/08 readapt for PIC32MX
* Maurizio Spoto 5/08/09 mount LBA for MyDB table partition
* Maurizio Spoto 10/10/08 adding method for LOW_RAM ,
* adding SWAP sector for LOW_RAM
* optimized and unifique Buffering RX and TX
* Maurizio Spoto 11/10/08 adding method use NAND FLASH
* with Dynamic NOR FLASH and automatic
* partition in sequencial skip sector
* Maurizio Spoto 09/03/10 readapt for SPI FLASH MICROCHIP
********************************************************************/
#include <p18f4550.h>
#include <math.h>
//SPI FLASH MACRONIX
//#define MX25L8005 //Macronix 8mbit (1Mb)
#define FLASH_CS_TRIS (TRISAbits.TRISA1)
#define FLASH_CS_IO (LATAbits.LATA1)
#define FLASH_SCK_TRIS (TRISAbits.TRISA2)
#define FLASH_SDI_TRIS (TRISAbits.TRISA3)
#define FLASH_SDO_TRIS (TRISAbits.TRISA4)
#define Setup_SCK(rw) FLASH_SCK_TRIS=rw
#define Setup_SDI(rw) FLASH_SDI_TRIS=rw
#define Setup_SDO(rw) FLASH_SDO_TRIS=rw
#define FLASH_SPI_IF (PIR1bits.SSPIF)
#define FLASH_SSPBUF (SSPBUF)
#define FLASH_SPISTAT (SSPSTAT)
#define FLASH_SPISTATbits (SSPSTATbits)
#define FLASH_SPICON1 (SSPCON1)
#define FLASH_SPICON1bits (SSPCON1bits)
#define FLASH_SPICON2 (SSPCON2)
#define MC25AA1024
// FLASH SPI opcodes
#define READ 0x03 // lectura
#define WRITE 0x02 // escritura
#define WRDI 0x04 // deshabilitamos la escritura
#define WREN 0x06 // habilitamos la escritura
#define RDSR 0x05 // registro de lectura
#define WRSR 0x01 // registro de escritura
#define DYFM 0x00 // byte nulo
#if defined(MC25AA1024)
#define RDID 0xAB // lettura ID de el fabricante
#define PEFM 0x42 // borrado de una pagina
#define SEFM 0xD8 // borrado de un sector
#define CEFM 0xC7 // borrado de el Chip
#else
#define RDID 0x9F // lettura ID de el fabricante
#define SEFM 0x20 // borrado de un sector
#define BEFM 0x52 // borrado de un block
#define CEFM 0x60 // borrado de el Chip
#define FREAD 0x0B // lectura rapida
#endif
#define ALL_OPEN 0x02 // escritura habilitada + zona protegida en modalidad abierta
//este define activa la alta velocidad de lectura en memoria que la permiten
//#define FLASH_HIGH_SPEED //lectura max 50Mhz (other operation 25Mhz)
#define FLASH_LOW_SPEED //lectura max 25Mhz (other operation 25Mhz)
//este define activa el processo de ottimizacion de la ram y hace que el driver gaste solo 256bytes de ram y no 4096bytes
#define FLASH_SMALL_RAM
#define XFSH_SUCCESS (1u)
#if defined(MC25AA1024)
#define FLASH_ST_VIRTUAL_SECTOR (0x0001F000)
#define FLASH_EN_VIRTUAL_SECTOR (0x0001FFFF)
#define FLASH_CS_WAIT (1u)
#else
#define FLASH_ST_VIRTUAL_SECTOR (0x000FF000)
#define FLASH_EN_VIRTUAL_SECTOR (0x00100000)
#define FLASH_BIT_SPEED (8E6) //8Mhz
#define FLASH_CS_WAIT (INSTR_FREQ / FLASH_BIT_SPEED)
#endif
#if defined(MX25L8005)
#define MAX_CHIP_ADDRESS (0x0FFFFF)
#define BLOCK_LEN (65535ul)
#define SECTOR_LEN (4095ul)
#define PAGE_LEN (255ul)
#define IDMF (0xC2) //MACRONIX
#define TYMF (0x20)
#define DSMF (0x14)
#elif defined(MC25AA1024)
#define MAX_CHIP_ADDRESS (0x01FFFF)
#define BLOCK_LEN (65535ul)
#define SECTOR_LEN (4095ul)
#define PAGE_LEN (255ul)
#define IDMF (0x29) //MICROCHIP
#define TYMF (0x20)
#define DSMF (0x14)
#else
#error "NOT DEFINE FLASH MODEL"
#endif
typedef unsigned char BYTE; // 8-bit
typedef unsigned short int WORD; // 16-bit
typedef unsigned long DWORD; // 32-bit
typedef enum _BOOL { FALSE = 0, TRUE } BOOL;
typedef BOOL XFSH_RESULT;
typedef struct
{
BYTE b0: 1;
BYTE b1: 1;
BYTE b2: 1;
BYTE b3: 1;
BYTE b4: 1;
BYTE b5: 1;
BYTE b6: 1;
BYTE b7: 1;
}BYTE_BITS;
typedef struct
{
WORD b0: 1;
WORD b1: 1;
WORD b2: 1;
WORD b3: 1;
WORD b4: 1;
WORD b5: 1;
WORD b6: 1;
WORD b7: 1;
WORD b8: 1;
WORD b9: 1;
WORD b10: 1;
WORD b11: 1;
WORD b12: 1;
WORD b13: 1;
WORD b14: 1;
WORD b15: 1;
}WORD_BITS;
typedef union _BYTE_VAL
{
BYTE_BITS bits;
BYTE Val;
} BYTE_VAL;
typedef union _WORD_VAL
{
WORD Val;
WORD_BITS bits;
struct
{
BYTE LB;
BYTE HB;
} byte;
struct
{
BYTE_VAL low;
BYTE_VAL high;
}byteUnion;
BYTE v[2];
} WORD_VAL;
typedef union _DWORD_VAL
{
DWORD Val;
struct
{
BYTE LB;
BYTE HB;
BYTE UB;
BYTE MB;
} byte;
struct
{
WORD LW;
WORD HW;
} word;
struct
{
WORD_VAL low;
WORD_VAL high;
}wordUnion;
struct
{
BYTE_VAL lowLSB;
BYTE_VAL lowMSB;
BYTE_VAL highLSB;
BYTE_VAL highMSB;
}byteUnion;
BYTE v[4];
WORD w[2];
} DWORD_VAL;
#if defined (FLASH_SMALL_RAM)
#define FLASH_BUFFER_SIZE ((WORD)(PAGE_LEN+1)) //LIMIT 256 Bytes
#else
#define FLASH_BUFFER_SIZE ((WORD)(SECTOR_LEN+1)) //LIMIT 4096 Bytes
#endif
#if defined (FLASH_SMALL_RAM)
unsigned long tempVirtualAddress=0; //swap sector address
unsigned int iA=0,iB=0,iC=0,iD=0,iE=0; //unknowns
#endif
//Dummy RAM
unsigned char DummyMaster=0;
unsigned char tmpOut=0;
unsigned char ctny=0;
static WORD SPICON1Save;
static DWORD FLASHAddress=0;
static BYTE *FLASHBufferPtr=0;
unsigned int LimitBytesToWrite=0;
unsigned int BytesWritten=0;
unsigned int BlockNumber;
unsigned int SectorNumber;
unsigned int PageNumber;
unsigned int SectorIndex;
unsigned int myPtr=0;
DWORD StoredAddress;
DWORD BlockStart;
DWORD BlockEnd;
DWORD SectorStart;
DWORD SectorEnd;
DWORD PageStart;
DWORD PageEnd;
DWORD SaveSectorStart;
#pragma idata sectionBUFFERS
BYTE XFSHRAMBuf[FLASH_BUFFER_SIZE]={0x0};
#define CSON (0)
#define CSOFF (1)
#if defined (__PIC32MX__)
#define SetCS(x) ctny=FLASH_CS_WAIT; \
if(x){ while(ctny--); FLASH_CS_IO=x; }else{ FLASH_CS_IO=x; while(ctny--);}
#else
#define SetCS(x) FLASH_CS_IO=x;
#endif
#if defined (__PIC32MX__)
static inline __attribute__((always_inline)) void putcSPI(unsigned int data_out)
{ mSPI2BusyWait(); putcSPI2(data_out);}
static inline __attribute__((always_inline)) unsigned int getcSPI(void)
{ mSPI2BusyWait(); return getcSPI2();}
#define writeXSFHSPI(x) putcSPI(x)
#define readXSFHSPI(x) x = getcSPI()
#else
//8bits method with flush buffer
#define writeXSFHSPI(x) \
FLASH_SSPBUF = x; \
while(!FLASH_SPI_IF); \
DummyMaster = FLASH_SSPBUF; \
FLASH_SPI_IF = 0;
//8bits method with flush buffer
#define readXSFHSPI(x) \
FLASH_SSPBUF =0; \
while(!FLASH_SPI_IF); \
x = FLASH_SSPBUF; \
FLASH_SPI_IF = 0;
#endif
#define saveSPISPEED() SPICON1Save = FLASH_SPICON1; FLASH_SPICON1 = FLASH_SPICON1
#define restoreSPISPEED() FLASH_SPICON1 = SPICON1Save
static BOOL XFSHIsBusy(void);
static BYTE FLASHReadCheck(void);
static void FLASHSetReg(void);
static void FLASHSetWEL(BYTE mode);
static BOOL LocalizeAddress(DWORD dwAddressL);
void DynamicWriteF(DWORD dwAddress);
void DynamicWriteLenF(DWORD dwAddress,WORD lenBuf);
XFSH_RESULT XFSHDynamicRead(DWORD addressD,BYTE *bufferD,WORD lengthD);
void SetFSHSetting(void);
XFSH_RESULT XFSHEndWrite(void);
/*
| FUNCIÓN PARA DETERMINAR EL ESTADO DE NUESTRA MEMORIA
|
|__________________________________________________*/
static BOOL XFSHIsBusy(void)
{
// ESCRIBIENDO PROTEGIDA
if((FLASHReadCheck()==0x00)||(FLASHReadCheck()==0x02))
return 0;
return 1;
}
/*
| ESTE METODO NOS DEVUELVE LA LECTURA DEL REGISTRO
| DE NUESTRA MEMORIA
|
|__________________________________________________*/
static BYTE FLASHReadCheck(void)
{
BYTE Dummy;
saveSPISPEED();
SetCS(CSON);
// ENVIAMOS LECTURA DEL REGISTRO
writeXSFHSPI(RDSR);
// LEEMOS INFORMACION
readXSFHSPI(Dummy);
SetCS(CSOFF);
restoreSPISPEED();
return Dummy;
}
/*
| ESTA FUNCIÓN HABILITA LA ESCRITURA TOTAL DE LA
| MEMORIA FLASH INCLUYENDO LOS SECTORES PROTEGIDOS
|
|__________________________________________________*/
static void FLASHSetReg(void)
{
FLASHSetWEL(1);
saveSPISPEED();
SetCS(CSON);
// ENVIAMOS ESCRITURA DE REGISTRO
writeXSFHSPI(WRSR);
// TODO PERMITIDO
writeXSFHSPI(ALL_OPEN);
SetCS(CSOFF);
restoreSPISPEED();
}
/*
| ESTA FUNCIÓN CONFIGURA EL REGISTRO DE ESCRITURA
|
|__________________________________________________*/
static void FLASHSetWEL(BYTE mode)
{
saveSPISPEED();
SetCS(CSON);
if(mode)
{
// HABILITAMOS EL REGISTRO DE ESCRITURA
writeXSFHSPI(WREN);
}
else
{
// DESHABILITAMOS EL REGISTRO DE ESCRITURA
writeXSFHSPI(WRDI);
}
SetCS(CSOFF);
restoreSPISPEED();
}
/*
| ESTA FUNCIÓN SIRVE PARA LOCALIZAR UNA DIRECCIÓN
| Y DEVOLVER SU BLOCK , SECTOR Y PAGINA
|
| EN LA VERSIÓN 2 DE LA LIBRERÍA HAY UN MÉTODO OPTIMIZADO
| PERO MUY PESADO PARA UN MICROS DE 8 BITS
|__________________________________________________*/
static BOOL LocalizeAddress(DWORD dwAddressL)
{
int i;
if(dwAddressL<=MAX_CHIP_ADDRESS)
{
BlockNumber=1;
SectorNumber=1;
PageNumber=1;
SectorStart=0;
SectorEnd=0;
PageStart=0;
PageEnd=0;
myPtr=0;
SectorIndex=0;
for(i=0;i<16;i++){
BlockEnd = (long)(BLOCK_LEN * BlockNumber)+i;
if(dwAddressL<=BlockEnd)break;
BlockStart = BlockEnd + 1;
BlockNumber++;
}
BlockNumber -= 1;
for(i=0;i<256;i++){
SectorEnd = (long)(SECTOR_LEN * SectorNumber)+i;
if(dwAddressL<=SectorEnd)break;
SectorStart = SectorEnd + 1;
SectorNumber++;
}
SectorNumber -= 1;
PageStart += SectorStart;
for(i=0;i<16;i++){
PageEnd =(long)((PAGE_LEN * PageNumber)+i) + SectorStart;
if(dwAddressL<=PageEnd)break;
PageStart = PageEnd + 1;
PageNumber++;
}
PageNumber -= 1;
StoredAddress = dwAddressL;
SectorIndex = StoredAddress - SectorStart;
return TRUE;
}
else
{
return FALSE;
}
}
/*
| ESTA FUNCIÓN SIRVE PARA COMPROBAR LOS DATOS IDENTIFICATIVOS
| DE NUESTRA MEMORIA QUE CORRESPONDAN A LOS DECLARADOS
|__________________________________________________*/
BOOL FLASHReadID(void)
{
static BYTE tempB[3];
saveSPISPEED();
SetCS(CSON);
//ENVIAMOS RDID OPCODE
writeXSFHSPI(RDID);
//LEEMOS EL FABRICANTE
readXSFHSPI(tempB[0]);
//LEEMOS EL TIPO
readXSFHSPI(tempB[1]);
// LEEMOS LA DENSIDAD
readXSFHSPI(tempB[2]);
SetCS(CSOFF);
restoreSPISPEED();
if((tempB[0]==IDMF)&&(tempB[1]==TYMF))
return TRUE;
else
return FALSE;
}
/*
| BORRADO DE UN SECTOR
|__________________________________________________*/
XFSH_RESULT FLASHEraseSector(DWORD dwAddress)
{
while(FLASHReadCheck()!=ALL_OPEN)
{FLASHSetWEL(1);}
saveSPISPEED();
SetCS(CSON);
writeXSFHSPI(SEFM);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[2]);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[1]);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[0]);
SetCS(CSOFF);
restoreSPISPEED();
while(XFSHIsBusy());
return XFSH_SUCCESS;
}
#if !defined(MC25AA1024)
/*
| BORRADO DE UN BLOCK
|__________________________________________________*/
XFSH_RESULT FLASHEraseBlock(DWORD dwAddress)
{
while(FLASHReadCheck()!=ALL_OPEN)
{FLASHSetWEL(1);}
saveSPISPEED();
SetCS(CSON);
writeXSFHSPI(BEFM);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[2]);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[1]);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[0]);
SetCS(CSOFF);
restoreSPISPEED();
while(XFSHIsBusy());
return XFSH_SUCCESS;
}
#endif
/*
| BORRADO DE EL CHIP
|__________________________________________________*/
XFSH_RESULT FLASHEraseChip(void)
{
while(FLASHReadCheck()!=ALL_OPEN)
{FLASHSetWEL(1);}
saveSPISPEED();
SetCS(CSON);
writeXSFHSPI(CEFM);
SetCS(CSOFF);
restoreSPISPEED();
while(XFSHIsBusy());
return XFSH_SUCCESS;
}
/*
| ESTA FUNCION PREPARA NUESTRO DRIVER A RECIVIR DATOS
| PARA ESCRIBIR EN NUSTRA MEMORIA
|__________________________________________________*/
XFSH_RESULT XFSHBeginWrite(DWORD address)
{
#if defined (FLASH_SMALL_RAM)
unsigned int j;
unsigned long dym=0;
LocalizeAddress(address); //LOCALIZAMOS EL SECTOR
//CONFIGURAMOS EL LIMITE DE ESTE SECTOR
LimitBytesToWrite = (SectorStart + (SECTOR_LEN+1)) - address;
BytesWritten=0;
FLASHEraseSector(FLASH_ST_VIRTUAL_SECTOR); //BORRAMOS EL SECTOR DE RESPALDO
//CALCULAMOS EL NUMERO DE BYTES A ESCRIBIR ANTES DE LA DIRECCION DE ORIGEN
iA = (unsigned int)(address - SectorStart);
iE = (PAGE_LEN+1);
if(iA<=iE)
{//SI ES LA PRIMERA PAGINA DEL SECTOR
SectorIndex=0;
if(iA)
{
XFSHDynamicRead(SectorStart,
XFSHRAMBuf,
iA); //IMPORTAMOS LOS DATOS EN RAM
//VOLCAMOS LOS DATOS EN RAM EN EL SECTOR DE RESPALDO
DynamicWriteLenF(FLASH_ST_VIRTUAL_SECTOR,iA);
tempVirtualAddress = FLASH_ST_VIRTUAL_SECTOR + iA;
}else{
tempVirtualAddress = FLASH_ST_VIRTUAL_SECTOR;
}
}
else
{
//CALCULAMOS LA PAGINAS GUARDADAS EN EL SECTOR DE RESPALDO
iC = (unsigned int) floor(iA / iE);
//CALCULAMOS EL NUMERO DE BYTE QUE TENEMOS QUE ESCRIBIR EN LA PAGINA ANTES DE LLEGAR A SU FIN
iD = (unsigned int) iA - ( iC * iE);
tempVirtualAddress = FLASH_ST_VIRTUAL_SECTOR;
PageStart=0;
for(j=0;j<iC;j++)
{
PageStart=dym + SectorStart;
SectorIndex=0;
XFSHDynamicRead(PageStart,
XFSHRAMBuf,
iE); //IMPORTAMOS LOS DATOS EN RAM
//VOLCAMOS LOS DATOS EN RAM EN EL SECTOR DE RESPALDO
DynamicWriteLenF(tempVirtualAddress,iE);
tempVirtualAddress += iE;
dym=(PAGE_LEN*(j+1))+(j+1);
}
if(iD)
{//SI HAY BYTES DA ESCRIBIR EN LA PAGINA
PageStart=dym + SectorStart;
SectorIndex=0;
XFSHDynamicRead(PageStart,
XFSHRAMBuf,
iD); //IMPORTAMOS LOS DATOS EN RAM
//VOLCAMOS LOS DATOS EN RAM EN EL SECTOR DE RESPALDO
DynamicWriteLenF(tempVirtualAddress,iD);
tempVirtualAddress += iD;
}
}
FLASHBufferPtr = XFSHRAMBuf;
return XFSH_SUCCESS;
#else //METODO FULL RAM
LocalizeAddress(address); //LOCALIZAMOS EL SECTOR
XFSHDynamicRead(SectorStart,
XFSHRAMBuf,
(SECTOR_LEN+1)); //GUARDAMOS EL SECTOR EN RAM
FLASHEraseSector(SectorStart); //BORRAMOS EL SECTOR
return XFSH_SUCCESS;
#endif
}
/*
| FUNCION DE ENTRADA PARA ESCRIBIR EN LA FLASH
|__________________________________________________*/
XFSH_RESULT XFSHWrite(BYTE val)
{
#if defined (FLASH_SMALL_RAM)
if( FLASHBufferPtr == (XFSHRAMBuf + FLASH_BUFFER_SIZE) )
{
FLASHBufferPtr = XFSHRAMBuf;
//ESCRIBIMOS EN EL SECTOR DE RESPALDO
DynamicWriteLenF(tempVirtualAddress,FLASH_BUFFER_SIZE);
tempVirtualAddress += FLASH_BUFFER_SIZE;
}
//CONTROLAMOS QUE LA DIRECCION NO EXCEDA DEL ACTUAL SECTOR
if((BytesWritten++)>=LimitBytesToWrite)
{//SI ES UN NUEVO SECTOR
XFSHEndWrite(); //CERRAMOS EL ACTUAL SECTOR
XFSHBeginWrite(SectorStart); //ARRANCAMOS UN NUEVO SECTOR
}
*FLASHBufferPtr++ = val;
return XFSH_SUCCESS;
#else
//ESCRIBIMOS EN RAM
XFSHRAMBuf[SectorIndex] = val;
SectorIndex++;
return XFSH_SUCCESS;
#endif
}
/*
| FUNCION DE FINALIZACION DE ESCRITURA
|__________________________________________________*/
XFSH_RESULT XFSHEndWrite(void)
{
#if defined (FLASH_SMALL_RAM)
unsigned int j;
unsigned long dym=0;
//PASO PREVIO) VOLCAMOS EL BUFFER EN EL SECTOR DE RESPALDO
if( FLASHBufferPtr != (&XFSHRAMBuf[0]) )
{
//BYTE QUE HAY EN RAM
iA = ((unsigned int) FLASHBufferPtr) - ((unsigned int)(&XFSHRAMBuf[0]));
//VOLCAMOS LA RAM EN EL SECTOR DE RESPALDO
DynamicWriteLenF(tempVirtualAddress,iA);
tempVirtualAddress += iA;
}
//1º PASO) SECTOR DE ORIGEN -> RAM -> SECTOR DE RESPALDO
//BYTES ESCRITOS
iA = (unsigned int)tempVirtualAddress - FLASH_ST_VIRTUAL_SECTOR;
//BYTES PARA ESCRIBIR
iB = (unsigned int)FLASH_EN_VIRTUAL_SECTOR - tempVirtualAddress;
if(tempVirtualAddress < FLASH_EN_VIRTUAL_SECTOR)
{
if(iB < (PAGE_LEN + 1))
{//SI ES SOLO UNA PAGINA
SectorIndex=0;
XFSHDynamicRead((DWORD)SectorStart+iA,
XFSHRAMBuf,
iB); //IMPORTAMOS LOS DATOS EN RAM
//VOLCAMOS LOS DATOS EN RAM EN EL SECTOR DE RESPALDO
DynamicWriteLenF(tempVirtualAddress,iB);
}
else
{
if(iA<=(PAGE_LEN+1))
{
//ESCRITOS EN LA PAGINA ACTUAL
iC = 1;
//PARA ESCRIBIR EN LA PAGINA ACTUAL
iE = (unsigned int) (PAGE_LEN + 1) - iA;
}
else
{
//PAGINAS ESCRITAS
iC = (unsigned int) floor(iA / (PAGE_LEN + 1));
//ESCRITOS EN LA PAGINA ACTUAL
iD = (unsigned int) iA - ( iC * (PAGE_LEN + 1));
//PARA ESCRIBIR EN LA PAGINA ACTUAL
iE = (unsigned int) (PAGE_LEN + 1) - iD;
}
if(iE)
{
if(iC>1)iC+=1;
SectorIndex=0;
XFSHDynamicRead((DWORD)SectorStart+iA,
XFSHRAMBuf,
iE); //IMPORTAMOS LOS DATOS EN RAM
//VOLCAMOS LOS DATOS EN RAM EN EL SECTOR DE RESPALDO
DynamicWriteLenF(tempVirtualAddress,iE);
tempVirtualAddress += iE;
}
iE = (PAGE_LEN+1);
dym = iE*iC;
for(j=iC;j<16;j++){
PageStart=dym + SectorStart;
SectorIndex=0;
XFSHDynamicRead(PageStart,
XFSHRAMBuf,
iE); //IMPORTAMOS LOS DATOS EN RAM
//VOLCAMOS LOS DATOS EN RAM EN EL SECTOR DE RESPALDO
DynamicWriteLenF(tempVirtualAddress,iE);
tempVirtualAddress += iE;
dym=(PAGE_LEN*(j+1))+(j+1);
}
}
}
//2º PASO) SECTOR DE RESPALDO-> RAM -> SECTOR DE DESTINACION
FLASHEraseSector(SectorStart); //BORADO DE SECTOR
PageStart=0;
dym=0;
for(j=0;j<16;j++)
{
PageStart=dym + FLASH_ST_VIRTUAL_SECTOR;
SectorIndex=0;
XFSHDynamicRead(PageStart,
XFSHRAMBuf,
iE); ////IMPORTAMOS LOS DATOS EN RAM
//VOLCAMOS LOS DATOS EN RAM EN EL SECTOR DE DESTINACION
DynamicWriteLenF(SectorStart,iE);
SectorStart += iE;
dym=(PAGE_LEN*(j+1))+(j+1);
}
return XFSH_SUCCESS;
#else
int j;
long dym=0;
PageStart=0;
for(j=0;j<16;j++){
PageStart=dym + SectorStart;
DynamicWriteF(PageStart);
dym=(PAGE_LEN*(j+1))+(j+1);
}
return XFSH_SUCCESS;
#endif
}
/*
| FUNCION DE ESCRITURA
|__________________________________________________*/
void DynamicWriteLenF(DWORD dwAddress,WORD lenBuf)
{
WORD DynamicBytes =lenBuf;
myPtr=0;
while(FLASHReadCheck()!=ALL_OPEN)
{FLASHSetWEL(1);}
saveSPISPEED();
SetCS(CSON);
// ENVIO WRITE OPCODE
writeXSFHSPI(WRITE);
// ENVIAMOS DIRECCION
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[2]);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[1]);
writeXSFHSPI(((DWORD_VAL*)&dwAddress)->v[0]);
while(DynamicBytes--)
{
//ENVIAMOS BYTE PARA ESCRIBIR
writeXSFHSPI(XFSHRAMBuf[myPtr]);
myPtr++;
}
SetCS(CSOFF);
restoreSPISPEED();
// ESPERAMOS QUE ACABE
while( XFSHIsBusy() );
}
/*
| FUNCION QUE PREPARA EL DRIVER PARA LEER DESDE
| LA MEMORIA
|__________________________________________________*/
XFSH_RESULT XFSHBeginRead(unsigned long raddress)
{
//GUARDAMOS LA DIRECCION
FLASHAddress = raddress;
//CONFIGURAMOS EL BUFFER EN RAM
FLASHBufferPtr = XFSHRAMBuf + FLASH_BUFFER_SIZE;
return XFSH_SUCCESS;
}
/*
| FUNCION DE SALIDA
|__________________________________________________*/
BYTE XFSHRead(void)
{
// CONTROLAMOS QUE NO HAY NADA EN EL BUFFER
if( FLASHBufferPtr == (XFSHRAMBuf + FLASH_BUFFER_SIZE) )
{//SI ES LA PRIMERA LLAMADA
// LEEMOS UNA PAGINA
XFSHDynamicRead(FLASHAddress,XFSHRAMBuf,FLASH_BUFFER_SIZE);
FLASHAddress += FLASH_BUFFER_SIZE;
FLASHBufferPtr = XFSHRAMBuf;
}
// DEVOLVEMOS UN BYTE DESDE LA RAM
return *FLASHBufferPtr++;
}
/*
| FUNCION CIERRE DE LECTURA
| ESTA FUNCION SE USA EN EL CASO DE DEBER UTILIZAR
| EL DRIVER EN UN RTOS CON SEMAFOROS
|__________________________________________________*/
XFSH_RESULT XFSHEndRead(void)
{
#if defined (_CONTROL_LBA_)
LBA_XFSHEndRead(raddress);
#endif
return XFSH_SUCCESS;
}
/*
| FUNCIÓN DE ESCRITURA EN LA MEMORIA
|__________________________________________________*/
XFSH_RESULT XFSHDynamicRead(DWORD addressD,
BYTE *bufferD,
WORD lengthD)
{
while( XFSHIsBusy() );
SetCS(CSON);
#if defined(FLASH_HIGH_SPEED)
// ENVIO FAST READ OPCODE
writeXSFHSPI(FREAD);
#else
// ENVIO READ OPCODE
writeXSFHSPI(READ);
#endif
// ENVIO DE LA DIRECCION
writeXSFHSPI(((DWORD_VAL*)&addressD)->v[2]);
writeXSFHSPI(((DWORD_VAL*)&addressD)->v[1]);
writeXSFHSPI(((DWORD_VAL*)&addressD)->v[0]);
#if defined(FLASH_HIGH_SPEED)
// DUMMY CYCLE
writeXSFHSPI(DYFM);
#endif
while(lengthD--)
{
if(bufferD != 0){
readXSFHSPI(*bufferD);
*bufferD++;
}
};
SetCS(CSOFF);
restoreSPISPEED();
return XFSH_SUCCESS;
}
void XFSHInit(int pbclk)
{
FLASH_CS_TRIS = 0;
SetCS(CSOFF);
Setup_SCK(0);
Setup_SDI(1);
Setup_SDO(0);
#if defined(__C30__)
FLASH_SPICON1 = PROPER_SPICON1;
FLASH_SPICON2 = 0;
FLASH_SPISTAT = 0;
SPI1CON1bits.MODE16 =0;
FLASH_SPISTATbits.SPIEN = 1;
#elif defined(__PIC32MX__)
FLASH_SPIBRG = (pbclk/8)/2ul/FLASH_MAX_SPI_FREQ;
FLASH_SPICON1bits.CKE = 1;
FLASH_SPICON1bits.MSTEN = 1;
FLASH_SPICON1bits.ON = 1;
#elif defined(__18CXX)
FLASH_SPICON1 = 0x21;
FLASH_SPI_IF = 0;
FLASH_SPISTATbits.CKE = 1;
FLASH_SPISTATbits.SMP = 0;
#endif
FLASHSetReg();
}
void main(void)
{
BYTE C,ix;
XFSHInit(0); //inicializamos el driver
FLASHReadID(); //para debug llamamos esta funcion para ver si nuestra memoria contesta
//ESCRIBIMOS 10 bytes
XFSHBeginWrite(0x00000000);
XFSHWrite('E');
XFSHWrite('S');
XFSHWrite('T');
XFSHWrite('O');
XFSHWrite('Y');
XFSHWrite(' ');
XFSHWrite('V');
XFSHWrite('I');
XFSHWrite('V');
XFSHWrite('A');
XFSHEndWrite();
//LEEMOS 10 bytes
XFSHBeginRead(0x00000000);
for(ix=0;ix<10;ix++)
{
C = XFSHRead();
//aqui envias el la variable "C" por una serial o lcd o lo que sea
}
XFSHEndRead();
for(;;){ };
}
void UInt32toByteArray(UInt32 Value, Byte *Buffer)
{
Byte i;
UInt32 Digit;
UInt32 Divisor;
Bool Printed = False;
if(Value)
{
for(i = 0, Divisor = 1000000000; i < 10; i++)
{
Digit = Value/Divisor;
if(Digit || Printed)
{
*Buffer++ = '0' + Digit;
Value -= Digit*Divisor;
Printed = True;
}
Divisor /= 10;
}
}
else
{
*Buffer++ = '0';
}
*Buffer = '\0';
}
void UInt32toEndianByteArray(UInt32 Value, Byte *Buffer, UInt8 maxLen)
{
Byte ix,yx=0;
UInt32 Digit;
UInt32 Divisor;
Byte endianData[10] ={0x0};
Bool Printed = False;
Bool StartEndian = False;
if(Value)
{
for(ix = 0, Divisor = 1000000000; ix < 10; ix++)
{
Digit = Value/Divisor;
if(Digit || Printed)
{
endianData[ix] = '0' + Digit;
Value -= Digit*Divisor;
Printed = True;
}
Divisor /= 10;
}
for(ix=(10-maxLen);ix<10;ix++)
{
if(endianData[ix]>='0')
*Buffer++ = endianData[ix];
else
*Buffer++ = '0';
}
}
else
{
*Buffer++ = '0';
}
*Buffer = '\0';
}
inline Byte AToB(Char inA)
{
if ((inA >= 0x30) && (inA <= 0x39))
{
return (inA - 0x30);
}
else if ((inA >= 0x41) && (inA <= 0x46))
{
return (inA - 0x37);
}
else if ((inA >= 0x61) && (inA <= 0x66))
{
return (inA - 0x57);
}
else
{
return 0;
}
}
inline Char BToA(Byte inB)
{
if(inB<=9)
return (inB + 0x30);
if((inB>9)&&(inB<=15))
return (inB + 0x37);
return 0;
}
char nibbleToHex(int nibble)
{
const int ascii_zero = 48;
const int ascii_a = 65;
if((nibble >= 0) && (nibble <= 9))
{
return (char) (nibble + ascii_zero);
}
if((nibble >= 10) && (nibble <= 15))
{
return (char) (nibble - 10 + ascii_a);
}
return '?';
}
unsigned char bcd(unsigned char dec)
{
return ((dec/10)<<4)+(dec%10);
}
unsigned char decimal(unsigned char bcd)
{
return ((bcd>>4)*10)+bcd%16;
}
Bool isPrint(char c){
Byte _c=(Byte)c;
if ((_c>=0x20) && (_c<=0x7F)){
return 1;
}
return 0;
}