Hi, Folks,
Hopefully, someone can shed some light to this. Thanks.
I am using the LPC2000 IAP functions to put user data in to flash, but I got a weird problem. My target MCU is a LPC2214 and debugger is the Keil uvision 3.05 + ULink2. I have a MSB2100 evaluation board but it's broken, so I cannot test this on it.
The following is the test program. For each user, I read the 512 bytes block the user should be in to a RAM buffer, update the user data and then program the buffer back in.
The problem is the programed data are often not consistent with the data in the RAM buffer. I programmed 8000 users, usually this will happen more then 1000 times. The following example is one of them. The user number 7 was wrong, and this happened when user 8 was programmed. I had erased this section before I ran this function and checked all data in the section were 0xFF. In the whole process, the IAP functions return 0 (CMD_SUCCESS)
d 0x10000 0x00010000 01 00 00 00 10 FF FF FF 0x00010008 02 00 00 00 10 FF FF FF 0x00010010 03 00 00 00 10 FF FF FF 0x00010018 04 00 00 00 10 FF FF FF 0x00010020 05 00 00 00 10 FF FF FF 0x00010028 06 00 00 00 10 FF FF FF 0x00010030 07 00 02 00 10 FF FF FF 0x00010038 08 00 00 00 10 FF FF FF 0x00010040 FF FF FF FF FF FF FF FF 0x00010048 FF FF FF FF FF FF FF FF .......ALL oxFF
d flash_buffer 0x4000021C 01 00 00 00 10 FF FF FF 0x40000224 02 00 00 00 10 FF FF FF 0x4000022C 03 00 00 00 10 FF FF FF 0x40000234 04 00 00 00 10 FF FF FF 0x4000023C 05 00 00 00 10 FF FF FF 0x40000244 06 00 00 00 10 FF FF FF 0x4000024C 07 00 00 00 10 FF FF FF 0x40000254 08 00 00 00 10 FF FF FF 0x4000025C FF FF FF FF FF FF FF FF 0x00000264 FF FF FF FF FF FF FF FF .......ALL oxFF
//////////////my test program////////////// typedef struct { unsigned long id; BYTE zone; } USER_DATA; unsigned char flash_buffer[512]; //the start address of users in flash (64k block) USER_DATA *user = (USER_DATA *)0x10000; unsigned long blockerrors = 0; unsigned long singleerrors = 0; void test_user() { unsigned long i; unsigned char *program_addr; USER_DATA temp_user; for(i = 1; i <= 8000, i++) { //get the 512 bytes block base address the current user is in. program_addr =(BYTE*)((unsigned int)(&user[i]) & 0xFFFFFE00); //update the user in the buffer. memcpy((void*)flash_buffer, (void*)program_addr, 512); temp_user = (USER_DATA*)(flash_buffer + (((BYTE*)(user + i)) - program_addr)); temp_user->id = i; temp_user->zone = 16; //program the flsh FlashProgram((uint)program_addr, flash_buffer, 512); if(memcmp(flash_buffer, program_addr, 512)) //check block programming errors ++blockerrors; if(i != user[i].id) // ++singleerrors; DELAY(100); //delay 100 millisends } } #define XTAL_HZ 10000000 // Oscillator Frequency in HZ #define PLL_MUL 6 #define VPB_DIVIDER 4 // VPB Clock divider #define CPU_CLK_HZ (XTAL_HZ*PLL_MUL) // CPU Clock (cclk) in HZ #define CPU_CLK_KHZ (CPU_CLK_HZ / 1000) // CPU Clock (cclk) in kHz #define VPB_CLK_HZ (CPU_CLK_HZ / VPB_DIVIDER) // VPB Clock (pclk) in Hz struct iap_in { uint cmd; uint par[4]; }; typedef void (*IAP)(struct iap_in *in, uint *result); #define IapEntry ((IAP) 0x7FFFFFF1) // IAP Entry Point uint FlashProgram (uint addr, uchar *data, uint size) { struct iap_in iap; // IAP Input Parameters uint result[16]; // IAP Results assert(FlashGetSecNum (addr) >= 8); di(); // disable all interrupts iap.cmd = 50; // IAP Command: Prepare Sectors for Write iap.par[0] = FlashGetSecNum (addr); // Start Sector iap.par[1] = iap.par[0]; // End Sector IapEntry (&iap, result); // Call IAP Function if (result[0]) goto exit; // Error occured? iap.cmd = 51; // IAP Command: Copy RAM to Flash iap.par[0] = addr; // Destination Address iap.par[1] = (uint) data; // Source Address iap.par[2] = size; // Number of Bytes iap.par[3] = CPU_CLK_KHZ; // CPU Clock IapEntry (&iap, result); // Call IAP Function exit: ei(); // enable all interrupts return (result[0]); }