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

Need support for configurating the Flashfilesystem?

Hello,

I'm writing this huge Forum request because the Keil support didn't answer my email support request in a proper way, yet. I'm a bit disappointed, so I hope somebody else might help me...Maybe I'm not the only one, who has problems with the flashfilesystem.

I want to use the flashfilesystem delivered with the RealTime Libary on the on the MCB2300 board (with LPC2378 from NXP). Using ARM-MDK (3.04) and RL-ARM (3.04).

First I'm describing my configuration of the FFS and after that I explain my problems.

The flashfilesystem should be placed in the upper 5 sectors of the internal flash of the microcontroller.

So this is my device configuration file FS_FlashDev.h:

...
//Definition of the FlashSectors used by the Flash File System
// DFB( size   , baseadr ),   /* Comment                 */ \ <-- macro continuation sign (Don't forget)
#define FLASH_DEVICE                                \ 
   DFB(0x001000, 0x000000),   /* Sector Size 4kB */ \ 
   DFB(0x001000, 0x001000),   /* Sector Size 4kB */ \ 
   DFB(0x001000, 0x002000),   /* Sector Size 4kB */ \ 
   DFB(0x001000, 0x003000),   /* Sector Size 4kB */ \ 
   DFB(0x001000, 0x004000),   /* Sector Size 4kB */ \ 
// Number of previously defined sectors
#define FL_NSECT    5

I setup the File_Config.c like this:

Flash Drive Option                              checked
        Target device Base address              0x0007 8000
        Device Size in bytes                    0x0001 0000
        CPU Clock Frequency[Hz]                 48000000
        Initial Content of Erased Memory        0xFF
        Device Description File                 FS_FlashDev.h
Default Drive:          Flash


