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