SPIMemory() slows down when Program Storage Space hits more than 50%

Hello Everyone,

I have a project I’m rushing to finish, but I’ve run into a weird issue I can’t seem to crack. I have an 8-Bit R2R DAC connected to an ATMEGA32u4, and a 16MB Adesto SPI Flash Memory IC. Reading and writing just fine, and I have most of my code done. Originally, I had split it into two pieces of code, one which uploads stuff to the memory IC, through the serial port, and another which plays back the data in my application. From testing, I found that SPIMemory took around 52-55microseconds to do a single read. Here is the code loop in question to hit the DAC:

 for (uint32_t i=0;i<leng;i++) {
  dacdat=flash.readByte((saddr*4096)+i);  //start sector addr
  playdat();
  delayMicroseconds(1);                   //seems roughly correct for 16KHz
 }                                        //16KHz = 62.5microsec period. readByte takes 52-55microsecs in testing

That’s it, I just read a byte and play it. I do have the OneButton library running, but I suspect it does nothing unless you .tick() on it, so no other timers or anything to interfere. Been playing back audio for days with this loop.

As I was wrapping it up, I decide I have more than enough room to combine the two pieces of code, they already shared a lot of stuff anyway. I have a serial menu, which I just keep adding menu options to, then moving on. At one point however, I tested, and the DAC started playing slower. Not sure by how much, maybe 15-20 microseconds slower, but consistently slower. I dug for an hour, and I couldn’t find anything wrong, or that should be stomping on this super simple loop. However, if I just simply start commenting stuff out from the serial menu, it will work again when the code size takes less than 50% of available program space. It has nothing to do with RAM as I actually have more free now than ever before, as I added F() to all of my serial stuff, had forgotten to do so, and was down to 398 bytes, and it was working fine. Now, I have 1573 bytes free?

All of the functions work, as I’ve been testing them as I go, and I can totally just comment them out of the code. (Mind you, it’s not even trying to run these guys, unless I connect serial.) So I figure, some voodoo in the stack? I started getting rid of nested function calls, and all sorts of things, but I know all of the code is working either here, or in the other app, so it really didn’t add up that any changes would be needed.

My backup plan is just to split the apps back into two, and try to forget abour it. However, I really hate not knowing why this is happening and I really do want the combined functions now. I’d be happy to share the code, but it’s over 600 lines, and would take a lot of explaining.

Just really wondering if there is anything I can do to isolate this issue? I can imagine for some reason(s) the compilier decided it needed to preserve more data because of the mere existance of a certain function or functions? Each of these functions are very simple and single-purpose, so I really am not sure what to do.

Needless to say, it’s not worth a crap if the DAC is going too slow. :slight_smile:

Thanks!
-Kevin

Argh, I think I found it, but the question still remains.. Why?

I had one more function nested in two different functions which I removed, and basically stopped nesting, then, it got back to playing the way it should have. I was also passing a value to one of them, but just made it a global too, although I tried this first and it didn't help. But, I now need the global since I'm calling the functions in order. Basically, it seems if I go more than one deep, it slows doen SPIMemory(). Sorry if this is a common occurrence, I've never hit anything so timing critical that I noticed this much. In the grand scheme of things, it's not too much slower, but just enough it would seem.

Thanks,
-Kevin

If you post your full problematic code, somebody might be able to shine a light on it :wink:

Ok, so I figured out what is happening, so it looks like something is happening to change timing a bit within the library. The function below was not the sole offender, but the primary one. It’s super-odd too. Originally, I was just doing writeByte for each character in the data structure. I then moved it into the arrays, and initially, no change. This is a table of contents for the memory chip I’m storing in sector 0. I keep it in RAM, and rewrite as new entries are added with this function. .eraseSector(), .eraseSection(), & .writeByte() all seem to cause the problem I’m describing. Not individually mind you, I can throw a few writeByte()s in there, but not more than 2 or so. The sector commands are a problem though. I read the docs, but I guess I’m still not 100% clear on what happens when I overwrite. It seems like it may erase the sector if it sees that it needs too, which would be ideal in my case as invoking it directly causes my DAC to slow down too much. For now, the modifications I made to this function below are allowing it to work.

void writetoc() {   
 byte array1[16];                                 //  This slows down the DAC!!! WHY!!!
 Serial.println(F("Writing TOC..."));
 //was using this, but it slows readByte down forever afterwards, and makes the DAC playback too slow
 //I think writebyte will delete before writing, but I'm not sure...
 //flash.eraseSection(0, 4096);
 for (int i=0;i<maxval;i++) {
  for (int j=0;j<9;j++) {
   array1[j]=TOC[i].name[j]; 
  }
  array1[9] =TOC[i].start00;
  array1[10]=TOC[i].start01;
  array1[11]=TOC[i].length00;
  array1[12]=TOC[i].length01;
  array1[13]=TOC[i].length02;
  array1[14]=TOC[i].normal;
  array1[15]=TOC[i].secret;
  flash.writeByteArray((i*16), array1, 16, false);
 }
 
 //was using this, but it slows readByte down forever afterwards, and makes the DAC playback too slow 
 //flash.writeByte(4093,((nextfreesec/256)-(nextfreesec%256)/256));  //it's ugly, but it's how it crept into my brain initially
 //flash.writeByte(4094,(nextfreesec%256));
 //flash.writeByte(4095,TOCCT);   //number of recs
 array1[0]=((nextfreesec/256)-(nextfreesec%256)/256);
 array1[1]=nextfreesec%256;
 array1[2]=TOCCT;
 flash.writeByteArray(4093, array1, 3, false);
 Serial.println();
 Serial.println(F("Done..."));
 Serial.println();
}

What still is totally crazy, is that if I just take this function unmodified over to another program with minimal other code, it will run just fine. It really didn’t start causing me grief until I added all of the F()s and freed up a ton of memory. Also. the total code is now around 60% of available size. I know this shouldn’t mean anything at all, but just something I noticed.

Worst case, erasing the whole chip still doesn’t cause an issue, so I may just have to go that route for now. It’s also worth noting that just the existence of these functions causes the issue immediately. I can never even call them, and I still have the problem. If I comment them out, of course, issue vanishes. So the compiler is doing something, but what?

Thanks!
-Kevin