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