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?
OriginalL'auteur NickHalden | 2010-10-20
Vous devez vous connecter pour publier un commentaire.
À quelqu'un est toujours curieux le problème est que la puce de mémoire a été extrêmement sensible à la lenteur des temps de montée. Après avoir mis un trigger de schmitt, tout a fonctionné parfaitement.
OriginalL'auteur NickHalden