Autor Tema: Memoria externa SPI  (Leído 10762 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado PFCarrera

  • PIC10
  • *
  • Mensajes: 32
Memoria externa SPI
« en: 05 de Marzo de 2010, 07:49:50 »
Buenas a todos!

Necesito escribir y leer  datos en una memoria externa SPI (25LC1024) y utilizo 18F4550.
El problema es que no me aclaro mucho con el SPI y por más que busco, no encuentro ejemplos de comunicación SPI con una memoria externa, todos los ejemplos que encuentro son con CSS y yo utilizo C18.

Espero que alguien pueda ayudarme!

un saludo!

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: Memoria externa SPI
« Respuesta #1 en: 05 de Marzo de 2010, 11:51:23 »
Entonces tendrás que leer la datasheet de la memoria y configurar el módulo SPI del pic desde cero.

Ve publicando tus avances.

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Memoria externa SPI
« Respuesta #2 en: 05 de Marzo de 2010, 11:51:46 »
No si habrá ejemplos en el foro, pero en www.microchipc.com hay varios ejemplos de distintas cosas en C para el compilador Hitech.

De todos modos te va a ser necesario leer el datasheet de la memoria para saber bien como son los comandos para dicha memoria.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado PFCarrera

  • PIC10
  • *
  • Mensajes: 32
Re: Memoria externa SPI
« Respuesta #3 en: 08 de Marzo de 2010, 09:08:19 »
Gracias chico!
he estado leyendo el datasheet....lo único que yo y el inglés no nos llevamos muy bien  :)
He averiguado algunas cosas, pero seguiré intentándolo.

Si encontrais algun ejemplo para poder guiarme os lo agradecería!!

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Memoria externa SPI
« Respuesta #4 en: 08 de Marzo de 2010, 11:17:34 »
Bueno, te dejo una explicación muy básica y los comando básicos del uso de la memoria. También te adjunto un programita hecho en C (HiTech) donde hay unas rutinitas de manejo de SPI y me comunico con la memoria en cuestión. Está simulado en Proteus y funciona bien. El programa es para un 16F876A.

---------------------------------------
Hay que tener en cuenta que el pin WP tiene que estar en 1 para poder escribir en la memoria.

Antes de intentar escribir en la memoria hay que habilitar la escritura enviando el comando correspondiente. Esto se
logra con la siguiente secuencia

    Se habilita el dispositivo (llevando el pin CS a 0)
    Enviamos la instruccion WREN (transmitimos el byte correspondiente que es "00000110")
    Deshabilitamos el dispositivo (llevando el pin CS a 1)

Una vez que hemos habilitado la escritura ya podemos escribir en la memoria.
Para escribir un Byte hay que hacer lo siguiente

    Habilitar el dispositivo (llevando el pin CS a 0)
    Enviamos la instruccion WRITE (transmitimos el byte correspondiente que es "00000010")
    Enviamos la direccion a escribir (la dirección es de 24 bits por lo tanto hay que enviar 3 bytes)
    Enviamos el dato a escribir
    Deshabilitamos el dispositivo (llevando el pin CS a 1)

Para escribir mas un Byte consecutivos y dentro de una misma pagina hay que hacer lo siguiente

    Habilitar el dispositivo (llevando el pin CS a 0)
    Enviamos la instruccion WRITE (transmitimos el byte correspondiente que es "00000010")
    Enviamos la direccion a escribir (la dirección es de 24 bits por lo tanto hay que enviar 3 bytes)
    Enviamos el dato a escribir
    Enviamos el dato a escribir
    ..... (Enviar cantidad de bytes que se quieren escribir)
    Deshabilitamos el dispositivo (llevando el pin CS a 1)

Se pueden enviar hasta 256 bytes antes que sea necesario un ciclo de escritura. Por cada ciclo de escritura hay
que esperar un máximo de 6ms antes de volver a escribir. El ciclo de escritura comienza a partir del momento en
que el pin CS se hace 1
Cada vez que termina el ciclo de escritura, se deshabilita la escritura automaticamente por lo tanto para volver
a escribir en la memoria hay volver a habilitar la escritura

