Me and my SW colleague have struggled quite a lot with the flash memory and finally we found the problem!
First, since Hayden pointed out that there could be different flash models we checked this and found that our XEM6001 have Numonyx while the XEM7001 has an ISSI. Even though they are supposed to be equivalent we checked the datasheets and found out that the read data is stable on rising clock edge for Numonyx but on the falling edge for ISSI.
However, in our case the read clock is quite slow and due to the time margin this turned out to have no effect in our implementation, but might help someone else
The problem we experienced was the worst kind; it worked “sometimes”. After hours of testing different operation sequences, data, and addresses; this was our basic conclusions:
- It works if starting to write at address 0, then the full memory may be written with valid data in a long sequence.
- If the start write address is in another location, the data is sometimes valid but often fully or partly corrupted.
Any guess what caused this? If you want to figure it out, then stop here to think before reading the spoiler a bit further down
Naturally, our first thought was that the problem must be our own reading functionality. So we tried to push this part to the limits by jumping back and forth between memory addresses, and these results were always consistent.
Furthermore, we have two different read operations; one where we read one page and send the result as a message through an okPipeOut component and one where we only read 4 bytes and set in registers (okWireOut), which both give the same data.
So then we were quite sure that the root cause unexpectedly must be within the write operation. After even more tests we finally found out that the errors more specifically came from the erase operation!
In XEM6001 we only used sector 32, starting at address 0x200000. It then worked to activate the erase in any single sector:
m_pXEM->SetWireInValue(0x00, address); // Send starting address
m_pXEM->SetWireInValue(0x01, nbrsectors); // Send the number of sectors to erase
m_pXEM->UpdateWireIns();
m_pXEM->UpdateTriggerOuts(); // Makes sure that there are no pending triggers back
m_pXEM->ActivateTriggerIn(0x40, 3); // Trigger the beginning of the sector erase routine
For some reason this does not work with XEM7001. Do we need to change something in these function calls?
As I mentioned in my first post, we use flashloader.bit to write the flash. So my guess would be that’s where the actual error is… Can anyone confirm?
Since it works to erase the whole flash (address = 0 and nbrsectors = 64), or as far as you want as long as you start from address 0, this is a simple workaround. But there could of course be situations when it’s not suitable to erase everything before the actual write position, so it would be nice with a solution to this issue
Best Regards,
Kenny