LPC1837 IAP usage to update flash

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

LPC1837 IAP usage to update flash

1,286 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by romanleonov on Thu Nov 26 03:27:10 MST 2015
Hi all!
Before explanation of my problem i want to tell my point of view of the working process with IAP flash update (by using command Copy_RAM_to_Flash, UM10430, p.74)

I want to write to sector 7, for example, of Flash bank A (i.e. start addres is 0x1A000000) 512 bytes from buffer, placed in ram. 512 - because of the Param2 command: number of bytes to written. It should be 512 | 1024 | 4096.
To do this, i perform next steps:

1) Create the entry to IAP (like in UM10430, p.72):

#define IAP_LOCATION *(volatile unsigned int *)(0x10400100);
typedef void (*IAP)(uint32_t[5], uint32_t[5]);
IAP iap_enrty = (IAP)IAP_LOCATION;

2) Next i perform three steps:

// First step - flash init

    uint32_t command[5], reply[5];
    iapCmd[0] = iap_Init;                        // iap_Init = 49
    iap(iapCmd, result);                        // call the IAP in the ROM

*here i had in result[0] something strange value which not equal CMD_SUCCESS (i.e. 0x00). This strange value looks like trash in memory.

// Second step - prepare flash to operation
    command[0] = iap_Prepare_sector_for_write_operation;
    command[1] = 7;                               //  Start sector 7 - want to write in sector 7 of bank A - 0x1A007000
    command[2] = 7;         //  End Sector the same
    command[3] = 0;                  //  Bank A
    iap(command, result);      // call the IAP in the ROM
  
** here i had the correct reply CMD_SUCCESS and it really seems like IAP does perform FLASH preparation.

//  Third step - write data to flash

    uint8_t data_to_write[512]; // Create the buffer in ram, addrees may differs, but always in address space of ram, for example: 0x10001F70
    memset(data_to_write, 0xAA, 512); // fill the buffer with 0xAA bytes

    command[0] = iap_Copy_RAM_to_Flash;
    command[1] = 0x1A007000;         //  Destination flash address where data bytes are to be written. This address should be a 512 byte boundary.
    command[2] = 0x10001F70;          //  Source RAM address from which data bytes are to be read. This address should be a word boundary.
    command[3] = 512;               //  Number of bytes to be written. Should be 512 | 1024 | 4096.
    command[4] = 180000;             //  CPU Clock Frequency (CCLK) in kHz, in my case i work on 180 MHz
    iap(command, result);     // call the IAP in the ROM

***here i got the result[0] value 0x09, which means SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION.

Here are my questions:
Is my point of view correct?
1) Should i perform this three command one by one: flash init, prepare for operation, write flash?
2) I use the sector number like in LPC11Uxx uCs, i.e. 0x00000000 is 0 sector, 0x00001000 is 1 sector, and so on. Thus 0x00007000 is 7 sector. Am I right?
3) I use distination flash address like 0x1A007000, but if i use address like 0x00007000 i got returned value 0x05 - DST_ADDR_NOT_MAPPED. What the right one?

I reservated 2 kB on the start of SRAM to stack of IAP (because i had seen in the forum information about that IAP command select flash bank uses ~2000 bytes, so i think "maybe command copy is does the same"). And my (program's) ram address started from 0x10000800. So, i suppose that program and ram stacks do not clashed.
I tryed to make my CPU frequency not so high and on CPU 48 MHz result the same.

So.
Could someone help me please?

Thank for attention and apologize for my long description and possible mistakes in grammatics.
Thank again.
Roman.
Labels (1)
0 Kudos
Reply
2 Replies

947 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by romanleonov on Thu Nov 26 07:43:38 MST 2015
Here are my new updates:

1) Yes, we can work on low CPU frequences like 48 MHz and high 180 MHz pretty well. But on high frequencies processor is so fast, that my other library for printing information by UART conflicted with (as far as i can hope and understand) incomplete flash memory operation. Thats why i need some empty cycles to wait the flash memory on high frequencies (in my case > 96 MHz). They are macro: WAIT_FLASH().
2) To accurately do writing in flash we should erase target page before doing it.

Here is my code, which seems to be working now. Hope so.

If there are some remarks or inaccuracies in the code, please tell me. Thanks.

static inline void flash_init()
{
    uint32_t cmd[5];
    cmd[0] = iap_Init;
    iap(cmd, cmd);
}

