2010-10-20 8 views
5

Prefacio: Esta pregunta es sobre un proyecto en el que estoy trabajando con un profesor de mi universidad. NO es para un grado, pero mi reputación con este profesor sí importa. Por lo tanto, aunque mi éxito en este proyecto es importante para mí, no creo que sea injusto buscar ayuda de Stack Overflow.ATmega328 + SPI Memoria Flash

Dicho esto, aquí hay un resumen general de de mi proyecto. Tengo un microcontrolador ATmega328. Tengo una tarjeta de memoria flash Microchip SST de 64 Mbit. El ATmega tiene una implementación de hardware de SPI. La memoria flash tiene una implementación de hardware de SPI.

Mi objetivo es leer datos y escribir datos en el chip flash con el ATmega en el modo maestro SPI. La memoria está organizada en una estructura de superposición múltiple que es agradable para borrar, pero para mis propósitos, es básicamente 32768 páginas de 256 bytes cada una.

Para escribir datos, la idea básica es enviar un byte de instrucciones, luego la dirección de inicio, luego los datos. Para leer datos, la idea básica es que envíe un byte de instrucciones, luego la dirección de inicio, luego un byte ficticio, y luego comienza a enviarme datos.

Estas son las hojas de datos:

Microcontrolador: http://www.atmel.com/dyn/resources/prod_documents/doc8271.pdf

de inflamación: http://www.sst.com/dotAsset/40498.pdf

Código:

#include <SPI.h> 
#include <Peggy2.h> 

#define SS_PIN 16 

Peggy2 frame1; 
byte toDisp = 0; 
byte checker = 0; 

void setup() 
{ 
    frame1.HardwareInit(); 
    pinMode(SS_PIN,OUTPUT); //set pin16 to output, SS pin 
    SPI.setClockDivider(SPI_CLOCK_DIV2); //set the SPI clock to f/2, fastest possible 
    SPI.begin(); //SPI lib function which sets ddr for SCK and MOSI pin 
        //MISO is auto input 
        //see SPI.cpp for more info 

} 

void loop() 
{ 

    if(!checker){ 
       enableProgramming(); 
     programData(); 
     toDisp = receiveByte(0); 
     checker = 1; 
     frame1.WriteRow(0,toDisp); 
    } 
    frame1.RefreshAll(2); 

} 

byte receiveByte(unsigned long startAddress) 
{ 
    //Begin High Speed Read Instruction 
    //See p. 10 of SST data sheet 
    digitalWrite(SS_PIN,LOW); 
    SPI.transfer(0x0B); //high speed read instruction 
    SPI.transfer(0x00); //next 3 transfers are address bits A32 - A0 
    SPI.transfer(0x00); //So this will read the first byte on the chip 
    SPI.transfer(0x00); //last address bits 
    SPI.transfer(0xFF); //dummy byte is required to start sending data back to uP 
    SPI.transfer(0xFF); //I'm hoping that if I transfer a bullshit byte, the flash 
         //chip will transfer it's data to me in the same time 
    digitalWrite(SS_PIN,HIGH); 
    //End High Speed Read Instruction 
    return SPDR;  
} 

//will perform the read instruction starting from 
//startAddress and will receive numOfBytes bytes in 
//succession 
void receiveBytes(int numOfBytes, unsigned long startAddress) 
{ 
    digitalWrite(SS_PIN,LOW); 
    SPI.transfer(0x0B);//high speed read instruction 

} 

