ISP example program.

Dependencies:   SLCD mbed USBLocalFileSystem

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BaseLpcIsp.cpp Source File

BaseLpcIsp.cpp

00001 #include "BaseLpcIsp.h"
00002 #include <algorithm>
00003 
00004 #if (DEBUG2 > 3)
00005 #define ISP_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");} while(0);
00006 #else
00007 #define ISP_DBG(...) while(0);
00008 #endif
00009 
00010 #define ISP_ERR() isp_error(__LINE__)
00011 
00012 #define RAM 0x10000300
00013 #define ROM_SIZE 0x10000
00014 
00015 void BaseLpcIsp::Reset(bool isp)
00016 {
00017     _nisp = isp ? 0 : 1;
00018     _nreset = 0;
00019     wait_ms(50);
00020     _nreset = 1;
00021     wait_ms(100);
00022 }
00023 
00024 bool BaseLpcIsp::Sync()
00025 {
00026     putc('?');
00027     if (waitln("Synchronized")) { // Synchronized
00028         sendln("Synchronized");
00029         if (waitln("OK")) {
00030             sendln("14748");
00031             if (waitln("OK")) {
00032                 if (_cmd("A 0")) { // echo off
00033                     return true;
00034                 }
00035             }
00036         }
00037     }
00038     ISP_ERR();
00039     return false;
00040 }
00041 
00042 bool BaseLpcIsp::_cmd(const char* format, ...)
00043 {
00044     char buf[128];
00045     va_list args;
00046     va_start(args, format);
00047     vsprintf(buf, format, args);
00048     va_end(args);
00049     sendln(buf);
00050 
00051     if (waitln("0")) { // CMD_SUCCESS ?
00052         return true;
00053     }
00054     ISP_ERR();
00055     return false;
00056 }
00057 
00058 void BaseLpcIsp::sendln(const char* s)
00059 {
00060     infoLED(LED_TX, tx_sw++ & 1);
00061     ISP_DBG("send:[%s]", s);
00062     puts(s);
00063     puts(CRLF);
00064 }
00065 
00066 bool BaseLpcIsp::waitln(const char* s)
00067 {
00068     char buf[64];
00069     while(recvln(buf, sizeof(buf))) {
00070         if (strcmp(buf, s) == 0) {
00071             ISP_DBG("recv:[%s]", buf);
00072             return true;
00073         }
00074         ISP_DBG("skip:[%s]", buf);
00075     }
00076     ISP_ERR();
00077     return false;
00078 }
00079 
00080 bool BaseLpcIsp::recvln(mystring& s)
00081 {
00082     Timer t;
00083     t.reset();
00084     t.start();
00085     while(t.read_ms() < 900) {
00086         if (readable()) {
00087             int c = getc();
00088             if (c == LF) {
00089                 return true;
00090             } else if (c >= ' ') {
00091                 s.append(c);
00092             }
00093         }
00094     }
00095     ISP_ERR();
00096     return false;
00097 }
00098 
00099 bool BaseLpcIsp::recvln(char* buf, int size)
00100 {
00101     Timer t;
00102     t.reset();
00103     t.start();
00104     int pos = 0;
00105     while(t.read_ms() < 900) {
00106         if (readable()) {
00107             int c = getc();
00108             if (c == LF) {
00109                 buf[pos] = '\0';
00110                 return true;
00111             } else if (c >= ' ') {
00112                 if (pos < size-1) {
00113                     buf[pos++] = c;
00114                 }
00115             }
00116         }
00117     }
00118     return false;
00119 }
00120 
00121 bool BaseLpcIsp::FlashWrite(const char* filename)
00122 {
00123     infoLED(LED_TX, 0);
00124     if (!_cmd("J")) {
00125         return false;
00126     }
00127     char lineBuf[16];
00128     if (!recvln(lineBuf, sizeof(lineBuf))) {
00129         ISP_ERR();
00130         return false;
00131     }
00132     ISP_DBG("recv:[%s]", lineBuf);
00133 
00134     part_code = strtoul(lineBuf, NULL, 10);
00135     if (part_code >= 0x8100 && part_code <= 0x81ff) { // LPC8XX
00136         chunk_size = 64;
00137         sector_size = 1024;
00138         plan_binary = true;
00139         infoSLCD("810 ");
00140     } else {
00141         chunk_size = 256;
00142         sector_size = 4096;
00143         plan_binary = false;
00144         infoSLCD("1114");
00145     }
00146     
00147     if (!_cmd("U 23130")) { // Unlock
00148         ISP_ERR();
00149         return false;
00150     }
00151 
00152     FILE* fp = fopen(filename, "rb");
00153     if (fp == NULL) {
00154         ISP_ERR();
00155         return false;
00156     }
00157 
00158     int bin_size = 0;
00159     Timer t;
00160     t.reset();
00161     t.start();
00162     uint8_t buf[chunk_size];
00163     int sector = 0;
00164     bool result = false;
00165     for(int addr = 0; addr < ROM_SIZE; addr += sizeof(buf)) {
00166         if (feof(fp)) {
00167             result = true;
00168             break;
00169         }
00170         fread(buf, sizeof(buf), 1, fp);
00171         if (!_patch(addr, buf, sizeof(buf))) {
00172             break;
00173         }
00174         bin_size += sizeof(buf);
00175         if (!_write_to_ram(RAM, buf, sizeof(buf))) {
00176             break;
00177         }
00178         if ((addr % sector_size) == 0) {
00179             sector = addr / sector_size;
00180             if (!_cmd("P %u %u", sector, sector)) {
00181                 break;
00182             }
00183             if (!_cmd("E %u %u", sector, sector)) { // Erase
00184                 break;
00185             }
00186             if (!_cmd("I %u %u", sector, sector)) { // Blank check
00187                 break;
00188             }
00189         }
00190         if (!_cmd("P %u %u", sector, sector)) {
00191             break;
00192         }
00193         if (!_cmd("C %u %u %u", addr, RAM, sizeof(buf))) { // copy
00194             break;
00195         }
00196         if (!_cmd("M %u %u %u", addr, RAM, sizeof(buf))) { // compare
00197             break;
00198         }
00199     }
00200     fclose(fp);
00201     infoLED(LED_TX, 0);
00202     if (result) {
00203         t.stop();
00204         ISP_DBG("bin size: %d bytes, %d ms, %d bytes/sec", 
00205             bin_size, t.read_ms(), bin_size*1000/t.read_ms());
00206         infoSLCD("OK  ");
00207     }   
00208     return result;
00209 }
00210 
00211 extern void uuencode(const void* src, int srcsize, char* dst); //utils.cpp
00212 
00213 bool BaseLpcIsp::_write_to_ram(int addr, uint8_t* buf, int size)
00214 {
00215     if (!_cmd("W %u %u", addr, size)) {
00216         return false;
00217     }
00218     if (plan_binary) {
00219         for(int i = 0; i < size; i++) {
00220             _target.putc(buf[i]);
00221         }
00222         return true;
00223     }
00224     int sum = 0;
00225     int line = 0;
00226     for(int n = 0; n < size; n += 45) {
00227         char tmp[61+1];
00228         int size2 = std::min(45, size - n);
00229         uuencode(buf+n, size2, tmp);
00230         sendln(tmp);
00231         for(int i = 0; i < size2; i++) {
00232             sum += buf[n+i];
00233         }
00234         if (++line >= 20 || (n + size2) >= size) {
00235             snprintf(tmp, sizeof(tmp), "%u", sum);
00236             sendln(tmp);
00237             if (!waitln("OK")) {
00238                 return false;
00239             }
00240             line = 0;
00241             sum = 0;
00242         }
00243     }
00244     return true;
00245 }
00246 
00247 bool BaseLpcIsp::_patch(int addr, uint8_t* buf, int size)
00248 {
00249     const int crp_start = 0x2fc; // Code Read Protection location
00250     if (crp_start >= addr && crp_start < addr+size) {
00251         uint32_t pat = *reinterpret_cast<uint32_t*>(crp_start-addr+buf);
00252         if (pat != 0xffffffff) { // NO_CRP ?
00253             ISP_ERR();
00254             return false;
00255         }
00256     }
00257     return true;
00258 }