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@5:2774358f5e4f, 2013-09-14 (annotated)
- Committer:
- va009039
- Date:
- Sat Sep 14 12:55:29 2013 +0000
- Revision:
- 5:2774358f5e4f
- Parent:
- 4:5e4107edcbdb
- Child:
- 6:5da6ad51a18f
deleted the code to access the data of unalignment.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
va009039 | 4:5e4107edcbdb | 1 | // Flash.cpp 2013/9/11 |
va009039 | 0:27d35fa263b5 | 2 | #include "Flash.h" |
va009039 | 0:27d35fa263b5 | 3 | #include "Target2.h" |
va009039 | 0:27d35fa263b5 | 4 | #include "mydebug.h" |
va009039 | 0:27d35fa263b5 | 5 | |
va009039 | 3:d7a7cde0bfb8 | 6 | #define SYSMEMREMAP 0x40048000 |
va009039 | 3:d7a7cde0bfb8 | 7 | #define MAINCLKSEL 0x40048070 |
va009039 | 3:d7a7cde0bfb8 | 8 | #define MAINCLKUEN 0x40048074 |
va009039 | 3:d7a7cde0bfb8 | 9 | #define SYSAHBCLKDIV 0x40048078 |
va009039 | 3:d7a7cde0bfb8 | 10 | |
va009039 | 0:27d35fa263b5 | 11 | Flash::Flash(Target2* target, Serial* usbpc) :_target(target),_pc(usbpc) |
va009039 | 0:27d35fa263b5 | 12 | { |
va009039 | 0:27d35fa263b5 | 13 | _setup(); |
va009039 | 0:27d35fa263b5 | 14 | } |
va009039 | 0:27d35fa263b5 | 15 | |
va009039 | 0:27d35fa263b5 | 16 | void Flash::_setup() |
va009039 | 0:27d35fa263b5 | 17 | { |
va009039 | 0:27d35fa263b5 | 18 | _target->halt(); |
va009039 | 0:27d35fa263b5 | 19 | _target->wait_status(TARGET_HALTED); |
va009039 | 4:5e4107edcbdb | 20 | _target->prog_status(); |
va009039 | 0:27d35fa263b5 | 21 | } |
va009039 | 0:27d35fa263b5 | 22 | |
va009039 | 3:d7a7cde0bfb8 | 23 | bool Flash::init() |
va009039 | 3:d7a7cde0bfb8 | 24 | { |
va009039 | 3:d7a7cde0bfb8 | 25 | _pc->printf("Initializing."); |
va009039 | 3:d7a7cde0bfb8 | 26 | if (_target->idcode == 0x0bb11477) { // LPC1114FN28 |
va009039 | 3:d7a7cde0bfb8 | 27 | _target->writeMemory(MAINCLKSEL, 0); // Select Internal RC Oscillator |
va009039 | 3:d7a7cde0bfb8 | 28 | _target->writeMemory(MAINCLKUEN, 1); // Update Main Clock Source |
va009039 | 3:d7a7cde0bfb8 | 29 | _target->writeMemory(MAINCLKUEN, 0); // Toggle Update Register |
va009039 | 3:d7a7cde0bfb8 | 30 | _target->writeMemory(MAINCLKUEN, 1); |
va009039 | 3:d7a7cde0bfb8 | 31 | uint32_t data = _target->readMemory(MAINCLKUEN); // Wait until updated |
va009039 | 3:d7a7cde0bfb8 | 32 | if (!(data & 1)) { |
va009039 | 3:d7a7cde0bfb8 | 33 | _pc->printf("\nerror MAINCLKUEN=%08x\n", data); |
va009039 | 3:d7a7cde0bfb8 | 34 | return false; |
va009039 | 3:d7a7cde0bfb8 | 35 | } |
va009039 | 3:d7a7cde0bfb8 | 36 | _target->writeMemory(SYSAHBCLKDIV, 1);// Set Main Clock divider to 1 |
va009039 | 3:d7a7cde0bfb8 | 37 | _target->writeMemory(SYSMEMREMAP, 2); // User Flash Mode |
va009039 | 3:d7a7cde0bfb8 | 38 | } else { |
va009039 | 3:d7a7cde0bfb8 | 39 | _pc->printf("\nerror idcode=%08x\n", _target->idcode); |
va009039 | 3:d7a7cde0bfb8 | 40 | return false; |
va009039 | 3:d7a7cde0bfb8 | 41 | } |
va009039 | 3:d7a7cde0bfb8 | 42 | _pc->printf("passed.\n"); |
va009039 | 3:d7a7cde0bfb8 | 43 | return true; |
va009039 | 3:d7a7cde0bfb8 | 44 | } |
va009039 | 3:d7a7cde0bfb8 | 45 | |
va009039 | 0:27d35fa263b5 | 46 | bool Flash::write(const char* filename) |
va009039 | 0:27d35fa263b5 | 47 | { |
va009039 | 0:27d35fa263b5 | 48 | FILE* fp = fopen(filename, "rb"); |
va009039 | 0:27d35fa263b5 | 49 | if (fp == NULL) { |
va009039 | 0:27d35fa263b5 | 50 | _pc->printf("file open error [%s]\n", filename); |
va009039 | 0:27d35fa263b5 | 51 | return false; |
va009039 | 0:27d35fa263b5 | 52 | } |
va009039 | 0:27d35fa263b5 | 53 | _pc->printf("Writing."); |
va009039 | 0:27d35fa263b5 | 54 | uint8_t buf[256]; |
va009039 | 0:27d35fa263b5 | 55 | bool passed = false; |
va009039 | 0:27d35fa263b5 | 56 | for(int addr = 0; addr < 0x8000; addr += sizeof(buf)) { |
va009039 | 3:d7a7cde0bfb8 | 57 | int ret = fread(buf, 1, sizeof(buf), fp); |
va009039 | 0:27d35fa263b5 | 58 | if (!_patch(buf, sizeof(buf), addr)) { |
va009039 | 0:27d35fa263b5 | 59 | break; |
va009039 | 0:27d35fa263b5 | 60 | } |
va009039 | 0:27d35fa263b5 | 61 | const int ram = 0x10000200; |
va009039 | 0:27d35fa263b5 | 62 | if (!_write_to_ram(ram, sizeof(buf), buf)) { |
va009039 | 0:27d35fa263b5 | 63 | break; |
va009039 | 0:27d35fa263b5 | 64 | } |
va009039 | 2:32e9437348ad | 65 | if (remoteIAP(PREPARE_SECTOR, _sector(addr), _sector(addr)) != CMD_SUCCESS) { |
va009039 | 2:32e9437348ad | 66 | _pc->printf("faild. PREPARE_SECTOR %d %d\n", _sector(addr), _sector(addr)); |
va009039 | 0:27d35fa263b5 | 67 | break; |
va009039 | 0:27d35fa263b5 | 68 | } |
va009039 | 2:32e9437348ad | 69 | if (remoteIAP(COPY_RAM_TO_FLASH, addr, ram, sizeof(buf), IAP_CCLK) != CMD_SUCCESS) { |
va009039 | 2:32e9437348ad | 70 | _pc->printf("faild. COPY_RAM_TO_FLASH %d %d %d %dn", addr, ram, sizeof(buf)); |
va009039 | 0:27d35fa263b5 | 71 | break; |
va009039 | 0:27d35fa263b5 | 72 | } |
va009039 | 4:5e4107edcbdb | 73 | if (remoteIAP(COMPARE, addr, ram, sizeof(buf)) != CMD_SUCCESS) { |
va009039 | 4:5e4107edcbdb | 74 | _pc->printf("faild. COMPARE %d %d %d", addr, ram, sizeof(buf)); |
va009039 | 4:5e4107edcbdb | 75 | break; |
va009039 | 0:27d35fa263b5 | 76 | } |
va009039 | 0:27d35fa263b5 | 77 | _pc->printf("."); |
va009039 | 3:d7a7cde0bfb8 | 78 | if (ret < sizeof(buf)) { |
va009039 | 3:d7a7cde0bfb8 | 79 | passed = true; |
va009039 | 3:d7a7cde0bfb8 | 80 | break; |
va009039 | 3:d7a7cde0bfb8 | 81 | } |
va009039 | 0:27d35fa263b5 | 82 | } |
va009039 | 0:27d35fa263b5 | 83 | fclose(fp); |
va009039 | 0:27d35fa263b5 | 84 | if (passed) { |
va009039 | 0:27d35fa263b5 | 85 | _pc->printf("passed.\n"); |
va009039 | 0:27d35fa263b5 | 86 | } |
va009039 | 0:27d35fa263b5 | 87 | return passed; |
va009039 | 0:27d35fa263b5 | 88 | } |
va009039 | 0:27d35fa263b5 | 89 | |
va009039 | 0:27d35fa263b5 | 90 | bool Flash::eraseAll() |
va009039 | 0:27d35fa263b5 | 91 | { |
va009039 | 0:27d35fa263b5 | 92 | _pc->printf("Erasing."); |
va009039 | 0:27d35fa263b5 | 93 | for(int sector = 0; sector <= 7; sector++) { |
va009039 | 2:32e9437348ad | 94 | IAP_STATUS status = remoteIAP(PREPARE_SECTOR, sector, sector); |
va009039 | 2:32e9437348ad | 95 | if (status != CMD_SUCCESS) { |
va009039 | 2:32e9437348ad | 96 | _pc->printf("faild. PREPARE_SECTOR %d %d status=%d\n", sector, sector, status); |
va009039 | 0:27d35fa263b5 | 97 | return false; |
va009039 | 0:27d35fa263b5 | 98 | } |
va009039 | 2:32e9437348ad | 99 | if (remoteIAP(ERASE_SECTOR, sector, sector, IAP_CCLK) != CMD_SUCCESS) { |
va009039 | 2:32e9437348ad | 100 | _pc->printf("faild. ERASE_SECTOR %d %d %d\n", sector, sector, IAP_CCLK); |
va009039 | 0:27d35fa263b5 | 101 | return false; |
va009039 | 0:27d35fa263b5 | 102 | } |
va009039 | 2:32e9437348ad | 103 | if (remoteIAP(BLANK_CHECK, sector, sector, IAP_CCLK) != CMD_SUCCESS) { |
va009039 | 2:32e9437348ad | 104 | _pc->printf("faild. BLANK_CHECK %d %d %d\n", sector, sector, IAP_CCLK); |
va009039 | 0:27d35fa263b5 | 105 | return false; |
va009039 | 0:27d35fa263b5 | 106 | } |
va009039 | 0:27d35fa263b5 | 107 | _pc->printf("."); |
va009039 | 0:27d35fa263b5 | 108 | } |
va009039 | 0:27d35fa263b5 | 109 | _pc->printf("passed.\n"); |
va009039 | 0:27d35fa263b5 | 110 | return true; |
va009039 | 0:27d35fa263b5 | 111 | } |
va009039 | 0:27d35fa263b5 | 112 | |
va009039 | 0:27d35fa263b5 | 113 | bool Flash::_write_to_ram(int addr, int size, uint8_t* buf) |
va009039 | 0:27d35fa263b5 | 114 | { |
va009039 | 0:27d35fa263b5 | 115 | _target->writeMemory(addr, (uint32_t*)buf, size / sizeof(uint32_t)); |
va009039 | 0:27d35fa263b5 | 116 | return true; |
va009039 | 0:27d35fa263b5 | 117 | } |
va009039 | 0:27d35fa263b5 | 118 | |
va009039 | 0:27d35fa263b5 | 119 | int Flash::_sector(int addr) |
va009039 | 0:27d35fa263b5 | 120 | { |
va009039 | 0:27d35fa263b5 | 121 | return addr / 4096; |
va009039 | 0:27d35fa263b5 | 122 | } |
va009039 | 0:27d35fa263b5 | 123 | |
va009039 | 5:2774358f5e4f | 124 | static uint32_t LD32(uint8_t* buf) |
va009039 | 5:2774358f5e4f | 125 | { |
va009039 | 5:2774358f5e4f | 126 | return buf[0] | buf[1]<<8 | buf[2]<<16 | buf[3]<<24; |
va009039 | 5:2774358f5e4f | 127 | } |
va009039 | 5:2774358f5e4f | 128 | |
va009039 | 0:27d35fa263b5 | 129 | bool Flash::_patch(uint8_t* buf, int size, int addr) |
va009039 | 0:27d35fa263b5 | 130 | { |
va009039 | 0:27d35fa263b5 | 131 | const int crp_start = 0x2fc; // Code Read Protection location |
va009039 | 0:27d35fa263b5 | 132 | if (crp_start >= addr && crp_start < addr+size) { |
va009039 | 5:2774358f5e4f | 133 | uint32_t pat = LD32(crp_start-addr+buf); |
va009039 | 0:27d35fa263b5 | 134 | if (pat != 0xffffffff) { // NO_CRP ? |
va009039 | 0:27d35fa263b5 | 135 | _pc->printf("\nCAUTION: CRP Pattern is not NO_CRP; %08x\n", pat); |
va009039 | 0:27d35fa263b5 | 136 | return false; |
va009039 | 0:27d35fa263b5 | 137 | } |
va009039 | 0:27d35fa263b5 | 138 | } |
va009039 | 0:27d35fa263b5 | 139 | return true; |
va009039 | 0:27d35fa263b5 | 140 | } |
va009039 | 0:27d35fa263b5 | 141 | |
va009039 | 2:32e9437348ad | 142 | Flash::IAP_STATUS Flash::remoteIAP(Flash::IAP_CMD cmd, uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3) |
va009039 | 0:27d35fa263b5 | 143 | { |
va009039 | 0:27d35fa263b5 | 144 | struct { |
va009039 | 0:27d35fa263b5 | 145 | uint32_t bkpt; // +0 |
va009039 | 0:27d35fa263b5 | 146 | struct { // IAP Structure |
va009039 | 0:27d35fa263b5 | 147 | uint32_t cmd; // +4 Command |
va009039 | 0:27d35fa263b5 | 148 | uint32_t par[4]; // +8 Parameters |
va009039 | 0:27d35fa263b5 | 149 | uint32_t stat; // +24 Status |
va009039 | 0:27d35fa263b5 | 150 | uint32_t res[4]; // +28 Result |
va009039 | 0:27d35fa263b5 | 151 | } IAP; // +44 |
va009039 | 0:27d35fa263b5 | 152 | } ram; |
va009039 | 0:27d35fa263b5 | 153 | |
va009039 | 2:32e9437348ad | 154 | ram.bkpt = 0xe00abe00; // bpkt #00 |
va009039 | 0:27d35fa263b5 | 155 | ram.IAP.cmd = cmd; |
va009039 | 0:27d35fa263b5 | 156 | ram.IAP.par[0] = p0; |
va009039 | 0:27d35fa263b5 | 157 | ram.IAP.par[1] = p1; |
va009039 | 0:27d35fa263b5 | 158 | ram.IAP.par[2] = p2; |
va009039 | 0:27d35fa263b5 | 159 | ram.IAP.par[3] = p3; |
va009039 | 0:27d35fa263b5 | 160 | _target->halt(); |
va009039 | 0:27d35fa263b5 | 161 | _target->wait_status(TARGET_HALTED); |
va009039 | 0:27d35fa263b5 | 162 | const uint32_t ram_addr = 0x10000100; |
va009039 | 0:27d35fa263b5 | 163 | _target->writeMemory(ram_addr, (uint32_t*)&ram, sizeof(ram)/sizeof(uint32_t)); |
va009039 | 2:32e9437348ad | 164 | _target->r0 = ram_addr + 4; // command addr |
va009039 | 2:32e9437348ad | 165 | _target->r1 = ram_addr + 24; // status addr |
va009039 | 2:32e9437348ad | 166 | _target->sp = 0x10000400-32; // IAP use ram top 32bytes |
va009039 | 0:27d35fa263b5 | 167 | _target->lr = ram_addr + 1; // return to bkpt |
va009039 | 0:27d35fa263b5 | 168 | _target->pc = 0x1fff1ff1; // IAP_Call |
va009039 | 0:27d35fa263b5 | 169 | _target->resume(); |
va009039 | 0:27d35fa263b5 | 170 | _target->wait_status(TARGET_HALTED); |
va009039 | 2:32e9437348ad | 171 | return (IAP_STATUS)_target->readMemory(ram_addr + 24); |
va009039 | 0:27d35fa263b5 | 172 | } |
va009039 | 0:27d35fa263b5 | 173 | |
va009039 | 0:27d35fa263b5 | 174 | bool Flash::verify(const char* filename) |
va009039 | 0:27d35fa263b5 | 175 | { |
va009039 | 0:27d35fa263b5 | 176 | FILE* fp = fopen(filename, "rb"); |
va009039 | 0:27d35fa263b5 | 177 | if (fp == NULL) { |
va009039 | 0:27d35fa263b5 | 178 | _pc->printf("file open error [%s]\n", filename); |
va009039 | 0:27d35fa263b5 | 179 | return false; |
va009039 | 0:27d35fa263b5 | 180 | } |
va009039 | 0:27d35fa263b5 | 181 | _pc->printf("Verifying."); |
va009039 | 0:27d35fa263b5 | 182 | uint8_t buf[256]; |
va009039 | 0:27d35fa263b5 | 183 | bool passed = false; |
va009039 | 0:27d35fa263b5 | 184 | for(int addr = 0; addr < 0x8000; addr++) { |
va009039 | 0:27d35fa263b5 | 185 | int c = fgetc(fp); |
va009039 | 0:27d35fa263b5 | 186 | if (c == EOF) { |
va009039 | 0:27d35fa263b5 | 187 | passed = true; |
va009039 | 0:27d35fa263b5 | 188 | break; |
va009039 | 0:27d35fa263b5 | 189 | } |
va009039 | 0:27d35fa263b5 | 190 | if ((addr % sizeof(buf)) == 0) { |
va009039 | 0:27d35fa263b5 | 191 | _target->readMemory(addr, (uint32_t*)buf, sizeof(buf)/sizeof(uint32_t)); |
va009039 | 0:27d35fa263b5 | 192 | _pc->printf("."); |
va009039 | 0:27d35fa263b5 | 193 | } |
va009039 | 0:27d35fa263b5 | 194 | if (c != buf[addr % sizeof(buf)]) { |
va009039 | 0:27d35fa263b5 | 195 | _pc->printf("\nError at %08x(%02x:%02x)\n", addr, c, buf[addr % sizeof(buf)]); |
va009039 | 4:5e4107edcbdb | 196 | break; |
va009039 | 0:27d35fa263b5 | 197 | } |
va009039 | 0:27d35fa263b5 | 198 | } |
va009039 | 0:27d35fa263b5 | 199 | fclose(fp); |
va009039 | 0:27d35fa263b5 | 200 | if (passed) { |
va009039 | 0:27d35fa263b5 | 201 | _pc->printf("passed.\n"); |
va009039 | 0:27d35fa263b5 | 202 | } |
va009039 | 0:27d35fa263b5 | 203 | return passed; |
va009039 | 0:27d35fa263b5 | 204 | } |