thousandparadox@gmail.com
Member
I wrote a simple program that demonstrates inconsistent functionality of Emulated EEPROM on the Teensy LC
PROBLEM:
The EEPROM writes data correctly ~70% of the time. The correct data can be read back during runtime, but upon reboot the data is corrupted with two different writes or just garbage data.
As a second problem, the EEPROM will refuse to be written after one of these corruption occurs, but after ~200 write attempt's it starts to works again.
This is not a worn out memory issue, this is apparent with Teensy LC's fresh out of the package
This is not a power loss issue, this happens even when gracefully shut down.
Here are previous threads I have found that may have been experiencing the same issue:
https://forum.pjrc.com/threads/60298-Teensy-LC-Diagnose-EEPROM-Issue
https://forum.pjrc.com/threads/35302-Teensy-LC-internal-EEPROM-issue
https://forum.pjrc.com/threads/64233-TeensyLC-EEPROM-emulation
https://forum.pjrc.com/threads/55336-Teensy-LC-EEPROM-Write-Speed
I am a big fan of Teensy and Paul and have used Teensys for years in my personal projects and contract work. I have the Teensy LC in a custom circuit board that will benefit directly from a fix to this bug.
I would have added an external EEPROM but on short notice I just implemented CRC checks to my firmware. Right now the user has to power cycle the board to confirm their configuration numbers are actually working.
Thanks for reading my post, let me know if I can provide any more information.
PROBLEM:
The EEPROM writes data correctly ~70% of the time. The correct data can be read back during runtime, but upon reboot the data is corrupted with two different writes or just garbage data.
As a second problem, the EEPROM will refuse to be written after one of these corruption occurs, but after ~200 write attempt's it starts to works again.
This is not a worn out memory issue, this is apparent with Teensy LC's fresh out of the package
This is not a power loss issue, this happens even when gracefully shut down.
Here are previous threads I have found that may have been experiencing the same issue:
https://forum.pjrc.com/threads/60298-Teensy-LC-Diagnose-EEPROM-Issue
https://forum.pjrc.com/threads/35302-Teensy-LC-internal-EEPROM-issue
https://forum.pjrc.com/threads/64233-TeensyLC-EEPROM-emulation
https://forum.pjrc.com/threads/55336-Teensy-LC-EEPROM-Write-Speed
I am a big fan of Teensy and Paul and have used Teensys for years in my personal projects and contract work. I have the Teensy LC in a custom circuit board that will benefit directly from a fix to this bug.
I would have added an external EEPROM but on short notice I just implemented CRC checks to my firmware. Right now the user has to power cycle the board to confirm their configuration numbers are actually working.
Thanks for reading my post, let me know if I can provide any more information.
Code:
#include <EEPROM.h>
#define p Serial.print
#define pl Serial.println
// This program demonstrates the common malfunctions that occur with the Teensy LC emulated EEPROM
// INSTRUCTIONS:
// 1. Starts by reading back what is stored in EEPROM, comparing it to the bytes to see which bank number they could have come from. Ideally it should be a 100% match with one of the 10 banks.
// 2. Write a one of the banks, which bank is chosen is determined with a random seed.
// 3. Immediately read back the EEPROM, and compare each byte to find which bank it belongs to.
// 4. The user is then expected to turn off the teensy in between tests, taking note of what was the last bank number written.
// 5. Turn on the teensy again and see if it's the same bank, or if it's corrupted.
// 6. If it is corrupted... wait and watch as the written bytes don't stick, but after a while they start to again.
// RESULTS:
// after turning the teensy back on, the result of the test is:
// 1. the correct data is shown
// 2. half one bank, haf the other
// 3. garbage data with bytes that do not match.
// NOTES:
// This glitch is not a result of turning the teensy off in the middle of a write. It exprences the same behavior with a graceful shutdown in my other project.
// This glitch is not a result of worn out program memory. It happens with brand new Teensy LC right out of the bag.
//try out different number of bytes:
#define numbytes 57 // 1 to 128
uint8_t readback[128];
uint8_t bank = 0;
bool foundMatch = 0;
int32_t firstBankVal = 0;
bool res = 0;
uint8_t sudorandom[10][128] = {
{0x42,0xFB,0x9F,0xE0,0x59,0x81,0x5A,0x81,0x66,0xA1,0x0E,0x5C,0x4E,0xB4,0xDA,0xEC,0x2F,0xF5,0x60,0x7E,0x8A,0xEA,0x3B,0xCA,0x2B,0xD5,0x82,0x69,0x1D,0xC3,0x84,0x13,0x0E,0xA6,0x6A,0x10,0xB3,0x3C,0xB4,0x4E,0x9A,0x80,0x4F,0x61,0x06,0x82,0x17,0xF4,0xCA,0x76,0xBA,0x84,0xE2,0xDC,0xC9,0x66,0x4F,0xA5,0x07,0x8C,0x8E,0x36,0xD1,0x97,0xDC,0x70,0x1B,0x0F,0x38,0x8A,0xFB,0x91,0xB0,0x20,0xB7,0x9F,0x90,0x62,0x6C,0x81,0x19,0x11,0xC4,0x32,0x47,0x04,0xEF,0xFB,0x7D,0x8F,0xF2,0xC3,0xCE,0xCB,0xF9,0xE2,0xE0,0xE3,0x2D,0xB7,0x4E,0xE0,0x5F,0x8C,0x6D,0x68,0xD3,0x40,0x1F,0xD5,0xF4,0x31,0x99,0xB2,0x74,0x82,0x86,0xBF,0xB3,0xB5,0x07,0x3E,0xC2,0x52,0x8B,0x7E,0x70,0xA6},
{0x02,0x47,0x45,0xA0,0x23,0x37,0x17,0x7E,0x09,0x26,0x1F,0x3E,0xC7,0xBB,0xED,0xF9,0xC5,0xE5,0x9B,0x2D,0x02,0x81,0x0F,0x76,0x3F,0x2B,0x35,0x90,0x7F,0x5A,0x2F,0x14,0x3C,0x3B,0x1B,0x55,0x34,0x8A,0xC5,0x5B,0x50,0x45,0x8F,0x9E,0x4C,0x3D,0x8A,0x9F,0x96,0x85,0x15,0x80,0x93,0xFE,0xE6,0xC1,0x49,0x2E,0x95,0x8B,0xF6,0x00,0x24,0xE1,0xB4,0xF3,0x80,0x1B,0x03,0xDD,0xEE,0x2D,0x2A,0xE5,0xA4,0x79,0x5F,0xDA,0x0F,0x0C,0xE7,0xB5,0xB8,0x42,0xB2,0x06,0x51,0xC5,0x40,0x12,0x7C,0x7D,0xA7,0xCF,0xF3,0x1B,0x53,0x19,0x5E,0xAF,0xFC,0xE7,0x26,0x3B,0x86,0x05,0xAA,0x5F,0xAB,0x28,0xA0,0x34,0xB5,0xAB,0x83,0x2A,0xAC,0x70,0x72,0xA6,0x66,0x17,0xC7,0x01,0x58,0x63,0x45,0xBA},
{0xD9,0x7E,0xD2,0xDE,0x7E,0x70,0x1B,0xC3,0xEC,0xC8,0x8B,0x3D,0xF0,0xE8,0xDE,0xE7,0x6B,0xA2,0x68,0x26,0xAE,0x7C,0x9C,0x2A,0x20,0x7B,0x1B,0xAD,0x7B,0x65,0xE5,0x56,0x41,0xE8,0xBE,0x83,0x97,0x06,0xDB,0x86,0x4F,0x81,0xF3,0x66,0x57,0xCA,0x0F,0xA1,0xBD,0xF7,0x51,0xC9,0xE1,0xA5,0x12,0x3E,0x56,0x8E,0x43,0xF1,0xD2,0x74,0xC1,0x35,0x20,0x00,0x61,0xEE,0xA2,0x8F,0xC9,0x0D,0x03,0x4E,0x2A,0xBE,0xC4,0xBD,0x60,0xBA,0xA5,0x1D,0x1A,0x29,0xB4,0x86,0x04,0x72,0x5D,0x72,0xC4,0x1E,0xC4,0x9D,0xAC,0xFB,0x04,0x2F,0xE1,0x82,0xED,0x3D,0x12,0xAB,0x17,0xBB,0x3F,0xF9,0x70,0xB1,0x3B,0xF0,0xB7,0xE2,0x6F,0xF7,0x0D,0x56,0x40,0xBD,0x2B,0xE8,0x26,0x42,0x25,0xF9,0xA9,0xF9},
{0x19,0x60,0x06,0x2C,0xFE,0xCC,0x74,0x3A,0xEF,0xB0,0x93,0xC9,0xBF,0x2C,0xFF,0x45,0xFA,0x5B,0xB6,0x28,0xE7,0x0F,0xE0,0x9B,0x86,0x96,0x03,0x1B,0xB5,0x81,0xC8,0xD4,0x74,0x7A,0xE4,0x18,0xAE,0x96,0xFF,0xFE,0x7B,0x23,0x23,0x30,0xFB,0x74,0x7C,0xC6,0x05,0x63,0x96,0x38,0xFE,0x33,0xC6,0xD6,0x12,0x44,0xCD,0x38,0xD5,0xC5,0xAE,0xA6,0xCC,0x30,0xBC,0x6A,0x8B,0x13,0x7D,0x48,0xB1,0x5C,0x0A,0xA6,0x42,0x90,0xE0,0x74,0x63,0x54,0xE7,0xEA,0x1E,0xDC,0x74,0x79,0x2E,0xC8,0xA5,0x27,0xBB,0x5F,0x65,0x42,0xBA,0xA9,0x95,0xA1,0x48,0xA7,0x0E,0xBA,0x8E,0xB6,0x6F,0x4F,0xFF,0x34,0xD0,0x01,0x68,0xB7,0xC3,0x41,0xC2,0x1A,0x93,0x9F,0xFA,0x2D,0xDB,0x05,0xAF,0xA4,0xEB,0xFB},
{0x27,0x01,0x7F,0x90,0x09,0xDA,0x0C,0x1A,0x8E,0xFC,0x89,0xFC,0x4F,0x1F,0x8A,0x0D,0xF2,0x12,0xD0,0x17,0xFC,0xEF,0xE3,0x56,0xF0,0x32,0xC8,0xBB,0x58,0x7B,0xC5,0x10,0xDD,0x9D,0x9F,0x44,0x12,0x80,0xF4,0x6B,0x9F,0xE4,0x9F,0xF7,0x98,0x2D,0x02,0x8B,0x7F,0x17,0x8D,0x63,0xAD,0x97,0x9A,0xC0,0x99,0xEF,0xEF,0x52,0x54,0x4F,0xD3,0xC2,0x28,0xD2,0xC4,0x49,0xAE,0xF0,0x94,0x9B,0x6F,0xCB,0x5C,0x21,0xD3,0x1D,0x37,0x0A,0x52,0x7D,0x45,0x5A,0x08,0x78,0xE7,0x93,0x1B,0x4E,0x9C,0x03,0x68,0xC6,0x59,0x08,0xC4,0x73,0x0A,0x89,0x9F,0x4B,0x9C,0xB7,0xD4,0x82,0x7F,0x49,0xEE,0xFE,0x59,0x00,0xF6,0x79,0x70,0xC9,0x34,0x92,0xCC,0xB1,0xF3,0x36,0xE6,0x5D,0xBC,0xDA,0x05,0x65},
{0xBA,0xEF,0x0B,0x18,0x49,0x6A,0x80,0xFA,0x31,0x1D,0x18,0xC6,0x49,0xCC,0x79,0x9F,0xE7,0x43,0x8E,0x23,0x7E,0x03,0xA1,0x65,0x05,0x16,0xD6,0x11,0x41,0x47,0x67,0x87,0x40,0x70,0xD2,0xF6,0x1A,0x95,0x7C,0xE2,0x97,0xFF,0x97,0x3A,0xA9,0x9C,0x5E,0xAC,0xA3,0xFC,0x86,0x21,0x97,0xF1,0xF0,0x48,0xA0,0x2A,0xCE,0x79,0xFC,0x52,0x79,0xF9,0xC8,0x82,0x5E,0x8F,0x12,0x7D,0xBC,0x02,0x72,0xB6,0x11,0x15,0x39,0xAC,0x41,0x0E,0x0E,0x28,0xC1,0xFA,0x7E,0x8C,0x9B,0xB4,0x3B,0xF8,0xA6,0x13,0x73,0xE7,0x7A,0x4C,0x15,0x2A,0x26,0xBD,0x37,0x02,0xF0,0x7F,0x3F,0xFA,0x6B,0x15,0xEF,0x93,0x8A,0x03,0xD9,0xBE,0x4A,0x35,0x5C,0x15,0x82,0xDD,0x8E,0xBC,0x5D,0x4F,0x91,0xBE,0x2A,0x8C},
{0xEC,0x91,0x10,0xF7,0x7A,0x7E,0x26,0x42,0x81,0xF5,0x50,0x8D,0x3F,0x1E,0x51,0x16,0x17,0x11,0x8F,0x25,0xFB,0xA2,0x0D,0x01,0xF1,0xB9,0x0A,0xF4,0xA4,0x16,0xFC,0xD2,0x4D,0x7F,0xD1,0x9A,0xDE,0x56,0x60,0xEF,0xEB,0x6C,0xBC,0xC1,0xE6,0xF1,0x07,0xA5,0x71,0x41,0x6A,0x43,0x98,0x17,0xDA,0x34,0x65,0x7A,0x15,0xD2,0xE5,0x51,0x7D,0xF6,0x87,0x4E,0x92,0x48,0x35,0xBE,0x7C,0x4E,0x7B,0xD0,0x25,0x0F,0x02,0xC5,0x79,0x8B,0x61,0xEA,0xF1,0xAC,0xF4,0x3C,0xA8,0x01,0xF3,0x20,0x1D,0x9C,0x8B,0x5E,0xDD,0x22,0xA1,0x78,0x44,0x41,0x33,0x3E,0x5C,0xA8,0x57,0x94,0xAD,0x3A,0x06,0xF8,0x81,0x18,0xC5,0x2A,0x5A,0xC8,0x21,0xDB,0x88,0xAC,0x67,0xCC,0x3D,0xBC,0xA8,0x67,0x8F,0x55},
{0xCE,0xED,0x2B,0x74,0x17,0x2E,0x7C,0x29,0xA5,0x5C,0x94,0xF9,0xD9,0x43,0x06,0x47,0x70,0x87,0x81,0x33,0x33,0x94,0x15,0x33,0x9D,0x4D,0x45,0x1D,0xF5,0xE4,0xF7,0x83,0x38,0xE9,0x55,0xAA,0xA6,0x70,0x93,0x42,0x3B,0x7E,0xA3,0x78,0xFF,0x31,0xE0,0xB0,0x9C,0x03,0x9C,0x4C,0x84,0x45,0x55,0x9F,0x5B,0x3E,0x4B,0x04,0xD8,0xB5,0xC8,0x5E,0x3A,0x42,0xF4,0x3C,0x39,0x4B,0xFD,0xF0,0xAB,0x24,0x50,0x70,0xFD,0x77,0x0D,0x19,0x57,0x1A,0x09,0x77,0xAE,0x2C,0x61,0xB5,0x80,0x18,0x3A,0xD7,0x38,0x3A,0x02,0x53,0x10,0x14,0xE8,0x4A,0x65,0x48,0x4F,0x98,0xE4,0xDA,0xFE,0x44,0xB1,0xA6,0x25,0x5C,0xA8,0x78,0x57,0xC1,0x06,0x3D,0x3C,0xA7,0x02,0x78,0x60,0x39,0x0A,0x75,0x0C,0x71},
{0x2F,0xF7,0x3F,0xC6,0x7D,0x5A,0x9A,0xB9,0x34,0x9C,0x0D,0x60,0xA0,0x38,0x38,0xC9,0xFF,0x06,0x1D,0x7F,0xC7,0xEC,0xD6,0xE2,0xD2,0x28,0x90,0x5A,0x1B,0x46,0x2D,0x2B,0x75,0xA9,0x22,0xCD,0xB4,0xB4,0xB0,0xA9,0x79,0x44,0x29,0xAD,0x67,0x0C,0x90,0xD9,0xFD,0xF5,0x1A,0x69,0x3B,0xFD,0x9B,0x51,0x87,0x66,0x50,0xD6,0x68,0x8F,0xBD,0xA7,0x30,0x58,0xC2,0x80,0xED,0x81,0xCD,0x99,0x57,0xD8,0x6B,0xA0,0x0E,0x57,0x33,0x3B,0x0A,0xB0,0x34,0x84,0x28,0x85,0x91,0xBB,0xE8,0x96,0xB9,0xA7,0xAD,0x9A,0x0F,0x21,0x2A,0x9A,0x90,0xA3,0x6E,0x90,0xAE,0xB8,0x9A,0x46,0x12,0xBC,0x54,0x92,0x39,0x62,0x8F,0x1B,0xA4,0x48,0x35,0x3B,0x43,0x17,0x7F,0x12,0xF3,0x7A,0xEA,0x8C,0x80,0xD0},
{0x3F,0x93,0xD9,0xD4,0x2A,0x64,0x00,0x73,0x2B,0x9A,0x38,0x29,0x70,0x01,0xBF,0xBE,0xCE,0xF7,0x02,0x51,0x74,0x6E,0x01,0x61,0x1F,0x54,0xB0,0x61,0xB7,0x14,0x09,0x52,0x57,0x97,0xFE,0x41,0x63,0xBB,0x47,0x6E,0x11,0x0E,0x24,0x13,0x93,0x6C,0x96,0x0D,0x2D,0xEF,0x4F,0x49,0xFC,0xE9,0x2F,0x84,0xC6,0x3B,0x12,0x78,0x4E,0x04,0xAB,0x04,0xA5,0x9D,0xBE,0xB5,0x9D,0x01,0xEA,0x57,0x71,0xC4,0x7C,0xA7,0xB7,0xA2,0xCA,0x6E,0x75,0xE9,0xE9,0xB2,0x2E,0xB5,0x42,0x2D,0x8E,0xFF,0xB2,0x16,0xD3,0xD4,0x3A,0x6C,0x51,0xF8,0x1A,0x04,0x87,0x66,0xBF,0x42,0xFD,0x5B,0x02,0x4B,0x7A,0x78,0xC5,0xD4,0x92,0xBD,0x64,0x37,0xF1,0x35,0x9D,0xA5,0xD2,0x66,0xF7,0xF0,0x97,0x76,0xDF,0x5C}
};
// 0 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 20 1 2 3 4 5 6 7 8 9 30 1 2 3 4 5 6 7 8 9 40 1 2 3 4 5 6 7 8 9 50 1 2 3 4 5 6 7 8 9 60 1 2 3 4 5 6 7 8 9 70 1 2 3 4 5 6 7 8 9 80 1 2 3 4 5 6 7 8 9 90 1 2 3 4 5 6 7 8 9 100 1 2 3 4 5 6 7 8 9 110 1 2 3 4 5 6 7 8 9 120 1 2 3 4 5 6 7
void setup() {
Serial.begin(115200);
delay(1000);
pl("Random number banks");
for(int k = 0; k < 10; k++){
p(" Bank #"); p(k); p(": ");
for(int i = 0; i < numbytes; i++){
pHEX(sudorandom[k][i]);p(" ");
}
pl();
}
pl();
p("Reading EEPROM: ");
for(uint8_t i = 0; i < numbytes; i++){
readback[i] = EEPROM.read(i);
pHEX(readback[i]); p(" ");
}
pl();
analyzeReadback();
randomSeed(analogRead(A0));
}
void loop() {
bank = random(10);
p("Writing bank ");p(bank); p(": ");
for(uint8_t i = 0; i < numbytes; i++){
EEPROM.write(i , sudorandom[bank][i]);
pHEX(sudorandom[bank][i]); p(" ");
}
pl();
p("Reading EEPROM: ");
for(uint8_t i = 0; i < numbytes; i++){
readback[i] = EEPROM.read(i);
pHEX(readback[i]); p(" ");
}
pl();
analyzeReadback();
delay(1500);
}
bool analyzeReadback(){
foundMatch = 0;
res = 1;
firstBankVal = -1;
p(" Bank Match: ");
for(int i = 0; i < numbytes; i++){
foundMatch = 0;
for(int k = 0; k < 10; k++){
if(sudorandom[k][i] == readback[i]){
p(k);
foundMatch = 1;
if(firstBankVal == -1){firstBankVal = k;}
if(firstBankVal != k){res = 0;}
break;
}
}
if(!foundMatch){
res = 0;
p("-");
}
p(" ");
}
pl();
if(res){
pl(" match :) ");
return 1;
}else{
pl("[[[ ERROR DETECTED! ]]]");
return 0;
}
}
void pHEX(uint8_t val){
if(val < 16){
p('0');
}
p(val,HEX);
}