Norimasa Okamoto / Mbed 2 deprecated emuISP

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BaseEmuISP.cpp Source File

BaseEmuISP.cpp

00001 // BaseEmuISP.cpp 2016/3/24
00002 #include <stdio.h>
00003 #include <stdlib.h>
00004 #include <string.h>
00005 #include <stdarg.h>
00006 #include "BaseEmuISP.h"
00007 
00008 void BaseEmuISP::Reset() {
00009     mode = M_RESET;
00010 }
00011 
00012 void BaseEmuISP::Poll() {
00013     Mode_t prev_mode = mode;
00014     int result;
00015     char buf[32];
00016     switch(mode) {
00017         case M_RESET:
00018             echoFlag = true;
00019             lockFlag = true;
00020             version.Major = BootCodeVersion() >>8;
00021             version.Minor = BootCodeVersion() & 0xff;
00022             mode = M_SYNC;
00023             break;
00024         case M_SYNC:
00025             if (sync()) {
00026                 mode = M_CMD;
00027             }
00028             break;
00029         case M_CMD:
00030             if (lineProc()) {
00031                 result = cmd(line.c_str());
00032                 snprintf(buf, sizeof(buf), "%d", result);
00033                 putln(buf);
00034                 line.clear();
00035             }
00036             break;
00037         case M_CMD_W_DATA:
00038             if (cmd_w_data()) {
00039                 mode = M_CMD;
00040             }
00041             break;
00042         case M_CMD_R_DATA:
00043             if (cmd_r_data()) {
00044                 mode = M_CMD;
00045             }
00046             break;
00047         case M_CMD_J:
00048             snprintf(buf, sizeof(buf), "%d", PartID());
00049             putln(buf);
00050             mode = M_CMD;
00051             break;
00052         case M_CMD_K:
00053             snprintf(buf, sizeof(buf), "%d", version.Major);
00054             putln(buf);
00055             snprintf(buf, sizeof(buf), "%d", version.Minor);
00056             putln(buf);
00057             mode = M_CMD;
00058             break;
00059         case M_CMD_N:
00060             mode = M_CMD;
00061             break;
00062         case M_CMD_S:
00063             mode = M_CMD;
00064             break;
00065     }
00066     if (prev_mode != mode) {
00067         seq = 0;
00068         line.clear();
00069     }
00070 }
00071 
00072 bool BaseEmuISP::sync() {
00073     switch(seq) {
00074         case 0:
00075             if (Getch() == '?') {
00076                 putln("Synchronized");
00077                 line.clear();
00078                 echoFlag = true;
00079                 seq++;
00080             }
00081             break;
00082         case 1:
00083             if (lineProc()) {
00084                 if (line == "Synchronized") {
00085                     putln("OK");
00086                     line.clear();
00087                     seq++;
00088                 } else {
00089                     seq = 0;
00090                 }
00091             }
00092             break;
00093         case 2:
00094             if (lineProc()) {
00095                 freq = atoi(line.c_str());
00096                 putln("OK");
00097                 return true;
00098             }
00099             break;
00100     }
00101     return false;
00102 }
00103 
00104 static int split(vec_charPtr_t &param, char *buf, const char* delimiters = " ") {
00105     param.clear();
00106     char* p = strtok(buf, delimiters);
00107     while(p != NULL) {
00108         param.push_back(p);
00109         p = strtok(NULL, delimiters);
00110     }
00111     return param.size();
00112 }
00113 
00114 ReturnCode_t BaseEmuISP::cmd(const char *str) {
00115     char buf[strlen(str) + 1];
00116     strcpy(buf, str);
00117     myvector<char*> p;
00118     if (split(p, buf) == 0) {
00119         return INVALID_COMMAND;
00120     }
00121     vec_int_t param;
00122     param.push_back(p[0][0]);
00123     for(size_t i = 1; i < p.size(); i++) {
00124         param.push_back(atoi(p[i]));
00125     }
00126     switch(param[0]) {
00127         case 'U': return cmd_u(param);
00128         case 'A': return cmd_a(param);
00129         case 'W': return cmd_w(param);
00130         case 'R': return cmd_r(param);
00131         case 'P': return cmd_p(param);
00132         case 'C': return cmd_c(param);
00133         case 'E': return cmd_e(param);
00134         case 'I': return cmd_i(param);
00135         case 'J': return cmd_j(param);
00136         case 'K': return cmd_k(param);
00137         case 'N': return cmd_n(param);
00138         case 'S': return cmd_s(param);
00139         default: return INVALID_COMMAND;
00140     }
00141 }
00142 
00143 ReturnCode_t BaseEmuISP::cmd_a(vec_int_t &param) {
00144     if (param.size() > 1) {
00145         if (param[1] == 0 || param[1] == 1) {
00146             echoFlag = (param[1] == 1) ? true : false;
00147             return CMD_SUCCESS;
00148         }
00149     }
00150     return PARAM_ERROR;
00151 }
00152 
00153 ReturnCode_t BaseEmuISP::cmd_u(vec_int_t &param) {
00154     if (param.size() > 1) {
00155         if (param[1] == 23130) {
00156             lockFlag = false;
00157             return CMD_SUCCESS;
00158         }
00159     }
00160     return PARAM_ERROR;
00161 }
00162 
00163 ReturnCode_t BaseEmuISP::cmd_w(vec_int_t &param) {
00164     if (param.size() > 2) {
00165         if (param[1] % 4 != 0) {
00166             return ADDR_ERROR;
00167         }
00168         if (param[2] % 4 != 0) {
00169             return COUNT_ERROR;
00170         }
00171         addr = param[1];
00172         data.Count = param[2];
00173         mode = M_CMD_W_DATA;
00174         return CMD_SUCCESS;
00175     }
00176     return PARAM_ERROR;
00177 }
00178 
00179 ReturnCode_t BaseEmuISP::cmd_r(vec_int_t &param) {
00180     if (param.size() > 2) {
00181         if (param[1] % 4 != 0) {
00182             return ADDR_ERROR;
00183         }
00184         if (param[2] % 4 != 0) {
00185             return COUNT_ERROR;
00186         }
00187         addr = param[1];
00188         data.Count = param[2];
00189         mode = M_CMD_R_DATA;
00190         return CMD_SUCCESS;
00191     }
00192     return PARAM_ERROR;
00193 }
00194 
00195 ReturnCode_t BaseEmuISP::cmd_p(vec_int_t &param) {
00196     if (param.size() > 2) {
00197         for(int sector = param[1]; sector <= param[2]; sector++) {
00198             if (!Prepare(sector)) {
00199                 return INVALID_SECTOR;
00200             }
00201         }
00202         return CMD_SUCCESS;
00203     }
00204     return PARAM_ERROR;
00205 }
00206 
00207 ReturnCode_t BaseEmuISP::cmd_c(vec_int_t &param) {
00208     if (lockFlag) {
00209         return CMD_LOCKED;
00210     }
00211     if (param.size() > 3) {
00212         if (param[1] % 4 != 0) {
00213             return DST_ADDR_ERROR;
00214         }
00215         if (param[2] % 4 != 0) {
00216             return SRC_ADDR_ERROR;
00217         }
00218         if (param[3] != 64 && param[3] != 128 && param[3] != 256 &&
00219             param[3] != 512 && param[3] != 1024) {
00220             return COUNT_ERROR;
00221         }
00222         CopyData(param[1], param[2], param[3]);
00223         return CMD_SUCCESS;
00224     }
00225     return PARAM_ERROR;
00226 }
00227 
00228 ReturnCode_t BaseEmuISP::cmd_e(vec_int_t &param) {
00229     if (lockFlag) {
00230         return CMD_LOCKED;
00231     }
00232     if (param.size() > 2) {
00233         for(int sector = param[1]; sector <= param[2]; sector++) {
00234             if (!Erase(sector)) {
00235                 return INVALID_SECTOR;
00236             }
00237         }
00238         return CMD_SUCCESS;
00239     }
00240     return PARAM_ERROR;
00241 }
00242 
00243 ReturnCode_t BaseEmuISP::cmd_i(vec_int_t &param) {
00244     if (param.size() > 2) {
00245         for(int sector = param[1]; sector <= param[2]; sector++) {
00246             if (!Blank(sector)) {
00247                 return SECTOR_NOT_BLANK;
00248             }
00249         }
00250         return CMD_SUCCESS;
00251     }
00252     return PARAM_ERROR;
00253 }
00254 
00255 ReturnCode_t BaseEmuISP::cmd_j(vec_int_t &param) {
00256     mode = M_CMD_J;
00257     return CMD_SUCCESS;
00258 }
00259 
00260 ReturnCode_t BaseEmuISP::cmd_k(vec_int_t &param) {
00261     mode = M_CMD_K;
00262     return CMD_SUCCESS;
00263 }
00264 
00265 ReturnCode_t BaseEmuISP::cmd_m(vec_int_t &param) {
00266     if (param.size() > 3) {
00267         if (param[1] % 4 != 0 || param[2] % 4 != 0) {
00268             return ADDR_ERROR;
00269         }
00270         if (param[3] % 4 != 0) {
00271             return COUNT_ERROR;
00272         }
00273         if (!Compare(param[1], param[2], param[3])) {
00274             return COMPARE_ERROR;
00275         }
00276         return CMD_SUCCESS;
00277     }
00278     return PARAM_ERROR;
00279 }
00280 
00281 ReturnCode_t BaseEmuISP::cmd_n(vec_int_t &param) {
00282     mode = M_CMD_N;
00283     return CMD_SUCCESS;
00284 }
00285 
00286 ReturnCode_t BaseEmuISP::cmd_s(vec_int_t &param) {
00287     mode = M_CMD_S;
00288     return CMD_SUCCESS;
00289 }
00290 
00291 void uudecode(vec_byte_t &dst, const char* src) {
00292     dst.clear();
00293     int len = strlen(src);
00294     if (len > 0) {
00295         size_t size = (src[0]^0x20)&0x3f;
00296         uint8_t b[4];
00297         int k = 0;
00298         for(int i = 1; i < len && dst.size() < size; i++) {
00299             b[k] = (src[i]^0x20)&0x3f;
00300             if (k == 0) {
00301                 k++;
00302             } else if (k == 1) {
00303                 dst.push_back(b[0]<<2|b[1]>>4);
00304                 k++;
00305             } else if (k == 2) {
00306                 dst.push_back(b[1]<<4|b[2]>>2);
00307                 k++;
00308             } else {
00309                 dst.push_back(b[2]<<6|b[3]);
00310                 k = 0;
00311             }
00312         }
00313     }
00314 }
00315 
00316 bool BaseEmuISP::cmd_w_data() {
00317     int c;
00318     switch(seq) {
00319         case 0:
00320             data.Current = 0;
00321             if (UuencodeMode()) {
00322                 seq = 2;
00323             } else {
00324                 seq = 1;
00325             }
00326             break;
00327         case 1: // binary mode
00328             if (data.Current >= data.Count) {
00329                 return true;
00330             }
00331             c = Getch();
00332             if (c != (-1)) {
00333                 if (echoFlag) {
00334                     Putch(c);
00335                 }
00336                 WriteData(addr++, c);
00337                 data.Current++;
00338             }
00339             break;
00340         case 2: // uuencode mode
00341             data.Line = 0;
00342             data.Cksum = 0;
00343             line.clear();
00344             seq++;
00345             break;
00346         case 3: // uu data start
00347             if (lineProc()) {
00348                 uudecode(data.Buf, line.c_str());
00349                 for(size_t i = 0; i < data.Buf.size(); i++) {
00350                     int c = data.Buf[i];
00351                     WriteData(addr++, c);
00352                     data.Cksum += c;
00353                     data.Current++;
00354                 }
00355                 data.Line++;
00356                 if (data.Line >= 20 || data.Current>= data.Count) {
00357                     seq++;
00358                 }
00359                 line.clear();
00360             }
00361             break;
00362         case 4: // check sum
00363             if (lineProc()) {
00364                 if (atoi(line.c_str()) == data.Cksum) {
00365                     putln("OK");
00366                     if (data.Current >= data.Count) {
00367                         mode = M_CMD;
00368                     } else {
00369                         seq = 2;
00370                     }
00371                 } else {
00372                     putln("RESEND");
00373                     seq = 2;
00374                 }
00375             }
00376             break;
00377     }
00378     return false;
00379 }
00380 
00381 bool BaseEmuISP::cmd_r_data() {
00382     int c;
00383     switch(seq) {
00384         case 0:
00385             data.Current = 0;
00386             if (UuencodeMode()) {
00387                 data.Line = 0;
00388                 data.Cksum = 0;
00389                 line.clear();
00390                 seq = 2;
00391             } else {
00392                 seq = 1;
00393             }
00394             break;
00395         case 1: // binary mode
00396             if (data.Current >= data.Count) {
00397                 return true;
00398             }
00399             c = ReadData(addr++);
00400             Putch(c);
00401             data.Current++;
00402             break;
00403         case 2:
00404             break;
00405     }
00406     return false;
00407 }
00408 
00409 
00410 void BaseEmuISP::putln(const char *s) {
00411     debugPrintf("send: %s<CR><LF>\n", s);
00412     while(*s) {
00413         Putch(*s++);
00414     }
00415     Putch('\r');
00416     Putch('\n');
00417 }
00418 
00419 bool BaseEmuISP::lineProc() {
00420     int c = Getch();
00421     if (c != (-1)) {
00422         if (echoFlag) {
00423             if (version.Major >= 4 || c != '\n') {
00424                 Putch(c);
00425             }
00426         }
00427         if (c == '\n') {
00428             debugPrintf("<LF>\n");
00429             return true;
00430         } else if (c == '\r') {
00431             debugPrintf("<CR>");
00432         } else {
00433             if (line.size() == 0) {
00434                 debugPrintf("recv: ");
00435             }
00436             debugPrintf("%c", c);
00437             line += c;
00438         }
00439     }
00440     return false;
00441 }
00442 
00443 void BaseEmuISP::debugPrintf(const char *format, ...) {
00444     char buf[256];
00445     va_list args;
00446     va_start(args, format);
00447     vsprintf(buf, format, args);
00448     for(const char *s = buf; *s; s++) {
00449         DebugPutch(*s);
00450     }
00451     va_end(args);
00452 }
00453