//will perform: 
// 1) Chip Erase 
// and loop through: 
// 1) Page Program 
// 2) increment Page 
//until the data has finished **note this can loop and over write beginning of memory 
void programData(){ 
    //Begin ChipErase Instruction 
    //See p. 17 of SST data sheet 
    digitalWrite(SS_PIN,LOW); 
    SPI.transfer(0x60);//chip erase instruction 
    digitalWrite(SS_PIN,HIGH); 
    delay(50);//spec'd time for CE to finish 
       //don't bother polling because time to program is irrelevant 
    //End ChipErase Instruction 

     //Begin WREN Instruction 
    //See p. 18 of SST data sheet 
    digitalWrite(SS_PIN,LOW); 
    SPI.transfer(0x06);//write enable instruction 
    digitalWrite(SS_PIN,HIGH); 
    //End WREN Instruction 

    digitalWrite(SS_PIN,LOW); 
    SPI.transfer(0x02); //page program instruction 
    SPI.transfer(0x00); //first 8 address bits 
    SPI.transfer(0x00); //2nd 8 address bits 
    SPI.transfer(0x00); //3rd 8 address bits 
    SPI.transfer(0xAA); //10101010 is the byte I should be writing 
    digitalWrite(SS_PIN,HIGH); 
    delayMicroseconds(3000); //wait 3 ms for page program 


    /* 
    //Begin Page-Program Instruction 
    //see p. 13 of SST data sheet 
    byte firstAddress = 0; 
    byte secondAddress = 0; 
    //this loop will write to every byte in the chips memory 
    //32,768 pages of 256 bytes = 8,388,608 bytes 
    for(unsigned int i = 0; i < 32,768; ++i) //long variable is number of pages 
    { 
     digitalWrite(SS_PIN,LOW); 
     ++secondAddress; //cycles from 0 to 255, counts pages 
     firstAddress = i>>8; // floor(i/256) 

     SPI.transfer(0x02);//Page-Program instruction byte 
     SPI.transfer(firstAddress); //increments every 256 pages i.e. at page 256 this should be 1 
     SPI.transfer(secondAddress); //increments every 256 bytes, i.e every page 
     SPI.transfer(0x00); //beginning of a page boundary 
     for(int j = 0; j < 256; ++j) //number of bytes per page 
     { 
      SPI.transfer(2program[(256*i) + j]);//data byte transfer    
     } 
     digitalWrite(SS_PIN,HIGH); 
     delayMicroseconds(2500); //2500us (2.5ms) delay for each page-program instruction to execute 
    } 
    //End Page-Program Instruction 
    */ 
} 

//Will prepare the chip for writing by performing: 
// 1) arm the status register 
// 2) Write Enable instruction 
//Only needs to be performed once! 
void enableProgramming(){ 
    //Begin EWSR & WRSR Instructions 
    //See p. 20 of SST data sheet for more info 
    digitalWrite(SS_PIN,LOW); //lower the SS pin 
    SPI.transfer(0x50); //enable write status register instruction 
    digitalWrite(SS_PIN,HIGH); //raise the SS pin 
    delay(10); 
    digitalWrite(SS_PIN,LOW); //lower the SS pin 
    SPI.transfer(0x01); //write the status register instruction 
    SPI.transfer(0x00);//value to write to register 
       //xx0000xx will remove all block protection 
    digitalWrite(SS_PIN,HIGH); 
    //End EWSR & WRSR Instructions 

    //Begin WREN Instruction 
    //See p. 18 of SST data sheet 
    digitalWrite(SS_PIN,LOW); 
    SPI.transfer(0x06);//write enable instruction 
    digitalWrite(SS_PIN,HIGH); 
    //End WREN Instruction 

} 

Así que esto se supone que es un programa de prueba que programa 1 byte ont o el flash y luego lo lee y muestra ese byte en un conjunto de LED que tengo. Si está interesado en el conjunto de LED, puede encontrarlo aquí: http://evilmadscience.com/tinykitlist/157

Creo que mi función de lectura funciona porque la primera vez que ejecuté esto, los 8 LED se iluminaron. Eso me indicaría que leyó la memoria flash cuando estaba en su estado de fábrica de todos los 1s. Ahora, aparentemente, he arruinado algo con la escritura porque el byte que se ilumina no se corresponde en absoluto con el byte que estoy intentando programar.

También debería tener en cuenta que estoy usando la biblioteca SPI predeterminada para Arduinos y funcionan las funciones de búfer de cuadros. Cuando hago frame1.WriteRow(toDisp), eso está funcionando correctamente y ha sido probado extensamente.

Si alguien tiene el tiempo o la paciencia para descubrir lo que estoy haciendo mal, sería extremadamente increíble.

EDIT: Para ayudar a la depuración:
Los LEDs están siendo impulsados ​​por chips de controlador que utilizan la interfaz SPI también. No escribí esa parte del código. En un osciloscopio, puedo ver que la línea SCK está impulsada por esa parte del código. Sin embargo, también tengo una sonda en el pin MOSI y si no enciendo ninguna luz, nunca parece ir alto. Para mí eso significa que no estoy enviando información correctamente. AKA ... tal vez mi SPI.transfer() necesita una función de habilitación o algo?

+0

Tiene pines de selección de esclavos (SS) por separado para el flash y los chips del controlador? – AndrewStone

Respuesta

4

Para cualquiera que todavía tenga curiosidad, el problema es que el chip de memoria es extremadamente sensible a los tiempos de subida lenta. Después de poner un disparador schmitt, todo funcionó perfectamente.

Cuestiones relacionadas