IAP Using USBVirtualCOM on LPC1788

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

IAP Using USBVirtualCOM on LPC1788

1,657 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by pcproa on Tue Oct 09 06:49:32 MST 2012
Hello,

I am having a problem with IAP on my LPC1788. I have merged two GIT examples by using Virtual COM port to download the entire new firmware to the SDRAM, using all of the Checksum data from the Hex File on the Host computer. Once everything is downloaded into a normal binary sequence on SDRAM, I start the process of CopyRAM2Flash in 1024byte sections into the flash from the starting address in the hex file.

Everything seems to copy successfully, but once the LPC1788 goes into ‘Compare’ it fails on the first or second 1024 byte compare loop.

I have even tried loading one solid value into the entire flash and tried comparing. It will always fail. In Keil, I try running debug. I set my debugger to run the firmware update. Once it fails I restart the debugger and verifiy the contents in the flash address that the Hex file said to write to, and it is always the same.

The CMSIS/GIT example linked below for IAP usage works start to finish on the same board. Compare and everything. The difference is, mine initializes the internal EEPROM, LCD, SDRAM, and the USB. In the future, it may also initialize SPI so I can use the touch screen controller. However, the IAP example just initializes UART0, where I do not in my program.

IAP Demo Used:
http://sw.lpcware.com/?p=lpc177x_8x.git&a=tree&h=c38c91aded3d473f12b1999431c6bc9556866af5&hb=5032933...

USB Virtual COM Demo Used:
http://sw.lpcware.com/?p=lpc177x_8x.git&a=tree&h=3546301845bdc9d998af808a01231228180237bd&hb=5032933...

I always get the value returned from Compare, 10, as COMPARE ERROR.
Sometimes I comment out the Compare section to test to see if the program will run after the IAP program loads it into flash. My IAP is set to load the downloaded programs to starting address 0x8000.

Once in a while I’ll have the LCD Backlight come on since it is set at the beginning of the main loop of the downloaded program as a test. Sometimes it will do a step or two further and clear the screen as well to a colour I set (Usually Red or Green)

And here is the full code section in cdcuser.c where I download the data to SDRAM, then load from SDRAM into internal Flash using intermediate buffers.

