本帖最后由 Simon21ic 于 2010-5-24 18:59 编辑
晚上思路清晰。。。。。。效率高啊。。。。。
最高速度:
Info: erasing flash
erasing flash |========================================%100| 0.04s used
Info: flash erased
Info: programming flash
writing flash |========================================%100| 1.34s used
Info: flash programmed for 98304bytes(71.64KB/s)
Info: verifying flash
reading flash |========================================%100| 1.08s used
Info: flash verified for 98304bytes(88.89KB/s)
优化原理:
一般的下载算法:
LPCARM的Flash下载很简单,只是通过USB接口下载一个FlashLoader和Flash数据到RAM,包括IAP命令和参数,然后,设置相应的寄存器(R0,R1,SP,LR,PC,下载寄存器需要先Halt)并设置中断后运行内核,这个是OpenOCD里用的标准算法,我这里测试可以达到5Kb/s左右的速度(560KHz JTAG)。
优化下载算法:
1. JTAG接口优化,一般使用内部4M RC的时候,最高的JTAG速度是650KHz(CCLK / 6,CortexM3标准)。
优化JTAG的实现方式后,一般可以超过这个限制,我这里测试在4500KHz和9000KHz下都可以正常操作。
优化原理:这个速度限制是由于总线访问的时候的限制,如果JTAG写完数据,在CortexM3总线访问时,加入一些等待时钟,就可以提高速度了。JTAG本省硬件上类似移位寄存器,是可以得到非常高的速度的。
使得可以得到超过70KB/s的Flash下载速度。
2. 乒乓操作(tick-tock)
CortexM3在操作Flash(写,擦除)是,JTAG接口仍旧可以访问SRAM,这样就可以简单实现乒乓操作。
芯片一边写Flash,一边通过JTAG下载下一次的数据。
从前面的数据来看,加入乒乓操作后,速度基本上一下子提升80%。
3. Flash Loader优化
由于一般的算法中,每次都要Halt内核,下载LPC的IAP命令,设置相应的寄存器和中断系统,然后在启动运行。这个过程会占用一些时间。
优化后,每次操作,都不需要Halt内核,不需要设置寄存器,不需要设置中断系统,直接写完LPC的IAP命令就可以了。
FlashLoader只需要在初始化的时候,下载一次即可。
核心FlashLoader:
static uint8_t iap_code[] = {
// wait_start:
0x15, 0x48, // ldr r0, [PC, #XX] // load sync
0x00, 0x28, // cmp r0, #0
0xFC, 0xD0, // beq wait_start
0x00, 0x00,
// init:
0x05, 0x4A, // ldr r2, [PC, #XX] // laod address of iap_entry
0x06, 0x48, // ldr r0, [PC, #XX] // load address of command
0x06, 0x49, // ldr r1, [PC, #XX] // load address of result
0x90, 0x47, // blx r2 // call iap_entry
0x00, 0x00,
0x06, 0x48, // ldr r0, [PC, #XX] // load address of sync
0x4F, 0xF0, 0x00, 0x01, // mov r1, #0
0x01, 0x60, // str r1, [r0, #0] // clear sync
0xF1, 0xE7, // b wait_start
0xFE, 0xE7, // b $
0, 0, // fill
// parameter
0, 0, 0, 0, // address of iap_entry
0, 0, 0, 0, // address of command
0, 0, 0, 0, // address of result
(LPC1000_IAP_SYNC_ADDR >> 0) & 0xFF, // address of aync
(LPC1000_IAP_SYNC_ADDR >> 8) & 0xFF,
(LPC1000_IAP_SYNC_ADDR >> 16) & 0xFF,
(LPC1000_IAP_SYNC_ADDR >> 24) & 0xFF,
0, 0, 0, 0, // reserved0
0, 0, 0, 0, // reserved1
0, 0, 0, 0, // reserved2
0, 0, 0, 0, // reserved3
0, 0, 0, 0, // command
0, 0, 0, 0, // param[0]
0, 0, 0, 0, // param[1]
0, 0, 0, 0, // param[2]
0, 0, 0, 0, // param[3]
0, 0, 0, 0, // param[4]
0, 0, 0, 0, // sync
// when write iap command, write command(6 DWORD) + sync(set to 1, 1 DWORD)
// when read result, read sync(1DWORD) + result(5 DWORD), sync = 0 means ready
0, 0, 0, 0, // result
0, 0, 0, 0, // reply[0]
0, 0, 0, 0, // reply[1]
0, 0, 0, 0, // reply[2]
0, 0, 0, 0 // reply[3]
}; |