T4.0 writing to EEPROM hangs when built using "Smallest Code" optimizaton

Status
Not open for further replies.

kd5rxt-mark

Well-known member
Setting the compiler optimization to "Smallest Code" seems to cause a fatal hang when writing to EEPROM on the T4.0. This can quickly be demonstrated using a slightly modified version of a small sketch that Paul posted in another thread where he was testing EEPROM write speed. I can't tell if the problem that I am seeing is unique to my specific Teensy4.0, or is in fact a problem on all T4.0s.

DETAILED NOTE: if a specific location in the EEPROM has previously been written to, the apparent hang may or may not occur. The hang can consistently be caused by writing 0xff to a specific location in EEPROM (which may or may not hang), then writing 0x00 to the same location (which always hangs). To make it easy to demonstrate in a single run, I modified Paul's simple sketch as follows:

Code:
#include <EEPROM.h>

void setup() {
  while (!Serial) ; // wait for Arduino serial monitor
  Serial.println("EEPROM write time test - writing 0xff");
  delay(25);
  unsigned int begin_usec = micros();
  EEPROM.write(9, 0xff);
  unsigned int end_usec = micros();
  Serial.print(end_usec - begin_usec);
  Serial.println(" microseconds");

  delay(1000);

  Serial.println("EEPROM write time test - writing 0x00");
  delay(25);
  begin_usec = micros();
  EEPROM.write(9, 0x00);
  end_usec = micros();
  Serial.print(end_usec - begin_usec);
  Serial.println(" microseconds");
}

void loop() {
}

Simply building this same code with the compiler optimization set to anything other than "Smallest Code" will always allow successful writes to the EEPROM on T4.0 using this simple test sketch.

Thanks,

Mark J Culross
KD5RXT

Edit: I posted <this> yesterday, but I think that post was in the wrong place. This post includes a much simpler way to demonstrate the problem, so the other can be deleted to avoid unnecessary cross-posting. MJC
 
Last edited:
I found a fix. @PaulStoffregen , C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4\eeprom.c, declare as volatile and initialize status for flash_wait function:
Code:
volatile uint8_t status = 0;

seems to be working fine now

Sketch:
Code:
#include <EEPROM.h>

void setup() {
  EEPROM.begin();
  while (!Serial) ; // wait for Arduino serial monitor
  Serial.print("EEPROM READ #1: "); Serial.println(EEPROM.read(9));
  Serial.println("EEPROM write time test - writing 0xff");
  delay(25);
  unsigned int begin_usec = micros();
  Serial.println("2");
  EEPROM.write(9, 0xff);
  Serial.println("3");
  Serial.print("EEPROM READ #2: "); Serial.println(EEPROM.read(9));
  unsigned int end_usec = micros();
  Serial.print(end_usec - begin_usec);
  Serial.println(" microseconds");

  delay(1000);

  Serial.println("EEPROM write time test - writing 0x00");
  delay(25);
  begin_usec = micros();
  EEPROM.write(9, 0x00);
  end_usec = micros();
  Serial.print("EEPROM READ #3: "); Serial.println(EEPROM.read(9));
  Serial.print(end_usec - begin_usec);
  Serial.println(" microseconds");
}

void loop() {
}


Output:
Code:
EEPROM READ #1: 0

EEPROM write time test - writing 0xff

2

WRITTEN

3

EEPROM READ #2: 255

15 microseconds

EEPROM write time test - writing 0x00

WRITTEN

EEPROM READ #3: 0

16 microseconds

yes, this is with Smallest Code optimisation :)
 
Last edited:
Working with "status" volatile: This must be a side-effect. It's filled by a volatile register?!
I tried this instead, and it works, too:

Code:
static void flash_wait()
{
    FLEXSPI_LUT60 = LUT0(CMD_SDR, PINS1, 0x05) | LUT1(READ_SDR, PINS1, 1); // 05 = read status
    FLEXSPI_LUT61 = 0;
    uint8_t status;
    do {
        FLEXSPI_IPRXFCR = FLEXSPI_IPRXFCR_CLRIPRXF; // clear rx fifo
        FLEXSPI_IPCR0 = 0;
        FLEXSPI_IPCR1 = FLEXSPI_IPCR1_ISEQID(15) | FLEXSPI_IPCR1_IDATSZ(1);
        FLEXSPI_IPCMD = FLEXSPI_IPCMD_TRG;
        while (!(FLEXSPI_INTR & FLEXSPI_INTR_IPCMDDONE)) {
//            asm("nop");[COLOR=#ff0000] //<-- not needed[/COLOR]
        }
        FLEXSPI_INTR = FLEXSPI_INTR_IPCMDDONE;
        asm("":::"memory");[COLOR=#ff0000] //<-- Insert[/COLOR]
        status = *(uint8_t *)&FLEXSPI_RFDR0;
    } while (status & 1);
    FLEXSPI_MCR0 |= FLEXSPI_MCR0_SWRESET; // purge stale data from FlexSPI's AHB FIFO
    while (FLEXSPI_MCR0 & FLEXSPI_MCR0_SWRESET) ; // wait
    __enable_irq();
}

Code:
EEPROM READ #1: 0
EEPROM write time test - writing 0xff
2
3
EEPROM READ #2: 255
12 microseconds
EEPROM write time test - writing 0x00
EEPROM READ #3: 0
14 microseconds
 
Status
Not open for further replies.
Back
Top