AT45DB dataflash library problems with timer2 interrupt

I am working with the dataflash library for the AT45DB series of flash memory which can be found here.
http://playground.arduino.cc/code/dataflash
I have the library working perfectly in some simple sketches but when I try to add it to my main code it becomes erratic and inconsistent. For example sometimes it wont write the page, it will fail to read pages sometimes, sometimes it will read a buffer but part of it. The errors are all over the place.

I am running a breadboard ATMEGA328P with the internal 8mhz oscillator and have a external 32.768 crystal. I use the external crystal to keep time and as an interrupt from sleep. A process of elimination has revealed that the cause of my problems is the timer2 interrupt. If I disable the timer2 interrupt my problems go away and the AT45DB works perfectly. In the sketch below I have it set to write the string from messageline into page 0. This loop will increment to the subsequent page and keep writing every page in the memory. This sketch example will consistently make it to page 3 and then hang for a a few seconds and then starts back at page 0. It does not seem to reset since I don't get the print statement from setup(), it just seems to start back from zero in the main loop which is quite strange. When I disable timer2 interrupt this sketch runs perfectly and writes/reads pages forever as it should (or at least until it runs out of pages).

My issue is that I don't want to disable timer2 even for a brief time since that will screw up my time keeping. Is there any way to keep the flash memory happy and keep my timer2 interrupt running?

#include <dataflash.h>

int page = 0;
int buffer = 1;
char messageline[60] = "#This is a test string for the flash memory";
char readFlash[60];
Dataflash dflash; 
int i = 0;


void setup(){
    //Setup TIMER2
  TCCR2A = 0x00;
  TCCR2B = (1<<CS22)|(1<<CS21)|(1<<CS20); //Set CLK/1024 or overflow interrupt every 8s
  ASSR = (1<<AS2); //Enable asynchronous operation, 32kHz xtal needed
  TIMSK2 = (1<<TOIE2); //Enable the timer 2 interrupt. If this is disabled the sketch works properly
 
  sei(); //Enable global interrupts
    
  pinMode(A3, OUTPUT); //Flash VCC
  digitalWrite(A3, HIGH); //powers the flash memory up
  delay(4000); 
  
  Serial.begin(9600);
  Serial.println("starting the sketch now");
  dflash.init(); //initialize the memory (pins are defined in dataflash.cpp 
}

void loop(){
  writeData();
  readData();
  page++; 
   
  delay(1000); //keep it from running so quickly in testing 
}


void writeData(){
  Serial.print("I am writing page ");
  Serial.println(page);
  i = 0;
  while (i < 60){
    dflash.Buffer_Write_Byte(1, i, messageline[i]);  //write to buffer 1, 1 byte at a time
    i++;
  }
  
  dflash.Buffer_To_Page(1, page); //write the buffer to the memory on page: page
}

void readData(){
  Serial.print("reading page ");
  Serial.println(page);
  dflash.Page_To_Buffer(page, buffer);//copy page to the buffer
  
  i = 0;
  while(i < 60){ 
    readFlash[i] = dflash.Buffer_Read_Byte(buffer, i); //read the buffer
    i++;
  }
  Serial.println(' ');
  Serial.println(readFlash); //print what was read from the buffer
}

Where is the timer 2 interrupt handler?

this enables the timer 2 interrupt.

TIMSK2 = (1<<TOIE2);

If I change that to zero the problem goes away. Until I find a better solution what I have done for the moment is to disable global interrupts at the start and enable them right after I write using cli() and sei() like this.

void writeData(){
  Serial.print("I am writing page ");
  Serial.println(page);
  cli(); //disable interrupts
  i = 0;
  while (i < 60){
    dflash.Buffer_Write_Byte(1, i, messageline[i]);  //write to buffer 1, 1 byte at a time
    i++;
  }
  
  dflash.Buffer_To_Page(1, page); //write the buffer to the memory on page: page
sei(); //enable interrupts
}

However, since this post I have found more issues. The dataflash library was created for the AT45DB041B memory which is the older 4 megabit "B" version. I am using the newer 8 megabit "D" version. The legacy B commands still work on the D, but I think I have some issues because of the memory size difference. For example when I try to store the buffer to page 6 it appears to write the data on page 3 instead. I am guessing that the library calculates the internal memory based on the 4 megabit version and that the 8 megabit version is different. I looked through the library and found the section that deals with writing the buffer to the page. I can see where it calculates the upper and lower part of the address but I don't know how to interpret it. I cant figure out where it gets "pageBits" from and what does ">>" mean?

