IJFW - IchigoJamのBASICプログラムをメモリカード(MMCまたは互換カード)に保存したり読み出したりできるプログラム。メモリカードにファームウェアのファイルを置くだけで、電源ON時に自動的に書き換える機能も搭載(一応こちらがメイン)。LPC1114FN28専用。

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers UartIspBase.cpp Source File

UartIspBase.cpp

00001 #include "UartIspBase.h"
00002 #include <stdio.h>
00003 #include <string.h>
00004 
00005 const int SYNC_RETRY_NUM = 3;
00006 const int UUENCODE_LINE_BYTES = 45;         // must be multiples of 3
00007 const int RETURN_NORMAL = 1;
00008 const int RETURN_FAULT = 0;
00009 
00010 
00011 UartIspBase::UartIspBase() {
00012     // echoback setting
00013     echoBack = 1;
00014 
00015     // Generate UUEncode Table
00016     uuCharTable[0] = 0x60;
00017     for (int i = 1; i < 64; i++) {
00018         uuCharTable[i] = i + 32;
00019     }
00020 }
00021 
00022 
00023 UartIspBase::~UartIspBase() {
00024 
00025 }
00026 
00027 
00028 char UartIspBase::getUuString(int i) {
00029     return uuCharTable[i % 64];
00030 }
00031 
00032 
00033 void UartIspBase::disableEchoBack() {
00034     writeString("A 0\n");
00035     echoBack = 0;
00036 }
00037 
00038 
00039 void UartIspBase::writeString(const char val) {
00040     writeSerial(val);
00041     if (echoBack) {
00042         readSerial();
00043     }
00044 }
00045 
00046 
00047 void UartIspBase::writeString(const char* str) {
00048     int length = strlen(str);
00049     for (int i = 0; i < length; i++) {
00050         writeSerial(*(str+i));
00051 
00052         if (echoBack) {
00053             while(!readable());
00054             readSerial();
00055         }
00056     }
00057 }
00058 
00059 
00060 int UartIspBase::isRecieveStringMatch(const char* checkString) {
00061     int length = strlen(checkString);
00062 
00063     for(int i = 0; i < length; i++) {
00064         char b = readSerial();
00065         if (b != *(checkString+i)) {
00066             return 0;       // Not matched
00067         }
00068     }
00069 
00070     return 1;       // Matched
00071 }
00072 
00073 
00074 int UartIspBase::openIsp(int mcufreq) {
00075     // Sequence of synchronization for MCU uart
00076     for (int i = 0; i < SYNC_RETRY_NUM; i++) {
00077         if (i > 0) {
00078             sleep(3000);
00079         }
00080         // step 1
00081         writeSerial('?');
00082         if (!isRecieveStringMatch("Synchronized\r\n")) {
00083             writeString("\n");
00084             continue;
00085         }
00086         // step 2
00087         writeString("Synchronized\n");
00088         if (!isRecieveStringMatch("OK\r\n")) {
00089             writeString("\n");
00090             continue;
00091         }
00092         // step 3
00093         char str[32];
00094         sprintf(str, "%d\n", mcufreq);
00095         writeString(str);
00096         if (!isRecieveStringMatch("OK\r\n")) {
00097             writeString("\n");
00098             continue;
00099         }
00100         return RETURN_NORMAL;
00101     }
00102     // when MCU does not sync
00103     return RETURN_FAULT;
00104 }
00105 
00106 
00107 int UartIspBase::unlockFlash() {
00108     // Unlock Flash Write and Erase
00109     writeString("U 23130\n");
00110     if (!isRecieveStringMatch("0\r\n")) {
00111         return RETURN_FAULT;
00112     }
00113     return RETURN_NORMAL;
00114 }
00115 
00116 
00117 int UartIspBase::eraseFlash(int startSector, int endSector) {
00118     // Prepare command
00119     char str[32];
00120     sprintf(str, "P %d %d\n", startSector, endSector);
00121     writeString(str);
00122     if (!isRecieveStringMatch("0\r\n")) {
00123         return RETURN_FAULT;
00124     }
00125 
00126     // Erase command (All sectors)
00127     sprintf(str, "E %d %d\n", startSector, endSector);
00128     writeString(str);
00129     if (!isRecieveStringMatch("0\r\n")) {
00130         return RETURN_FAULT;
00131     }
00132 
00133     return RETURN_NORMAL;
00134 }
00135 
00136 
00137 int UartIspBase::writeToRam(char buffer[], unsigned int ramAddress, int length) {
00138     int normalizeLength = ((length + 2) / 3) * 3;   // normalize multiples of 3
00139     unsigned int checksum = 0;
00140     unsigned int data3bytes = 0;
00141     int bufPos = 0;
00142     int lineNum = 0;
00143     int lineBytes;
00144     char str[32];
00145 
00146      // Send W command
00147     sprintf(str, "W %d %d\n", ramAddress, length);
00148     writeString(str);
00149     if (!isRecieveStringMatch("0\r\n")) {
00150         writeSerial(0x1B);      // send ESC
00151         return RETURN_FAULT;
00152     }
00153     
00154     while (bufPos < length) {
00155         // the number of sending bytes of a line
00156         if (bufPos <= length - UUENCODE_LINE_BYTES) {
00157             lineBytes = UUENCODE_LINE_BYTES;
00158             writeString(getUuString(lineBytes));
00159         } else {
00160             lineBytes = normalizeLength - bufPos;
00161             writeString(getUuString(length - bufPos));
00162         }
00163         
00164         // send data of a line 
00165         for (int i = 0; i < lineBytes; i++) {
00166             unsigned char data;
00167             if (bufPos + i < length) {
00168                 data = buffer[bufPos + i];
00169             } else {
00170                 data = 0;
00171             }
00172             checksum += data;
00173             
00174             // Encode uuencode data and store array
00175             if ((i % 3) == 0) {
00176                 data3bytes = data;
00177             } else {
00178                 data3bytes = (data3bytes << 8) + data;
00179             }
00180             
00181             if ((i % 3) == 2) {
00182                 writeString(getUuString( (data3bytes >> 18) & 0x3F ) );
00183                 writeString(getUuString( (data3bytes >> 12) & 0x3F ) );
00184                 writeString(getUuString( (data3bytes >>  6) & 0x3F ) );
00185                 writeString(getUuString( (data3bytes)       & 0x3F ) );
00186             }
00187         }
00188         writeString("\n");
00189         lineNum++;
00190         bufPos += UUENCODE_LINE_BYTES;
00191 
00192         if (bufPos >= length || (lineNum % 20) == 0) {
00193             sprintf(str, "%d\n", checksum);
00194             writeString(str);
00195             if (echoBack) {     // workaround for response (UART ISP bug?)
00196                 if (!isRecieveStringMatch("OK\r\n")) {
00197                     writeSerial(0x1B);          // send ESC
00198                     return RETURN_FAULT;
00199                 }
00200             } else {
00201                 if (!isRecieveStringMatch("0\r\n")) {
00202                     writeSerial(0x1B);          // send ESC
00203                     return RETURN_FAULT;
00204                 }
00205             }
00206             checksum = 0;
00207         }
00208     }
00209 
00210     return RETURN_NORMAL;
00211 }
00212 
00213 
00214 int UartIspBase::prepareFlash(int startSector, int endSector) {
00215     // Send P command
00216     char str[32];
00217     sprintf(str, "P %d %d\n", startSector, endSector);
00218     writeString(str);
00219 
00220     if (!isRecieveStringMatch("0\r\n")) {
00221         writeSerial(0x1B);      // send ESC
00222         return RETURN_FAULT;
00223     }
00224     return RETURN_NORMAL;
00225 }
00226 
00227 
00228 int UartIspBase::copyToFlash(unsigned int flashAddress, unsigned int ramAddress, int length) {
00229     // Copy program data from RAM to Flash
00230     char str[32];
00231     sprintf(str, "C %d %d %d\n", flashAddress, ramAddress, length);
00232     writeString(str);
00233     
00234     if (!isRecieveStringMatch("0\r\n")) {
00235         writeSerial(0x1B);          // send ESC
00236         return RETURN_FAULT;
00237     }
00238 
00239     // Verify RAM and Flash data
00240     if (flashAddress < 64) {
00241         sprintf(str, "M 64 %d %d\n", ramAddress + 64, length - 64);
00242     } else {
00243         sprintf(str, "M %d %d %d\n", flashAddress, ramAddress, length);
00244     }
00245     writeString(str);
00246 
00247     if (!isRecieveStringMatch("0\r\n")) {
00248         writeSerial(0x1B);          // send ESC
00249         return RETURN_FAULT;
00250     }
00251     
00252     return RETURN_NORMAL;
00253 }