static inline IAP_STATUS write_flash(uint32_t flash_addr, uint32_t ram_addr, uint32_t size)
{
    uint32_t cmd[5];
    cmd[0] = iap_Copy_RAM_to_Flash;
    cmd[1] = flash_addr;         //  Destination flash address where data bytes are to be written. This address should be a 256 byte boundary.
    cmd[2] = ram_addr;           //  Source RAM address from which data bytes are to be read. This address should be a word boundary.
    cmd[3] = size;               //  Number of bytes to be written. Should be 512 | 1024 | 4096.
    cmd[4] = CPU_FREQ_KHz;       //  CPU Clock Frequency (CCLK) in kHz
    iap(cmd, cmd);      // call the IAP in the ROM
    WAIT_FLASH();
    return (IAP_STATUS)cmd[0];
}

static inline IAP_STATUS prepare_flash(uint8_t sector_start, uint32_t sector_end)
{
    uint32_t cmd[5], result[5];             // (20-bytes on the stack)
    cmd[0] = iap_Prepare_sector_for_write_operation;
    cmd[1] = (uint32_t)sector_start;       //  Start sector
    cmd[2] = (uint32_t)sector_end;         //  End Sector
    cmd[3] = 0;                            //  Bank A
    iap(cmd, result);      // call the IAP in the ROM
    WAIT_FLASH();
    return (IAP_STATUS)result[0];
}

static inline IAP_STATUS erase_page(uint32_t page_start, uint32_t page_end)
{
    uint32_t cmd[5], result[5];
    cmd[0] = iap_Erase_page;
    cmd[1] = page_start;
    cmd[2] = page_end;
    cmd[3] = CPU_FREQ_KHz;
    iap(cmd, result);      // call the IAP in the ROM
    WAIT_FLASH();
    return (IAP_STATUS)result[0];
}

int iap_erase_page(uint8_t flash_sector, uint32_t flash_addr, uint32_t page_size) {
    // check flash bounaries and page: it must be 512
    if(flash_addr % LPC_FLASH_PAGE_SIZE != 0 || page_size % LPC_FLASH_PAGE_SIZE != 0)
        return 1;

    flash_init();

    if(CMD_SUCCESS != prepare_flash(flash_sector, flash_sector))
        return 2;

    if(CMD_SUCCESS != erase_page(flash_addr, flash_addr + page_size))
        return 3;

    return 0;
}

int iap_write_page(uint8_t flash_sector, uint32_t flash_addr, uint32_t ram_addr, uint32_t page_size)
{
    // check page size it must be 512 boundaries
    if(page_size % LPC_FLASH_PAGE_SIZE != 0)
        return 1;

    flash_init();

    if(CMD_SUCCESS != prepare_flash(flash_sector, flash_sector))
        return 2;

    if(CMD_SUCCESS != write_flash(flash_addr, ram_addr, page_size))
        return 3;

    return 0;
}

int iap_rewrite_page(uint8_t flash_sector, uint32_t flash_addr, uint32_t *ram_page, uint32_t page_size)
{
    if(iap_erase_page(flash_sector, flash_addr, page_size))
        return 1;

    return iap_write_page(flash_sector, flash_addr, (uint32_t)ram_page, page_size);
}
0 Kudos
Reply

947 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by romanleonov on Thu Nov 26 04:23:49 MST 2015
So, after half an hour i founded Table 25 Flash configuration (UM10430, p.58).
There are sector size description and start-end addresses boundaries present.
And I asked to questions by myself. Here my opinion:

1) We must perform 3 steps. Without first one uC is freeze on the command Copy_RAM_to_Flash in step 3.
2) So, if we want to write in 0x1A007000 we should write to sector 3, and my start- and end-sector value should be 3. By the way, sector size here 8 kB for first 8 sectors, and 64 kB for last 7 sectors. Together - 512 kBytes of bank A.
3) Destination address in the command should be as this: 0x1A007000.

And also, share my mind.
1) If we would like to write to 0x1A007000, thus we write to the second half of the sector 3. So we need use sector value 3. But in this case my uC (uC - microprocessor) freezed. What the reason - don't know yet.
2) In my previous example, i created a buffer in ram of uint8_t with size - 512. This means, that in case of 32-bits memory there are 16 double words.

Follow up situation explaining...
0 Kudos
Reply