<code>
case 'd': // Start the download
{
    //uint8_t * dest = (uint8_t *)((BulkBufOut[2] << 8) | (BulkBufOut[3]));
    int x;
    Font fnt = {0xFFFFFFFF, 0xFF000000, 8, 13};
    uint8_t good = 1, bad = 0;
    uint32_t checkSum = 0;
    for (x = 0; x < BulkBufOut[1] + 4; x++)
        checkSum += BulkBufOut[x + 1];
    checkSum = (0x100 - checkSum) & 0xFF;
    if (checkSum == BulkBufOut[5 + BulkBufOut[1]])
    {
        if (BulkBufOut[4] == 00) // If the type is data record
        {
            memmove((uint8_t*)dest, (uint8_t*)&BulkBufOut[5], (uint8_t)BulkBufOut[1]);
            //memset(dest, 2, BulkBufOut[1]);
            dest += BulkBufOut[1]; // Increase the Buffer by the amount of bytes recieved

            currentAddress &= 0xFFFF0000;
            currentAddress |= ((BulkBufOut[2] << 8) | (BulkBufOut[3]));

            if (flashstartaddress > currentAddress)
                flashstartaddress = currentAddress;
            if (flashendaddress < currentAddress)
                flashendaddress = currentAddress;
        }
        else if (BulkBufOut[4] == 04)
        {
            currentAddress &= 0xFFFF;
            currentAddress |= (((BulkBufOut[5] << 24) | (BulkBufOut[6])) << 16);
        }
        USB_TX((uint8_t*)&good, 1); // Send good value for next set

        if (BulkBufOut[4] == 01) // End of hex file
        {
            uint32_t flash_prog_area_sec_start;
            uint32_t flash_prog_area_sec_end;
            uint32_t one, two;
            int i;
            uint8_t __attribute__ ((aligned (4))) * ptr;
            uint8_t __attribute__ ((aligned (4))) * emcBuffer;// = (uint8_t *)(0xA0000000 + (LCD_WIDTH * LCD_HEIGHT * sizeof(uint32_t)));
            uint8_t __attribute__ ((aligned (4))) buffer[1024];

            IAP_STATUS_CODE status;
   
            clear(0,0,0);
            print("Starting Load", 0, 0, &fnt);

            NVIC->ICER[0] = 0xFFFFDFFF; // Disable the interrupts
            NVIC->ICER[1] = 0xFF;

            // Load firmware and execute user code
            flash_prog_area_sec_start = GetSecNum(flashstartaddress);
            flash_prog_area_sec_end =  GetSecNum(flashendaddress);

            status = EraseSector(flash_prog_area_sec_start, flash_prog_area_sec_end);
            if (status != CMD_SUCCESS)
            {
                clear(0xFF,0,0);
                print("Erase Error", 0, 0, &fnt);
                ShowInt(status, 13, 0, &fnt);
                while(1);
            }
            print("Erasing Complete", 13, 0, &fnt);
            status = BlankCheckSector(flash_prog_area_sec_start, flash_prog_area_sec_end, &one, &two);
            if (status != CMD_SUCCESS)
            {
                clear(0xFF,0,0);
                print("Blank Check Error", 0, 0, &fnt);
                while(1);
            }
            print("Blank Check Complete", 26, 0, &fnt);
            for (i = 0; i < ((flashendaddress - flashstartaddress) / 1024) + 1; i++)
            {
                ptr = (uint8_t*)(flashstartaddress + (i * 1024));
                emcBuffer = (uint8_t *)((0xA0000000 + (LCD_WIDTH * LCD_HEIGHT * sizeof(uint32_t))) + (i * 1024));
                memset((uint8_t*)buffer, 0xFF, 1024);
                memcpy((uint8_t*)buffer, (uint8_t*)emcBuffer, 1024);
   
                status = CopyRAM2Flash(ptr, buffer, IAP_WRITE_1024);

                if (status != CMD_SUCCESS)
                {
                    clear(0xFF,0,0);
                    ShowInt(((flashendaddress - flashstartaddress) / 1024) + 1, 0, 0, &fnt);
                    ShowInt(i, 13, 0, &fnt);
                    ShowInt(status, 26, 0, &fnt);

                    while(1){}
                }
            }
            print("Copy Complete", 39, 0, &fnt);

            for (i = 0; i < ((flashendaddress - flashstartaddress) / 1024) + 1; i++)
            {
                ptr = (uint8_t*)(flashstartaddress + (i * 1024));
                emcBuffer = (uint8_t *)((0xA0000000 + (LCD_WIDTH * LCD_HEIGHT * sizeof(uint32_t))) + (i * 1024));
                memcpy((uint8_t*)buffer, (uint8_t*)emcBuffer, 1024);

                status = Compare(ptr, buffer, IAP_WRITE_1024);

                if (status != CMD_SUCCESS)
                {
                    clear(0xFF,0,0xFF);
                    ShowInt(((flashendaddress - flashstartaddress) / 1024) + 1, 0, 0, &fnt);
                    ShowInt(i, 13, 0, &fnt);
                    ShowInt((uint32_t)status, 26, 0, &fnt);
                    while(1){}
                }
            }
            print("Compare Check Complete", 52, 0, &fnt);
            LPC_GPIO5->SET |= (1 << 04); // Remove Power on the USB pin pull up
            print("Turned off USB - Restarting", 65, 0, &fnt);
            _DelayMs(1000); // Delay for 1000ms
            NVIC->ICER[0] = 0xFFFFDFFF; // Again, make sure the interrupts are disabled
            NVIC->ICER[1] = 0xFF;
            execute_user_code();
            //NVIC_SystemReset();
        }
    }
    else
    {
        clear(0xFF,0,0);
        print("Send again", 0, 0, &fnt);
        USB_TX((uint8_t*)&bad, 1); // Send bad value for a repeat

        // TODO: Go back to recieve sent section from the Computer and remove the next while loop
        while(1){}
    }
}
break;
</code>

And there are three global variables used that are referred to in the code above
<code>
uint32_t flashstartaddress = 0xFFFFFFFF, flashendaddress = 0;
uint32_t currentAddress = 0;
uint8_t __attribute__ ((aligned (4))) * dest = (uint8_t*)(0xA0000000 + (LCD_WIDTH * LCD_HEIGHT * sizeof(uint32_t)));
</code>

Can anyone see something I’m missing here or there?  Or something I should be doing differently?
Thanks in advance,
Patrick
Labels (1)
0 Kudos
Reply
9 Replies

1,404 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by gopelsk on Mon Jun 22 04:39:26 MST 2015
Hi Lien,

I'm a newbee in this forum and now I learning the C++ language, but I know the Turbo Pascal and Borland delphi.

I need a little help.

Can you modify this usbdesc.c source code to USB to Serial converter?

I tried to modify but without success. Like the attachment.

bus1 and bus2 pics are that I need to modify this c source code.

If possible pls help me. I used the USB Bootloader source code.

Thank you in adavance. George
0 Kudos
Reply

1,404 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by studyembedded on Tue Feb 05 21:28:43 MST 2013
Hi friends ...did you manage to complete Bootloader for LPC1788, please update here. If you guy's manage to finish it please share with other people here....thanks!
0 Kudos
Reply

1,404 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by fsteff on Tue Jan 08 04:53:01 MST 2013

I found the error in my own code: The call to the flash erase function was missing the variable for CPU speed.
Adding this variable fixed my problem.

--
Fsteff
0 Kudos
Reply

1,404 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by fsteff on Fri Jan 04 03:21:24 MST 2013
Hi pcproa,

