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.

Parents
  • 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);
    }
    

Reply
  • 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);
    }
    

Children
No data