Comment: I'm not sure if I configured the Target device Base address correctly. According to the documentation it specifies the device base address in the memory space of ARM processor
I guess in my case it's the absolute starting address of the first Sector defined in the FS_FlashDev.h.

  • I took the flashprogramming routines from the directory C:\Keil\ARM\Flash\LPC_IAP2_512 and modified them accordingto the documentation. This is the resulting FS_FlashPrg.c:

    #include <File_Config.h>
    
    #define STACK_SIZE     64      // Stack Size
    
    #define SET_VALID_CODE 1       // Set Valid User Code Signature
    
    #define PAGE_SZ 256            // Page Size
    
    U32 Page[PAGE_SZ/4];           // Page Buffer
    
    unsigned long CCLK;            // CCLK in kHz
    
    struct sIAP {                  // IAP Structure
      unsigned long cmd;           // Command
      unsigned long par[4];        // Parameters
      unsigned long stat;          // Status
    } IAP;
    
    
    /*
     * IAP Execute
     *    Parameter:      pIAP:  Pointer to IAP
     *    Return Value:   None (stat in IAP)
     */
    
    void IAP_Execute (struct sIAP *pIAP);
    
    
    /*
     * Get Sector Number
     *    Parameter:      adr:  Sector Address
     *    Return Value:   Sector Number
     */
    
    unsigned long GetSecNum (unsigned long adr) {
            unsigned long n;
    
            n = (adr >> 12) & 0x7F;                      // Pseudo Sector Number
            if (n >= 0x78) {                             // High Small 4kB Sectors
                    n -= 0x62;
            }
            else if (n >= 0x08) {                        // Large 32kB Sectors
                    n  = 0x07 + (n >> 3);
            }
            return (n);                                  // Sector Number
    }
    
    
    /*
     *  Initialize Flash Programming Functions
     *    Parameter:      adr:  Device Base Address
     *                    clk:  Clock Frequency (Hz)
     *                    fnc:  Function Code (1 - Erase, 2 - Program, 3 - Verify)
     *    Return Value:   0 - OK,  1 - Failed
     */
    int fs_Init (U32 adr, U32 clk) {
    
      CCLK = clk / 1000;            //convert Hz to kHz
      return (0);
    }
    
    /*
     *  Erase Sector in Flash Memory
     *    Parameter:      adr:  Sector Address
     *    Return Value:   0 - OK,  1 - Failed
     */
    int fs_EraseSector (U32 adr) {
    
    
      unsigned long n;
    
      n = GetSecNum(adr);                          // Get Sector Number
    
      IAP.cmd    = 50;                             // Prepare Sector for Erase
      IAP.par[0] = n;                              // Start Sector
      IAP.par[1] = n;                              // End Sector
      IAP_Execute (&IAP);                          // Execute IAP Command
      if (IAP.stat) return (1);                    // Command Failed
    
      IAP.cmd    = 52;                             // Erase Sector
      IAP.par[0] = n;                              // Start Sector
      IAP.par[1] = n;                              // End Sector
      IAP.par[2] = CCLK;                           // CCLK in kHz
      IAP_Execute (&IAP);                          // Execute IAP Command
      if (IAP.stat) return (1);                    // Command Failed
    
      return (0);                                  // Finished without Errors
    }
    
    
    /*
     *  Program Page in Flash Memory
     *    Parameter:      adr:  Page Start Address
     *                    sz:   Page Size
     *                    buf:  Page Data
     *    Return Value:   0 - OK,  1 - Failed
     */
    int fs_ProgramPage (U32 adr, U32 sz, U8 *buf) {
      U32 padr, ofs, cnt, n;
    
      IAP.cmd    = 50;                             // Prepare Sector for Write
      IAP.par[0] = GetSecNum(adr);                 // Start Sector
      IAP.par[1] = GetSecNum(adr + sz - 1);        // End Sector
      IAP_Execute (&IAP);                          // Execute IAP Command
      if (IAP.stat) return (1);                    // Command Failed
    
      while (sz) {                                 // Go through all Data
        padr = adr & ~(PAGE_SZ - 1);               // Page Address
        ofs  = adr - padr;                         // Data Offset
        cnt  = PAGE_SZ - ofs;                      // Data Count
        if (cnt > sz) cnt = sz;                    // Adjust Data Count
        if (cnt != PAGE_SZ) {                      // Incomplete Page being written
          for (n = 0; n < PAGE_SZ/4; n++) {        // Go through complete Page
            Page[n] = *((U32 *)padr + n);          // Read Page Data from Flash
          }
        }
        for (n = 0; n < cnt; n++) {                // Go through Page Data
          *((U8 *)Page + ofs++) = *buf++;          // Copy & Align to Page Buffer
        }
    
        IAP.cmd    = 51;                           // Copy RAM to Flash
        IAP.par[0] = padr;                         // Destination Flash Address
        IAP.par[1] = (U32)Page;                    // Source RAM Address
        IAP.par[2] = PAGE_SZ;                      // Page Size
        IAP.par[3] = CCLK;                         // CCLK in kHz
        IAP_Execute (&IAP);                        // Execute IAP Command
        if (IAP.stat) return (1);                  // Command Failed
    
        adr += cnt;                                // Next Address
        sz  -= cnt;                                // Next Size
      }
    
      return (0);
    }
    

  • I finally added the IAP.s file for calling the IAP routine of the microcontroller and the RTLFS.lib.
    Everything was compiled, linked and loaded to the MCB2300 board.

    I created a simple testing programm:

    ...
    int main (void) {
            FILE *filehandle;
            int ch,i;
    
            ...
            printf ("Initialize Flash File System...");
            i = finit();
            if( i != 0 )
            {
                    printf ("(finit = %d)Failed\n",i);
            }
            else
            {
                    printf ("(finit() = %d)OK\n",i);
            }
    
            printf("Formatting Flash File System...");
            if ( fformat ("F:")   != 0 ){
                    printf ("Failed\n");
            }else{
                    printf ("OK\n");
            }
    
            printf("Writing a small Testfile...");
            filehandle = fopen ("F:Test.txt","w");
            if (filehandle == NULL) {
                    printf ("File not found!\n");
            }else {
                    printf("File opened...");
                    printf("%d Bytes written to File...",
                                    fprintf( filehandle, "0123456789" ));
                    fclose ( filehandle );
                    printf("File closed\n");
            }
    
            printf("Read back the written File...");
            filehandle = fopen ("F:Test.txt","r");
            if (filehandle == NULL) {
                    printf ("File not found!\n");
            }else {
                    printf("File opened...");
                    // Read all characters from the file
                    while ( !feof (filehandle) ) {
                            ch = fgetc ( filehandle );
                            printf("%c", ch );
                            if ( ferror (filehandle)) {
                                    printf ("File read error...");
                                    break;
                            }
                    }
                    fclose ( filehandle );
                    printf("File closed\n");
            }
    
            printf ("Checking Flash File System...");
            if (fcheck ("F:") != 0)
            {
                    printf ("Failed\n");
                    printf ("Flash File System inconsistent, formatting...");
            }
            else
            {
                    printf ("OK\n");
            }
            while(1);
    }
    

    So I have the following result:
    1. finit returns with "(finit() = 1)Failed"

    2. fformat returns with "OK"

    3. Writing to file is working. When I set a breakpoint in debugging mode after closing the written file, the correct filename is displayed in the Peripheral->RTX-Kernel->Flashfilesystem tab. When I check the memory position of the first sector, I can see the data written to the flash.

    4. Reading the file doesn't work correctly. It doesn't read anything useful, because it seems to read from the wrong position and so
    it could not detect the file end and is reading without stopping...

    So I would be happy, if anybody can give me some hints, what I have done wrong.

    Thank you to all the people taking the time to read this text to help me....

    Rainer

  • Just to inform others who may have the same problems:

    I got some proper information from keil support , that the issue is due to the ECC of the LPC2378 flash memory.

    So I made some tests writing data with inbuild IAP routine of the LPC2378 and read it again. So my current result is that the first writing to a position works, but the second write doesn't work. So it seems the IAP routine doesn't work properly and so it's not possible for the filesystem to write the data correctly to the internal flash of the LPC2378.

  • Rainer,
    followed is some advices, can be useful:
    -make sure you read errata sheet for your chip. Some manufacturers does not provides programming internal flash on max speed.
    -try use fwrite and fread functions instead fprintf and fgetc.
    -make sure you include "retarget.c" file in project.
    -try start using file system in RAM memory first, then move to flash.

  • Mikhail Sokolov,

    thanks for hints!

    I contacted the support of NXP, now. To get some more information about the problem with the IAP routine. But this will take some time.

  • LPC2148 uses ECC flash data protection algorithm. This means it has a hidden byte where a control code for the flash page is stored. Based upon this data, an automatic error correction of a few bits in a page is possible. This makes the flash data reliability much better, but on the other hand has a side effects. You can not write tha flash page twice, this means you must write the whole page only once and then erase the whole sector. I think that one page is 16 (or maybe 32) bytes. IAP routines are able to write only 512/1024 byte blocks.

    Flash File System does not work with ECC pages so this is the reason it is unusable for internal flash on devices using ECC.

  • hello
    Rainer, did you got some information from keil suport?
    because i also got some problems with the flashfile system and the internal flash!
    So if you got new information could you post it please.
    thanks
    ROmain

  • Hello MOURA Romain,

    as I already posted on 13-Feb-2007 04:04 in my case the problem is the ECC Code of the internal flash memory of the LPC23xx. It's like Franc Urbanc wrote above. To write some bytes to the flash, the whole sector must be erased before you can write one time. To write again somewhere to this sector the sector must be erased again. So it's impossible to use the internal flash memory of the LPC23xx as fast working flash filesystem.

    So you need some kind of external flash memory without ECC when you use an LPC23xx.

    Rainer