semihost server example program
Dependencies: SWD mbed USBLocalFileSystem BaseDAP USBDAP
LPCXpresso LPC11U68 | LPCXpresso LPC1549 | FRDM-KL46Z | EA LPC4088 QSB app-board | LPC1768 app-board | LPC810 | LPC1114FN28 | |
---|---|---|---|---|---|---|---|
server | server | server | server | server | client | client | |
SWDIO | D12 | D12 | D12 | p25 | p21 | p4(P0_2) | p12 |
SWCLK | D10 | D10 | D10 | p26 | p22 | p3(P0_3) | p3 |
nRESET *option | D6 | D6 | D6 | p34 | p30 | p1(P0_5) | p23 |
GND | GND | GND | GND | p1 | p1 | p7 | p22 |
3.3V | P3V3 | P3V3 | P3V3 | p44 | p40 | p6 | p21 |
flash write | SW2(P0_1) | SW3(P1_9) | SW1 | p14 joystick center | p14 joystick center |
client example:
Import programlpc810-semihost_helloworld
semihost client example program
Flash.cpp
- Committer:
- va009039
- Date:
- 2014-04-28
- Revision:
- 14:e6acf863207e
- Parent:
- 9:7e71c20c96e4
File content as of revision 14:e6acf863207e:
// Flash.cpp 2014/2/18 #include "Flash.h" #include "Target2.h" #include "mydebug.h" // LPC1347,LPC1114,LPC812,LPC810 #define LPC_SYSCON_SYSMEMREMAP 0x40048000 #define LPC_SYSCON_MAINCLKSEL 0x40048070 #define LPC_SYSCON_MAINCLKUEN 0x40048074 #define LPC_SYSCON_SYSAHBCLKDIV 0x40048078 // LPC1768,LPC1769 #define LPC_SC_MEMMAP 0x400fc040 #define LPC_SC_PLL0CON 0x400fc080 #define LPC_SC_PLL0CFG 0x400fc084 #define LPC_SC_PLL0STAT 0x400fc088 #define LPC_SC_PLL0FEED 0x400fc08c Flash::Flash(Target2* target, Serial* usbpc) :_target(target),_pc(usbpc) { _setup(); } void Flash::_setup() { _target->halt(); _target->wait_status(TARGET_HALTED); _target->prog_status(); } bool Flash::init() { _pc->printf("Initializing"); ram_addr = 0x10000000; ram_size = 0x400; if (remoteIAP(READ_PART_ID) != CMD_SUCCESS) { _pc->printf("\nfaild. READ_PART_ID\n"); return false; } bool result = false; _pc->printf("(%08x).", part_id); switch(part_id) { case 0x08020543: // LPC1347 result = flash_init_lpc1347(); break; case 0x26113f37: // LPC1768,LPC1769 result = flash_init_lpc1769(); break; default: if (part_id >= 0x00008100 && part_id <= 0x000081ff) { // LOC810 result = init_lpc1114fn28_lpc810(1024); } else { // part_id = 0x0a40902b or 0x1a40902b LPC1114FN28 result = init_lpc1114fn28_lpc810(4096); } break; } if (result) { _pc->printf("passed.\n"); } return result; } bool Flash::remoteREG(uint32_t addr, uint32_t value) { _target->writeMemory(addr, value); return true; } bool Flash::init_lpc1114fn28_lpc810(int sector_size) { cfg.iap_cclk = 12000; cfg.sector_size = sector_size; remoteREG(LPC_SYSCON_MAINCLKSEL, 0); // Select Internal RC Oscillator remoteREG(LPC_SYSCON_MAINCLKUEN, 1); // Update Main Clock Source remoteREG(LPC_SYSCON_MAINCLKUEN, 0); // Toggle Update Register remoteREG(LPC_SYSCON_MAINCLKUEN, 1); uint32_t data = _target->readMemory(LPC_SYSCON_MAINCLKUEN); // Wait until updated if (!(data & 1)) { _pc->printf("\nerror MAINCLKUEN=%08x\n", data); return false; } remoteREG(LPC_SYSCON_SYSAHBCLKDIV, 1);// Set Main Clock divider to 1 remoteREG(LPC_SYSCON_SYSMEMREMAP, 2); // User Flash Mode return true; } bool Flash::flash_init_lpc1347() { cfg.iap_cclk = 12000; cfg.sector_size = 4096; remoteREG(LPC_SYSCON_MAINCLKSEL, 0); // Select Internal RC Oscillator remoteREG(LPC_SYSCON_SYSAHBCLKDIV, 1);// Set Main Clock divider to 1 if (!remoteREG(LPC_SYSCON_SYSMEMREMAP, 2)) { // User Flash Mode return false; } return true; } bool Flash::flash_init_lpc1769() { cfg.iap_cclk = 4000; cfg.sector_size = 4096; remoteREG(LPC_SC_PLL0CON, 0x00); // Select Internal RC Oscillator remoteREG(LPC_SC_PLL0FEED, 0xaa); remoteREG(LPC_SC_PLL0FEED, 0x55); if (!remoteREG(LPC_SC_MEMMAP, 0x01)) { // User Flash Mode return false; } return true; } bool Flash::write(const char* filename) { const int chunk_size = 512; FILE* fp = fopen(filename, "rb"); if (fp == NULL) { _pc->printf("file open error [%s]\n", filename); return false; } _pc->printf("Writing."); uint8_t buf[chunk_size]; bool passed = false; for(int addr = 0; addr < 0x80000; addr += sizeof(buf)) { int ret = fread(buf, 1, sizeof(buf), fp); if (!_patch(buf, sizeof(buf), addr)) { break; } if (!write(addr, buf, sizeof(buf))) { break; } _pc->printf("."); if (ret < sizeof(buf)) { passed = true; break; } } fclose(fp); if (passed) { _pc->printf("passed.\n"); } return passed; } int Flash::addr_to_sector(int addr) { if (addr < 0x10000) { return addr / cfg.sector_size; } return addr / 0x8000 + 0x10000/cfg.sector_size - 2; } bool Flash::sector_head(int addr) { if (addr < 0x10000) { return (addr%cfg.sector_size) == 0; } return (addr%0x8000) == 0; } bool Flash::write(int addr, const uint8_t* data, int size) { int temp_addr = ram_addr + 44; int temp_size = 512; for(int i = 0; i < size; i += temp_size) { update(); if (!_write_to_ram(temp_addr, temp_size, data+i)) { _pc->printf("faild. write to ram %08x\n", temp_addr); return false; } int sector = addr_to_sector(addr + i); if (sector_head(addr + i)) { if (remoteIAP(PREPARE_SECTOR, sector, sector) != CMD_SUCCESS) { _pc->printf("faild. PREPARE_SECTOR %d %d\n", sector, sector); return false; } if (remoteIAP(ERASE_SECTOR, sector, sector, cfg.iap_cclk) != CMD_SUCCESS) { _pc->printf("faild. ERASE_SECTOR %d %d %d\n", sector, sector, cfg.iap_cclk); return false; } if (remoteIAP(BLANK_CHECK, sector, sector, cfg.iap_cclk) != CMD_SUCCESS) { _pc->printf("faild. BLANK_CHECK %d %d %d\n", sector, sector, cfg.iap_cclk); return false; } } if (remoteIAP(PREPARE_SECTOR, sector, sector) != CMD_SUCCESS) { _pc->printf("faild. PREPARE_SECTOR %d %d\n", sector, sector); return false; } if (remoteIAP(COPY_RAM_TO_FLASH, addr+i, temp_addr, temp_size, cfg.iap_cclk) != CMD_SUCCESS) { _pc->printf("faild. COPY_RAM_TO_FLASH %d %d %d %dn", addr+i, temp_addr, temp_size, cfg.iap_cclk); return false; } if (remoteIAP(COMPARE, addr+i, temp_addr, temp_size) != CMD_SUCCESS) { _pc->printf("faild. COMPARE %d %d %d", addr+i, temp_addr, temp_size); return false; } } return true; } bool Flash::_write_to_ram(int addr, int size, const uint8_t* buf) { _target->writeMemory(addr, (uint32_t*)buf, size / sizeof(uint32_t)); return true; } static uint32_t LD32(uint8_t* buf) { return (buf[0]) | (buf[1]<<8) | (buf[2]<<16) | (buf[3]<<24); } bool Flash::_patch(uint8_t* buf, int size, int addr) { const int crp_start = 0x2fc; // Code Read Protection location if (crp_start >= addr && crp_start < addr+size) { uint32_t pat = LD32(crp_start-addr+buf); if (pat != 0xffffffff) { // NO_CRP ? _pc->printf("\nCAUTION: CRP Pattern is not NO_CRP; %08x\n", pat); return false; } } return true; } Flash::IAP_STATUS Flash::remoteIAP(Flash::IAP_CMD cmd, uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3) { struct { uint32_t bkpt; // +0 struct { // IAP Structure uint32_t cmd; // +4 Command uint32_t par[4]; // +8 Parameters uint32_t stat; // +24 Status uint32_t res[4]; // +28 Result } IAP; // +44 } ram; ram.bkpt = 0xe00abe00; // bpkt #00 ram.IAP.cmd = cmd; ram.IAP.par[0] = p0; ram.IAP.par[1] = p1; ram.IAP.par[2] = p2; ram.IAP.par[3] = p3; _target->halt(); _target->wait_status(TARGET_HALTED); _target->writeMemory(ram_addr, (uint32_t*)&ram, sizeof(ram)/sizeof(uint32_t)); _target->r0 = ram_addr + 4; // command addr _target->r1 = ram_addr + 24; // status addr _target->sp = 0x10000400-32; // IAP use ram top 32bytes _target->lr = ram_addr + 1; // return to bkpt _target->pc = 0x1fff1ff1; // IAP_Call _target->resume(); _target->wait_status(TARGET_HALTED); if (cmd == READ_PART_ID) { part_id = _target->readMemory(ram_addr + 28); } return (IAP_STATUS)_target->readMemory(ram_addr + 24); } bool Flash::verify(const char* filename) { FILE* fp = fopen(filename, "rb"); if (fp == NULL) { _pc->printf("file open error [%s]\n", filename); return false; } _pc->printf("Verifying."); uint8_t buf[256]; bool passed = false; for(int addr = 0; addr < 0x80000; addr++) { int c = fgetc(fp); if (c == EOF) { passed = true; break; } if ((addr % sizeof(buf)) == 0) { _target->readMemory(addr, (uint32_t*)buf, sizeof(buf)/sizeof(uint32_t)); _pc->printf("."); } if (c != buf[addr % sizeof(buf)]) { _pc->printf("\nError at %08x(%02x:%02x)\n", addr, c, buf[addr % sizeof(buf)]); break; } } fclose(fp); if (passed) { _pc->printf("passed.\n"); } return passed; }