void Dataflash::Buffer_To_Page (unsigned char BufferNo, unsigned int PageAdr)
{
  DF_CS_inactive();						//make sure to toggle CS signal in order
  DF_CS_active();						//to reset Dataflash command decoder
  if (1 == BufferNo)						//program flash page from buffer 1
  {
    DF_SPI_RW(Buf1ToFlashWE);					//buffer 1 to flash with erase op-code
    DF_SPI_RW((unsigned char)(PageAdr >> (16 - PageBits)));	//upper part of page address
    DF_SPI_RW((unsigned char)(PageAdr << (PageBits - 8)));	//lower part of page address
    DF_SPI_RW(0x00);										//don't cares
  }

I'm confused. Are you posting because you need to vent or because you need help?

Sorry if it came across the wrong way but I really do need help. I need to get the external flash memory working on my project and I am at a loss on how to do that. During my original post I thought the only issue was the interrupts. However, I continued to test and found additional issues with the library such as if I try to write to page 6 it appears to write to page 3. It is not clear to me if I am writing to the wrong page or reading from the wrong page (or possibly both). I do not understand enough of the library to make the modifications to get it working. I am only guessing as to where the issue is but a reasonable place to start seemed to be with how the library assigns the page to memory. My problem is that despite the simplicity of the library I don't understand it. If you have suggestions on how to get the library working for my particular application or if you can suggest some reading I would greatly appreciate it!

fbriggs4:
Sorry if it came across the wrong way but I really do need help.

Excellent. In that case please answer the question in Reply #1.

I misunderstood your question the first time, hopefully this answers you properly. This is the complete sketch with the interrupt handler included.

#include <dataflash.h>

int page = 0;
int buffer = 1;
char messageline[60] = "#This is a test string for the flash memory";
char readFlash[60];
Dataflash dflash; 
int i = 0;
volatile int seconds = 0; //used to keep time


SIGNAL(TIMER2_OVF_vect){
  seconds++;
}


void setup(){
  //Setup TIMER2
  TCCR2A = 0x00;
  TCCR2B = (1<<CS22)|(1<<CS21)|(1<<CS20); //Set CLK/1024 or overflow interrupt every 8s
  ASSR = (1<<AS2); //Enable asynchronous operation, 32kHz xtal needed
  TIMSK2 = (1<<TOIE2); //Enable the timer 2 interrupt. If this is disabled the sketch works properly
 
  sei(); //Enable global interrupts
    
  pinMode(A3, OUTPUT); //Flash VCC
  digitalWrite(A3, HIGH); //powers the flash memory up
  delay(4000); 
  
  Serial.begin(9600);
  Serial.println("starting the sketch now");
  dflash.init(); //initialize the memory (pins are defined in dataflash.cpp 
}

void loop(){
  writeData();
  readData();
  page++; 
   
  delay(1000); //keep it from running so quickly in testing 
}


void writeData(){
  Serial.print("I am writing page ");
  Serial.println(page);
  i = 0;
  while (i < 60){
    dflash.Buffer_Write_Byte(1, i, messageline[i]);  //write to buffer 1, 1 byte at a time
    i++;
  }
  
  dflash.Buffer_To_Page(1, page); //write the buffer to the memory on page: page
}

void readData(){
  Serial.print("reading page ");
  Serial.println(page);
  dflash.Page_To_Buffer(page, buffer);//copy page to the buffer
  
  i = 0;
  while(i < 60){ 
    readFlash[i] = dflash.Buffer_Read_Byte(buffer, i); //read the buffer
    i++;
  }
  Serial.println(' ');
  Serial.println(readFlash); //print what was read from the buffer
}

Arduino IDE version?

IDE 1.0.3

Are you getting a compiler error with the dataflash library? Something about WConstants.h not found.

The library would not compile initially but I changed WProgam.h to Arduino.h and I don't get any compile errors since then.

Do you still need help?

I was actually able to get it working, but I am not 100% sure why. What I have found is that I need to transmit the page twice in order for it to write the buffer to the memory. For example this works

  i = 0;
  while (i < 60){
    dflash.Buffer_Write_Byte(1, i, messageline[i]);  //write to buffer 1, 1 byte at a time
    i++;
  }
  
  dflash.Buffer_To_Page(1, page); //write the buffer to the memory on page: page
  dflash.Buffer_To_Page(1, page); //write the buffer to the memory on page: page
}

This does not work.

  i = 0;
  while (i < 60){
    dflash.Buffer_Write_Byte(1, i, messageline[i]);  //write to buffer 1, 1 byte at a time
    i++;
  }
  
  dflash.Buffer_To_Page(1, page); //write the buffer to the memory on page: page
}

Any idea why writing the page twice would work? Maybe I need to send more don't care bits?