ATmega328 + SPI Mémoire Flash

Préface: Cette question est au sujet d'un projet sur lequel je travaille avec un professeur de mon université. Il n'est PAS un grade, mais ma réputation avec ce professeur. Ainsi, alors que ma réussite sur ce projet est important pour moi, je ne vois pas qu'il est injuste de demander de l'aide auprès d'un Débordement de Pile.

Cela dit, voici un haut niveau aperçu de mon projet. J'ai un microcontrôleur ATmega328. J'ai une Puce SST 64 Mb de mémoire flash de la carte. L'ATmega dispose d'un matériel de mise en œuvre de SPI. La mémoire flash dispose d'un matériel de mise en œuvre de SPI.

Mon but est de lire des données à partir et écrire des données dans la mémoire flash à l'aide de l'ATmega en SPI master mode. Le mémoire est organisé en plusieurs superposition de la structure qui est agréable pour les effacer, mais pour ma part, c'est simplement de 32 768 pages de 256 octets chacun.

Pour écrire des données à l'idée de base est que j'ai envoyer une instruction octet, puis de l'adresse de départ, puis les données. Pour lire les données à l'idée de base est que j'envoie une instruction octet, puis de l'adresse de départ, puis un mannequin d'octets, et puis, il commence à m'envoyer des données.

Voici les fiches de données:

Microcontrôleur: http://www.atmel.com/dyn/resources/prod_documents/doc8271.pdf

Flash: http://www.sst.com/dotAsset/40498.pdf

Code:

#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

}

Donc c'est censé être un programme de test qui programmes 1 octet sur le flash et puis le lit à l'arrière et l'affiche de l'octet sur une LED tableau que j'ai. Si vous êtes intéressé dans le tableau, il peut être trouvé ici: http://evilmadscience.com/tinykitlist/157

Je crois que ma fonction de lecture des œuvres, car la première fois j'ai couru à ce, tous les 8 LEDs s'allument. Qui serait de m'indiquer qu'il lire la mémoire flash quand il a été dans son état par défaut de toutes les 1s. Maintenant, apparemment, j'ai vissé quelque chose avec l'écriture, car l'octet qui s'allume ne correspond pas du tout avec l'octet que je suis tenter de programme.

Je tiens également à noter que j'utilise par défaut la bibliothèque de SPI pour les Arduinos et le tampon de trame fonctions de travail. Quand je fais frame1.WriteRow(toDisp), qui fonctionne correctement et a été largement testé.

Si quelqu'un a le temps ou la patience pour comprendre ce que je fais mal, ce serait extrêmement impressionnant.

EDIT: D'aide au débogage:
Les LEDs sont dictés par les puces conducteur qui utilisent l'interface SPI. Je n'ai pas écrit de la partie du code. Sur un oscilloscope, je peux voir le SCK ligne conduit par cette partie du code. Cependant, j'ai aussi une sonde sur le MOSI pin et si je n'ai pas allume toutes les lumières, il n'apparaît jamais à aller haut. Pour moi, cela signifie que je ne suis pas de l'envoi d'informations correctement. AKA... peut-être mon SPI.transfer() besoins activer la fonction ou quelque chose?

Vous avez séparé slave select (SS) broches pour le flash et le pilote de jetons?

OriginalL'auteur NickHalden | 2010-10-20