EmbeddedRelated.com
Forums

USB Bootloader problems - Bootloader from Flash

Started by a6o4o July 27, 2007
Hi

A buddy of mine is using an LPC2148. He is using USB and is trying
since days to implement an USB bootloader but with no success.
His bootloader is on the Flash, NOT the RAM. He is using the IAP
function to start the bootloader. This seems to work so far. He can
delete sectors BUT as soon as he wants to write to the Flash the Flash
is unlocked and he can't write to it.
Is the reason maybe that with IAP you can't write to Flash because
it's running from the Flash?
He is doing it like that because he implemented a test after the reset
to check if the ARM was in the bootloader before or in the
application. (he got a byte on the top in the Flash that he can
set/reset to do that) So if the power gets lost or something goes
wrong the ARM will always restart again in the bootloader and the
software can be loaded again.

Any ideas why this is not working?

thank you

An Engineer's Guide to the LPC2100 Series

a6o4o wrote:
> Hi
>
> A buddy of mine is using an LPC2148. He is using USB and is trying
> since days to implement an USB bootloader but with no success.
> His bootloader is on the Flash, NOT the RAM. He is using the IAP
> function to start the bootloader. This seems to work so far. He can
> delete sectors BUT as soon as he wants to write to the Flash the Flash
> is unlocked and he can't write to it.
> Is the reason maybe that with IAP you can't write to Flash because
> it's running from the Flash?
> He is doing it like that because he implemented a test after the reset
> to check if the ARM was in the bootloader before or in the
> application. (he got a byte on the top in the Flash that he can
> set/reset to do that) So if the power gets lost or something goes
> wrong the ARM will always restart again in the bootloader and the
> software can be loaded again.
>
> Any ideas why this is not working?
>

It may help to start by reviewing a working example:
http://www.tnkernel.com/usb_fw_upgrader.html
I've done this sucessfully running from Flash on a LPC2368. At
least I was making the call into the IAP from code in the user flash.

I do recall that I had to make the unlock call before I erased a
sector and again before I programmed it.

I'm not sure if the LPC2148 is any different.

Andy
--- In l..., "a6o4o" wrote:
>
> Hi
>
> A buddy of mine is using an LPC2148. He is using USB and is trying
> since days to implement an USB bootloader but with no success.
> His bootloader is on the Flash, NOT the RAM. He is using the IAP
> function to start the bootloader. This seems to work so far. He
can
> delete sectors BUT as soon as he wants to write to the Flash the
Flash
> is unlocked and he can't write to it.
> Is the reason maybe that with IAP you can't write to Flash because
> it's running from the Flash?
> He is doing it like that because he implemented a test after the
reset
> to check if the ARM was in the bootloader before or in the
> application. (he got a byte on the top in the Flash that he can
> set/reset to do that) So if the power gets lost or something goes
> wrong the ARM will always restart again in the bootloader and the
> software can be loaded again.
>
> Any ideas why this is not working?
>
> thank you
>
Hi

I'm using this on my LPC2148 and it works fine so far:

I'm flashing in chunks of 512bytes. Don't forget to turn off IRQs!

clock = 60Mhz

static char flashdata[512];
static unsigned long flashdatapointer=0;
static unsigned long flashsectorpointer=0;
static unsigned long flashaddrpointer=0;
//+++++++++++++++++++++++++IAP++++++++++++++++++++++++++++++++++++
#define PREPARE_SECTOR_FOR_WRITE_OPERATION 50 // IAP command
#define COPY_RAM_TO_FLASH 51
#define ERASE_SECTOR 52
#define BLANK_CHECK_SECTOR 53
#define READ_PART_ID 54
#define READ_BOOT_CODE_VERSION 55
#define COMPARE 56 // codes

static unsigned long iap_cmd[5]; // IAP command table
static unsigned long iap_res[3]; // result table

static long iap(long code, long p1, long p2, long p3, long p4)
{
iap_cmd[0] = code; // set command code
iap_cmd[1] = p1; // 1st param
iap_cmd[2] = p2; // 2nd param
iap_cmd[3] = p3; // 3rd param
iap_cmd[4] = p4; // 4th param

((void (*)())0x7ffffff1)(iap_cmd, iap_res); // IAP entry point
return *iap_res; // return status
}

static void part_id(void)
{
if (iap(READ_PART_ID, 0, 0, 0, 0)) {
DBG("Error reading part ID\n");
return;
}
DBG("Part ID: %u\n", iap_res[1]);
}

static void bootcodeversion(void)
{
if (iap(READ_BOOT_CODE_VERSION, 0, 0, 0, 0)) {
DBG("Reading boot code version\n");
return;
}
DBG("Boot code version: %d.%d\n",(unsigned char)(iap_res[1]>>8),
(unsigned char)iap_res[1]);
}

unsigned long adress_to_sector(unsigned long address)
{
if (address<0x8000)
return (address>>12);
if (address<0x78000)
return ((address>>15)+7);
if (address<0x7D000)
return ((address>>12)-98);
return 26;
}

static void s_write(unsigned long address)
{
unsigned long SECT = 0;
SECTress_to_sector(address);
if (iap(PREPARE_SECTOR_FOR_WRITE_OPERATION, SECT, SECT, 0, 0)
|| iap(COPY_RAM_TO_FLASH, address, (long)flashdata, 512, 60000)
|| iap(COMPARE, address, (long)flashdata, 512, 0)) {
DBG("Error Writing sector");
return;
}
DBG("Data successfully written.");
}

static void s_erase(unsigned long address)
{
unsigned long SECT = 0;
SECTress_to_sector(address);
if (!iap(BLANK_CHECK_SECTOR, SECT, SECT, 0, 0)) {
DBG("Sector already blank!\n");
return;
}

if (iap(PREPARE_SECTOR_FOR_WRITE_OPERATION, SECT, SECT, 0, 0)
|| iap(ERASE_SECTOR, SECT, SECT, 60000, 0)
|| iap(BLANK_CHECK_SECTOR, SECT, SECT, 0, 0)) {
DBG("Error Erasing sector\n");
return;
}
DBG("Sector successfully erased.\n");
}
void InApplicationProgramming(void)
{
disableIRQ();
if (flashsectorpointer {
s_erase(flashaddrpointer);
flashsectorpointerress_to_sector(flashaddrpointer);
}
s_write(flashaddrpointer);
enableIRQ();
}