Did you find a specific solution to your problem (I tried to look at your sources, but didn't see it).


I'm experiencing the same problem, except that I'm running from the main Osc at 12Mhz. (But have also tested at 96MHz from the MainPLL)

I have positively verified that the problem occurs when using the CopyRAM2Flash() function.

The really suspicious problem I have, is that I have found an indirect way to always make it work, and to always make it fail, which really puzzles me:

There are three methods for me to place the initial bootloader and user-app in the LPC1788.
   1. Use the internal bootloader with flash magic or similar serial programmer.
   2. Use RedProbe+ (JTAG probe) and the "Program Flash" option inside RedSuite.
   3. Use RedProbe+ (JTAG probe) and perform a debug on the (release) source, then detaching the debugger.

In all of the above cases, I've used flash magic to extract the entire flash, and I can see they all have 100% identical contents.

Yet,
In case 1, it fails 50% of the times (If it fails first time, it always fails. If it works first time, it always works.).
In case 2, it never fails.
In case 3, it always fail.

All cases has been tested from both cold and warm boot, but there's no difference.

This makes me suspect some sort of persisted setting that I'm missing to deal with.

--
Fsteff
0 Kudos
Reply

1,404 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by pcproa on Wed Oct 10 20:20:11 MST 2012
Here is the current state of my USB Bootloader. It is for use in Keil
Sorry for the sloppy structure. Just open the Uvision project file in the main folder
0 Kudos
Reply

1,404 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by pcproa on Wed Oct 10 19:49:22 MST 2012
Unfortunately it's a no-go

Still does the same thing at both 96MHz and 84MHz, it just does it slower... Also, when it intermittently completes the write to flash, the jump to the small test program loaded at 0x8000 no longer works, probably because the clock setting doesn't change.
0 Kudos
Reply

1,404 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Lien.Nguyen on Wed Oct 10 19:24:44 MST 2012
Hi Patrick,
Please try running with the clock of 96MHz or below. I've heard about IAP issue related to maximum core frequency.

Best Regards,
Lien
0 Kudos
Reply

1,404 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by pcproa on Wed Oct 10 17:49:18 MST 2012
Hi Lien,
Thank you very much for the example code. I was planning on putting the case statement in a separate function, but I wanted to get it functioning correctly first.

I worked backwards and I believe I’ve isolated the issue but I’m not sure how to approach it next.
The USB downloads into the SDRAM correctly. I’ve created my own compare sequence to compare individual bytes from the original HEX file and the bytes downloaded to the SDRAM, as well as with the associated bytes written address on the Internal Flash.

The problem is with the data stored in flash from the CopyRAM2Flash function in the file lpc177x_8x_iap.c.

<code>
command.param[3] =  CLKPWR_GetCLK(CLKPWR_CLKTYPE_CPU) / 1000;         // CCLK in kHz
</code>

For some reason, between 3 and 7 percent of the bytes written to flash are incorrect, while occasionally all bytes are correct and it will load the full program to the correct address and begin to execute at 0x8000.

One time I changed the divider in the code above to a smaller number and it seemed to work better each time where it would work all the time at a divider of 50. I then tried to load a larger program at 0x8000. It failed and went back to the same pattern of not writing between 3 and 7 percent of the bytes to flash, even though they are stored correctly in SDRAM.

What I find strange is that I can write the same small program to load at 0x8000 twenty times in a row. Sometimes 2 bytes won’t get written correctly, sometimes 10 bytes won’t get written correctly, sometimes 3 bytes won’t get written correctly, and the list goes on. It makes me believe it has something to do with timing and not with the actual code. But there are not many ways to change the timing of the IAP other than to adjust the clock and/or change the divider on the code above.
Also, once in a while I find a pattern to the incorrect flash writes. Sometimes the byte written to an address is actually the byte that is supposed to be written 4 bytes over at a higher address.

So for example.
Address: 0x00008000 – expects byte 0x10
Address: 0x00008000 – Contains byte 0xCC (Same as in address 0x8005)
Address: 0x00008005 – Contains byte 0xCC

I have attached a copy of my ‘system_LPC177x_8x.c’ file to take a look. I have it configured to clock settings of 120MHz PLL0 and 48MHz PLL1.

Do you know of any better/reliable ways to adjust the timing of the IAP?

Thanks,

Patrick
0 Kudos
Reply

1,404 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Lien.Nguyen on Wed Oct 10 01:05:00 MST 2012
Hi Patrick,
I think that you should isolate functions to find out what is the problem. As code above, there are 2 separate phases,  1 for downloading firmware to SDRAM and another for copying data from SDRAM to flash. You should make sure each phase is ok before starting to integrate them.

I tried integrating everything as you said. It still works ok. I attached this example for you. Hope that it'll be helpfull. (You must login first to download it).

Best Regards,
Lien
0 Kudos
Reply