Para deshabilitar la escritura hay que enviar la siguiente secuencia

    Se habilita el dispositivo (llevando el pin CS a 0)
    Enviamos la instruccion WRDI (transmitimos el byte correspondiente que es "00000100")
    Deshabilitamos el dispositivo (llevando el pin CS a 1)

Para leer un Byte hay que enviar la siguiente secuencia

    Habilitar el dispositivo (llevando el pin CS a 0)
    Enviamos la instruccion READ (transmitimos el byte correspondiente que es "00000011")
    Enviamos la direccion a leer (la dirección es de 24 bits por lo tanto hay que enviar 3 bytes)
    Hacemos una trasmisión (se puede enviar o no dato hacia el dispositivo) para poder leer la memoria.
    Deshabilitamos el dispositivo (llevando el pin CS a 1)

Para leer mas un Byte consecutivos hay que enviar la siguiente secuencia

    Habilitar el dispositivo (llevando el pin CS a 0)
    Enviamos la instruccion READ (transmitimos el byte correspondiente que es "00000011")
    Enviamos la direccion a leer (la dirección es de 24 bits por lo tanto hay que enviar 3 bytes)
    Hacemos una trasmisión (se puede enviar o no dato hacia el dispositivo) para poder leer la memoria.
    Hacemos una trasmisión (se puede enviar o no dato hacia el dispositivo) para poder leer la memoria.
    ..... (Una transmisión por cada byte que se quiera leer, la dirección se incrementa automáticamente)
    Deshabilitamos el dispositivo (llevando el pin CS a 1)
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Memoria externa SPI
« Respuesta #5 en: 08 de Marzo de 2010, 11:25:02 »
Había un error en la parte del for del programita que te mandé. Acá te lo subo reparado

Código: C
  1. /********************************************
  2. *
  3. * Prueba de protocolo SPI por HardWare
  4. *
  5. /********************************************/
  6.  
  7.  
  8. #include <htc.h>
  9. #include "Def16f87xa.h"
  10. #define PIC_CLK 20000000
  11.  
  12.  
  13. #include "Hardspi.c"
  14. #include "delayhd.h"
  15.  
  16. void main()
  17. {
  18.         unsigned char veces;
  19.         unsigned char Dato_leido;
  20.  
  21.         TRISC0 = 0;
  22.         RC0 = 1;
  23.         setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV16);
  24.  
  25.  
  26.         RC0 = 0;                // habilito el dispositivo
  27.         write_spi(6);   // habilito la escritura en la memoria
  28.         RC0 = 1;                // deshabilito el dispositivo
  29.  
  30.         RC0 = 0;                // habilito el dispositivo
  31.         write_spi(2);   // instruccion de escribir
  32.         write_spi(0);   // direccion, byte mas significativo
  33.         write_spi(0);   // direccion
  34.         write_spi(0);   // direccion, byte menos significativo
  35.         write_spi(128); // dato
  36.         write_spi(64);  // dato
  37.         RC0 = 1;                // deshabilito el dispositivo
  38.  
  39.        
  40.         for (veces = 24; veces > 0; veces--)
  41.         {
  42.                 DelayUs(250);
  43.         }
  44.  
  45.         //El ciclo (For...) anterior es para hacer una espera de 6ms que es
  46.         //el tiempo del ciclo de escritura de la memoria.
  47.        
  48.  
  49.         RC0 = 0;                // habilito el dispositivo
  50.         write_spi(3);   // instruccion de leer
  51.         write_spi(0);   // direccion, byte mas significativo
  52.         write_spi(0);   // direccion
  53.         write_spi(0);   // direccion, byte menos significativo
  54.         Dato_leido = read_spi();                // leo el dato de la direccion 000
  55.         Dato_leido = read_spi();                // leo el dato de la direccion 001
  56.         RC0 = 1;                // deshabilito el dispositivo
  57.  
  58.         while (1);
  59. }
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: Memoria externa SPI
« Respuesta #6 en: 08 de Marzo de 2010, 20:41:53 »
Hoy en día el inglés no debería ser problema. Este link te será de mucha utilidad.

