hola ,
lo prometido o a un mejor voy a explicarte paso a paso lo que hay que hacer porque la dichosa información
entre y salga de esta araña de 8 patas que tienes cerca de tu micro
Suponiendo que todo el hardware esta en su lugar.
Y que con tu osciloscopio has visto salir bits por las patitas de tu micro.
procedemos con explicar 2 conceptos básicos de las memorias flash
a diferencia de la nuestra cara eeprom, las memorias flash son mas rápidas
también debido a que su borrado se efectúa por sectores y no por bytes
así que en realidad ganamos tiempo en escribir gran cantidad de datos ,
pero perdemos mas tiempo si nuestra cantidad de datos a escribir es inferior
al tamaño de un sector.
pero como en la mayoría de los proyectos lo que cuenta es el dinero que nos podemos gastar en el
o lo que nuestros clientes están dispuestos a gastarse,
nos vemos obligados a utilizar una sola memoria
para alojar tanto datos de gran tamaño que las pequeñas estructuras de datos que hacen ir nuestro
firmware.
esto hace que en el caso de querer escribir un solo byte en un sector y querer mantener lo demás bytes debemos
emplear un método de respaldo de memoria y esto cambia algo en nuestras secuencia de entrada de datos
secuencia de escritura de una memoria EEprom (los procesos de borrado y escritura internos al IC son explicado muy por encima sin explicar el pre y post borrado)
1)enviamos comando para habilitar la escritura
2)enviamos comando de escritura
2)enviamos la dirección del byte que queremos escribir (suelen ser 3 bytes dato que las EEprom son pequeñitas y hay un byte fantasma)
3)el ic borra la locación de memoria
4)enviamos el byte
5)esperamos que acabe de escribir
y ya esta!!
secuencia de escritura de una memoria Flash en el caso de querer borrar todo el contenido del sector
1)enviamos comando para habilitar la escritura
2)enviamos comando de borrado de sector
3)enviamos la dirección del sector que contiene nuestro byte
si la dirección de nuestro byte es 0x00000A01 la dirección de nuestro sector es 0x00000000
si la dirección de nuestro byte es 0x00001A01 la dirección de nuestro sector es 0x00001000
4)esperamos que el ic acabe de borrar el sector
5)enviamos comando para habilitar la escritura (la mayoría de la memorias flash suelen deshabilitar la escritura después de un borrado)
6)enviamos comando de escritura
7)enviamos la dirección del byte que queremos escribir
8)enviamos el byte
9)esperamos que acabe de escribir
como se ve desde lejo hay que finalizar muchos mas procesos para escribir una flash, pero también hay de explicar
que en la mayorías de memorias flash hay la escritura secuencial de una pagina esto permite enviar una sola vez
la dirección y cada 256 bytes (en el caso de nuestra memoria con paginacion de 256bytes) enviamos la dirección
mas adelante analizamos la secuencia de escritura queriendo guardar los datos presentes en la flash
procedemos con la escritura de nuestro código
PASO 1) la primera cosa debemos hacer un mapa de nuestro hardware
ATTENCION! en los ejemplos uso unos pines que seguramente no corresponden con tu hardware
/* 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)
PASO 2) creamos un define que nos permitirá compilar solo el código fuente relacionado a nuestro hardware asi se podra mantener el código
par otras memoria SPI FLASH con solo comentar este define
#define MC25AA1024
PASO 3) creamos nuestro defines de opcode (esto sirve para que el código mantenga legibilidad)
// 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
PASO 4) creamos unos defines de atributos
//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
el define FLASH_ST_VIRTUAL_SECTOR identifica el sector utilizado da el driver para respaldar los datos
PASO 5) creamos unos tipos de datos utilizados en nuestro driver
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;
PASO 6) creamos unos defines con casting basado en los tipos recien creados en el paso 5
#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
...continua