USB composite device example program, drag-and-drop flash writer.

Dependencies:   SWD USBDevice mbed BaseDAP

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Flash.cpp Source File

Flash.cpp

00001 // Flash.cpp 2013/9/16
00002 #include "Flash.h"
00003 #include "Target2.h"
00004 #include "mydebug.h"
00005 
00006 #define SYSMEMREMAP  0x40048000
00007 #define MAINCLKSEL   0x40048070
00008 #define MAINCLKUEN   0x40048074
00009 #define SYSAHBCLKDIV 0x40048078
00010 
00011 Flash::Flash(Target2* target, Serial* usbpc) :_target(target),_pc(usbpc)
00012 {
00013     _setup();
00014 }
00015 
00016 void Flash::_setup()
00017 {
00018     _target->halt();
00019     _target->wait_status(TARGET_HALTED);
00020     _target->prog_status();
00021 }
00022 
00023 bool Flash::init()
00024 {
00025     _pc->printf("Initializing.");
00026     if (_target->idcode == 0x0bb11477) { // LPC1114FN28
00027         _target->writeMemory(MAINCLKSEL, 0);  // Select Internal RC Oscillator
00028         _target->writeMemory(MAINCLKUEN, 1);  // Update Main Clock Source
00029         _target->writeMemory(MAINCLKUEN, 0);  // Toggle Update Register
00030         _target->writeMemory(MAINCLKUEN, 1);
00031         uint32_t data = _target->readMemory(MAINCLKUEN); // Wait until updated
00032         if (!(data & 1)) {
00033             _pc->printf("\nerror MAINCLKUEN=%08x\n", data);
00034             return false;
00035         }
00036         _target->writeMemory(SYSAHBCLKDIV, 1);// Set Main Clock divider to 1
00037         _target->writeMemory(SYSMEMREMAP, 2); // User Flash Mode
00038     } else {
00039         _pc->printf("\nerror idcode=%08x\n", _target->idcode);
00040         return false;
00041     }
00042     _pc->printf("passed.\n");
00043     return true;
00044 }
00045 
00046 bool Flash::write(const char* filename)
00047 {
00048     FILE* fp = fopen(filename, "rb");
00049     if (fp == NULL) {
00050         _pc->printf("file open error [%s]\n", filename);
00051         return false;
00052     }
00053     _pc->printf("Writing.");
00054     uint8_t buf[512];
00055     bool passed = false;
00056     for(int addr = 0; addr < 0x8000; addr += sizeof(buf)) {
00057         int ret = fread(buf, 1, sizeof(buf), fp);
00058         if (!_patch(buf, sizeof(buf), addr)) {
00059             break;
00060         }
00061         if (!write(addr, buf, sizeof(buf))) {
00062             break;
00063         }
00064         _pc->printf(".");
00065         if (ret < sizeof(buf)) {
00066             passed = true;
00067             break;
00068         }
00069     }
00070     fclose(fp);
00071     if (passed) {
00072         _pc->printf("passed.\n");
00073     }
00074     return passed;
00075 }
00076 
00077 bool Flash::write(int addr, const uint8_t* data, int size)
00078 {
00079     const int ram = 0x10000200;
00080     const int ram_size = 256;
00081     for(int i = 0; i < size; i += ram_size) {
00082         if (!_write_to_ram(ram, ram_size, data+i)) {
00083             _pc->printf("faild. write to ram %08x\n", ram);
00084             return false;
00085         }
00086         if (remoteIAP(PREPARE_SECTOR, _sector(addr+i), _sector(addr+i)) != CMD_SUCCESS) {
00087             _pc->printf("faild. PREPARE_SECTOR %d %d\n", _sector(addr+i), _sector(addr+i));
00088             return false;
00089         }
00090         if (remoteIAP(COPY_RAM_TO_FLASH, addr+i, ram, ram_size, IAP_CCLK) != CMD_SUCCESS) {
00091             _pc->printf("faild. COPY_RAM_TO_FLASH %d %d %d %dn", addr+i, ram, ram_size);
00092             return false;
00093         }
00094         if (remoteIAP(COMPARE, addr+i, ram, ram_size) != CMD_SUCCESS) {
00095             _pc->printf("faild. COMPARE %d %d %d", addr+i, ram, ram_size);
00096             return false;
00097         }
00098     }
00099     return true;
00100 }
00101 
00102 bool Flash::eraseAll()
00103 {
00104     _pc->printf("Erasing.");
00105     for(int sector = 0; sector <= 7; sector++) {
00106         IAP_STATUS status = remoteIAP(PREPARE_SECTOR, sector, sector); 
00107         if (status != CMD_SUCCESS) {
00108             _pc->printf("faild. PREPARE_SECTOR %d %d status=%d\n", sector, sector, status);
00109             return false;
00110         }
00111         if (remoteIAP(ERASE_SECTOR, sector, sector, IAP_CCLK) != CMD_SUCCESS) {
00112             _pc->printf("faild. ERASE_SECTOR %d %d %d\n", sector, sector, IAP_CCLK);
00113             return false;
00114         }
00115         if (remoteIAP(BLANK_CHECK, sector, sector, IAP_CCLK) != CMD_SUCCESS) {
00116             _pc->printf("faild. BLANK_CHECK %d %d %d\n", sector, sector, IAP_CCLK);
00117             return false;
00118         }
00119         _pc->printf(".");
00120     }
00121     _pc->printf("passed.\n");
00122     return true;
00123 }
00124 
00125 bool Flash::_write_to_ram(int addr, int size, const uint8_t* buf)
00126 {
00127     _target->writeMemory(addr, (uint32_t*)buf, size / sizeof(uint32_t));
00128     return true;
00129 }
00130 
00131 int Flash::_sector(int addr)
00132 {
00133     return addr / 4096;
00134 }
00135 
00136 static uint32_t LD32(uint8_t* buf)
00137 {
00138     return buf[0] | buf[1]<<8 | buf[2]<<16 | buf[3]<<24;
00139 }
00140 
00141 bool Flash::_patch(uint8_t* buf, int size, int addr)
00142 {
00143     const int crp_start = 0x2fc; // Code Read Protection location
00144     if (crp_start >= addr && crp_start < addr+size) {
00145         uint32_t pat = LD32(crp_start-addr+buf);
00146         if (pat != 0xffffffff) { // NO_CRP ?
00147             _pc->printf("\nCAUTION: CRP Pattern is not NO_CRP; %08x\n", pat);
00148             return false;
00149         }
00150     }
00151     return true;
00152 }
00153 
00154 Flash::IAP_STATUS Flash::remoteIAP(Flash::IAP_CMD cmd, uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3)
00155 {
00156     struct {
00157         uint32_t bkpt;       // +0       
00158         struct {             // IAP Structure
00159             uint32_t cmd;    // +4 Command
00160             uint32_t par[4]; // +8 Parameters
00161             uint32_t stat;   // +24 Status
00162             uint32_t res[4]; // +28 Result
00163         } IAP;               // +44
00164     } ram; 
00165     
00166     ram.bkpt = 0xe00abe00; // bpkt #00
00167     ram.IAP.cmd = cmd;
00168     ram.IAP.par[0] = p0;
00169     ram.IAP.par[1] = p1;
00170     ram.IAP.par[2] = p2;
00171     ram.IAP.par[3] = p3;
00172     _target->halt();
00173     _target->wait_status(TARGET_HALTED);
00174     const uint32_t ram_addr = 0x10000100;
00175     _target->writeMemory(ram_addr, (uint32_t*)&ram, sizeof(ram)/sizeof(uint32_t));
00176     _target->r0 = ram_addr + 4;  // command addr
00177     _target->r1 = ram_addr + 24; // status addr
00178     _target->sp = 0x10000400-32; // IAP use ram top 32bytes
00179     _target->lr = ram_addr + 1; // return to bkpt
00180     _target->pc = 0x1fff1ff1; // IAP_Call
00181     _target->resume();
00182     _target->wait_status(TARGET_HALTED);
00183     return (IAP_STATUS)_target->readMemory(ram_addr + 24);  
00184 }
00185 
00186 bool Flash::verify(const char* filename)
00187 {
00188     FILE* fp = fopen(filename, "rb");
00189     if (fp == NULL) {
00190         _pc->printf("file open error [%s]\n", filename);
00191         return false;
00192     }
00193     _pc->printf("Verifying.");
00194     uint8_t buf[256];
00195     bool passed = false;
00196     for(int addr = 0; addr < 0x8000; addr++) {
00197         int c = fgetc(fp);
00198         if (c == EOF) {
00199             passed = true;
00200             break;
00201         }
00202         if ((addr % sizeof(buf)) == 0) {
00203             _target->readMemory(addr, (uint32_t*)buf, sizeof(buf)/sizeof(uint32_t));
00204             _pc->printf(".");
00205         }
00206         if (c != buf[addr % sizeof(buf)]) {
00207             _pc->printf("\nError at %08x(%02x:%02x)\n", addr, c, buf[addr % sizeof(buf)]);
00208             break;
00209         }
00210     }
00211     fclose(fp);
00212     if (passed) {
00213         _pc->printf("passed.\n");
00214     }
00215     return passed;
00216 }