http://translate.google.com

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Memoria externa SPI
« Respuesta #7 en: 08 de Marzo de 2010, 20:53:15 »
he estado leyendo el datasheet....lo único que yo y el inglés no nos llevamos muy bien  :)

Uff! Entonces le erraste de camino!  :D Va a ser necesario que se comiencen a llevar bien  :D
No contesto mensajes privados, las consultas en el foro

Desconectado PFCarrera

  • PIC10
  • *
  • Mensajes: 32
Re: Memoria externa SPI
« Respuesta #8 en: 09 de Marzo de 2010, 07:00:07 »
Muchísimas gracias AngelGris!

voy a ponerme en ello!!
ya os contaré mis progresos

Por lo del inglés....ya se que es muy importante...estoy en ello.
Gracias a los demás.

Un saludo

Desconectado barral

  • PIC10
  • *
  • Mensajes: 37
Re: Memoria externa SPI
« Respuesta #9 en: 09 de Marzo de 2010, 08:21:35 »
En el ejemplo de TCP/IP hay rutinas para memorias SPI, el los archivos son Spieeprom.c, xeeprom.h

spieeprom.c
Código: [Seleccionar]
/*********************************************************************
 *
 *               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)

Código: [Seleccionar]
/*********************************************************************
 *
 *               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

Desconectado PFCarrera

  • PIC10
  • *
  • Mensajes: 32
Re: Memoria externa SPI
« Respuesta #10 en: 09 de Marzo de 2010, 08:49:32 »
Buenas a todos!

Os comento, este es mi código:

#include <p18f4550.h>
#include <delays.h>
#include <spi.h>

#pragma config FOSC = XT_XT
#pragma config WDT= OFF
#pragma config MCLRE= ON
#pragma config LVP= OFF
#pragma config DEBUG= ON
#pragma config PWRT= OFF

#define   CS         PORTBbits.RB4

#define   RDSR   0b00000101
#define   WRSR   0b00000001
#define   WREN   0b00000110
#define   WRDI   0b00000100
#define   WRITE  0b00000010
#define   READ   0b00000011

unsigned char address,dato,longitud,valor;

void CMD_Write(unsigned char SPI_Cmd){
   SSPBUF=SPI_Cmd;
   Delay1KTCYx(6);

}


void SET_WREN(void){
   CS=0;
   CMD_Write(WREN);
   CS=1;
}


void Byte_Write(unsigned char address, unsigned char dato){             //Escribir en la memoria
   SET_WREN();
   CS=0;
   CMD_Write(WRITE);
   CMD_Write(address);
   CMD_Write(dato);
   CS=1;
   Delay1KTCYx(6);   //retardo de 6ms
}

void Byte_Read(unsigned char address, unsigned char *dato, unsigned char longitud){       //Leer de la memoria
   CS=0;
   CMD_Write(READ);
   CMD_Write(address);
   getsSPI(dato,longitud);
   CS=1;
   
   return(SSPBUF);
}

void main (void){
   PORTB=0X00;
   PORTC=0X00;
   CS=1;

   TRISBbits.TRISB4=0; //Define CS como salida
   TRISBbits.TRISB1=0; //Define SCK como salida
   TRISBbits.TRISB0=1; //Define SDI como entrada
   TRISCbits.TRISC7=0; //Define SDO como salida
   
   SSPSTAT= 0xC0; // SPI Bus mode 0,0
   SSPCON1 = 0x21; // Enable SSP, FOSC/16

   OpenSPI(SPI_FOSC_4, MODE_00, SMPEND);
   
   while(1){
   address=0x00;  //address
   dato=0xA5;
   longitud=0x01;
   Byte_Write(address,dato);
   Byte_Read(address,&dato,longitud);
   PORTD=SSPBUF;
   }
}

Cuando escribo en la memoria escribo directamente en el registro SSPBUF, no se si estará bien o tengo que escribir en el bus spi (instrucción WriteSPI) y cuando leo, leo desde el bus spi (instrucción getsSPI) y la función de lectura me devuelve el registro SSPBUF.

Y para visualizar el resultado de la lectura lo he puesto en el PORTD, pero.....me sale 0x00.....es decir....no me está leyendo nada!!

¿Qué es lo que hago mal?

Por cierto....gracias a todos

micronoob

  • Visitante
Re: Memoria externa SPI
« Respuesta #11 en: 09 de Marzo de 2010, 09:10:06 »
hola,

buena esta memoria  de microchip es una tortuga ...

atención amigo!

escribir o leer en una memoria FLASH no es lo único que debes tener en cuenta sus tiempos de borrados y su vida por sector son muy importantes.

hace un par de años modifique una librería de microchip llamada SPIeprom.c   que era utilizada por el stack microchip para su modulo HTTP

microchip por aquellos tiempos aun no tenia memorias FLASH y ademas necesitaba adaptarlos a mis hardware  ST y MACRONIX  pues así hice  SPIflash esta librería permite usar una memoria FLASH NAND  como  si fuera una NOR  (básicamente como si fuera una eprom donde puedes cambiar solo un byte)

otra nota importante de esta librería es el uso selectivo de la opción LOW_RAM , explico:

si necesitamos guardar en RAM un sector entero de nuestra SPI FLASH vamos a necesitar 4096 bytes por ellos ..  bien no!,  

en esta librería hay un método que utiliza un sector denominado sector SWAP para ir trasladando lo que tiene que memorizar  borrar el sector y volver a volcar su contenido ...lento uhhhmmmm es bastante optimizado y sobre un 16 MIPs va de maravilla
también de notar que esta diseñado por FLASH algo mas rápidas que la de microchip (y mas  económicas)

también hay una versión modificada de el file system de microchip para invocar dicha librería.

Código: [Seleccionar]
/*********************************************************************
 *
 *               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)





aqui un ejemplo de lectura

XFSHBeginRead(DIRECCION_PARA_LEER);
DAME_UN_BYTE =  XFSHRead();
..
DAME_MAS =  XFSHRead();
XFSHEndRead();

Código: [Seleccionar]

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();

     ...

}



aqui un ejemplo de escritura

XFSHBeginWrite(DIRECCION_PARA_ESCRIBIR);
XFSHWrite(UN_BYTE_CUALQUIERA);
..
XFSHWrite(MAS_BYTES_SIQUIERES);
XFSHEndWrite();

Código: [Seleccionar]

...

 dPointer = XFSHMYDBPartition.Tables[jx].RAMAddress;
   
 XFSHBeginWrite(XFSHMYDBPartition.Tables[jx].XFSHAddress);

 for(ix=0;ix<(XFSHMYDBPartition.Tables[jx].SizeTable);ix++)
{
               XFSHWrite(*dPointer++);
         }          
           
         XFSHEndWrite();

     ...

}


el código hay que limpiarlo un poco de comentarios y todo esto
es que cuando pase a la version 2 de la librería deje de actualizar esta y así se quedo

Saludos
desde Micronoob  ....muy noob!
« Última modificación: 10 de Marzo de 2010, 19:29:18 por micronoob »

Desconectado PFCarrera

  • PIC10
  • *
  • Mensajes: 32
Re: Memoria externa SPI
« Respuesta #12 en: 09 de Marzo de 2010, 09:49:38 »
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?

micronoob

  • Visitante
Re: Memoria externa SPI
« Respuesta #13 en: 09 de Marzo de 2010, 10:34:36 »
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?


jejej hola,
haber si el truco esta en no leer el contenido de la librerías solo hay que llamar sus funciones ....si no  uno se acaba asustando jejej es broma amigo!

dame unas horas que acabo con el trabajo para un cliente,

me leo datasheet de microchip y antes que el sol anda a buscar la luna te publico una librería para tu memoria (me refiero a la 25ls1024)

saludos.




Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Memoria externa SPI
« Respuesta #14 en: 09 de Marzo de 2010, 12:48:54 »
Lo que yo veo mal es que cuando envias el address, tanto para escritura como para lectura, estás enviando sólo un byte y el address que hay que enviar es de 3 bytes. Fijate que está aclarado en el texto que había enviado previamente.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas


 

anything