This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

NOR Flash EFS fopen() passes invalid address to flash driver

Hello,

It appears that when performing a fopen() operation, the EFS driver calls the flash driver ReadData() function many times. Sometimes the address provided to the driver is invalid. This is causing the fopen() operation to fail. I verified this is not a stack overflow issue.  

Keil Middleware Version 7.16.0

Event Viewer

Invalid Address Passed In

Flash Into Structure

static ARM_FLASH_INFO FlashInfo = {
NULL,
0x200000u / 0x1000u,
0x1000u,
0x100,
1,
0xFF,
#if (ARM_FLASH_API_VERSION > 0x201U)
{ 0U, 0U, 0U }
#endif
};

uVision Installation Info

  • Hi,

    what is the NOR flash base address? Valid addresses for your flash are from (BASE_ADDR) + [0 to 0x1FFFFF] and EFS should only use this range. If it uses something else, then something might be wrongly written into flash, since EFS first reads data from flash and based on the values read out, sets the next address to access (read).

  • The base address of the NOR flash is 0. Isn't the base address part of the FlashInfo structure shown above?

    The NOR flash was not blank. The chip erase failed. After fixing this issue I was able to use fopen().

    Questions:

    1. How can you determine if the file system has been initialized?
      1. finit() and fmount() always complete successfully. 
      2. fopen() assumes the flash contents have been initialized and may attempt to read invalid addresses
    2. Does the flash file system do wear leveling?

      FILE *f = fopen(DRIVE "\\ao2.cfg","rw");
      if (f == NULL) {
        printf("Error (%d) opening ao2config.bin\n", errno);
        f = fopen(DRIVE "\\ao2.cfg","w");
        if (f == NULL) {
          printf("Error (%d) creating ao2.cfg\n", errno);
        } else {
          //f = freopen("\\ao2.cfg","rw",f);
          fseek(f, 100, SEEK_SET);
          long pos = ftell(f);
          fseek(f, 0, SEEK_SET);
          memset(protbuf, 0x55, sizeof(protbuf));
          size_t wt = fwrite(protbuf, sizeof(protbuf), 1, f);
          fseek(f, 0, SEEK_SET);
          memset(protbuf, 0x00, sizeof(protbuf));
          size_t rt = fread(protbuf, sizeof(protbuf), 1, f);
          fflush(f);
          fclose(f);
        }
      }

    Observations:

    • don't seem to be able to open file in read and write. "rw" mode acts like "r"
    • opening file in write mode will create the file
    • write will not extend the file. You must use fseek() to expand the file. Then go back to write the data.
    • write mode does not allow read. How do you open in R/W mode
  • Which (NOR) Flash are you using? Having an fully functional driver is essential when using EFS, since EFS is extremely simple file system and it does not use boot information and cannot know if it was previously formatted or not.

    finit and fmount will return successfully whenever the Flash driver gets initialized successfully and the information from FlashInfo makes sense.

    EFS does not do wear leveling in the same sense as it is required by NAND flash, but it will distribute writes across the whole flash area. It invalidates data in old sector and goes writing into the new sector. When all data from the old sector is invalidated the sector gets erased. And this continues until the last sector is filled and then the process starts from the first sector again.

    NOR flash endurance is much higher comparing to NAND flash and therefore complex wear leveling is not required.

    Regarding your observations...
    - read write mode is not supported
    - yes
    - opening in write mode truncates the file, subsequent writes should extend the file
    - R/W mode is not supported

    As I said, EFS is extremely simple file system initially designed to store and read configuration data. It can handle much more, but is limited. 
    You can read more in the documentation:

    File System Component: Embedded File System (EFS)
    File System Component: Standard I/O Routines