IJFW - IchigoJamのBASICプログラムをメモリカード(MMCまたは互換カード)に保存したり読み出したりできるプログラム。メモリカードにファームウェアのファイルを置くだけで、電源ON時に自動的に書き換える機能も搭載(一応こちらがメイン)。LPC1114FN28専用。
参考URL http://www.cyberchabudai.org/index.php/entry?tag=IJFW
UartIsp/UartIspBase.cpp@2:daf6c4719496, 2016-08-21 (annotated)
- Committer:
- oks486
- Date:
- Sun Aug 21 07:51:01 2016 +0000
- Revision:
- 2:daf6c4719496
- Parent:
- 0:43cce7b453d0
Modified I2c2mem for "FILES" command
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
oks486 | 0:43cce7b453d0 | 1 | #include "UartIspBase.h" |
oks486 | 0:43cce7b453d0 | 2 | #include <stdio.h> |
oks486 | 0:43cce7b453d0 | 3 | #include <string.h> |
oks486 | 0:43cce7b453d0 | 4 | |
oks486 | 0:43cce7b453d0 | 5 | const int SYNC_RETRY_NUM = 3; |
oks486 | 0:43cce7b453d0 | 6 | const int UUENCODE_LINE_BYTES = 45; // must be multiples of 3 |
oks486 | 0:43cce7b453d0 | 7 | const int RETURN_NORMAL = 1; |
oks486 | 0:43cce7b453d0 | 8 | const int RETURN_FAULT = 0; |
oks486 | 0:43cce7b453d0 | 9 | |
oks486 | 0:43cce7b453d0 | 10 | |
oks486 | 0:43cce7b453d0 | 11 | UartIspBase::UartIspBase() { |
oks486 | 0:43cce7b453d0 | 12 | // echoback setting |
oks486 | 0:43cce7b453d0 | 13 | echoBack = 1; |
oks486 | 0:43cce7b453d0 | 14 | |
oks486 | 0:43cce7b453d0 | 15 | // Generate UUEncode Table |
oks486 | 0:43cce7b453d0 | 16 | uuCharTable[0] = 0x60; |
oks486 | 0:43cce7b453d0 | 17 | for (int i = 1; i < 64; i++) { |
oks486 | 0:43cce7b453d0 | 18 | uuCharTable[i] = i + 32; |
oks486 | 0:43cce7b453d0 | 19 | } |
oks486 | 0:43cce7b453d0 | 20 | } |
oks486 | 0:43cce7b453d0 | 21 | |
oks486 | 0:43cce7b453d0 | 22 | |
oks486 | 0:43cce7b453d0 | 23 | UartIspBase::~UartIspBase() { |
oks486 | 0:43cce7b453d0 | 24 | |
oks486 | 0:43cce7b453d0 | 25 | } |
oks486 | 0:43cce7b453d0 | 26 | |
oks486 | 0:43cce7b453d0 | 27 | |
oks486 | 0:43cce7b453d0 | 28 | char UartIspBase::getUuString(int i) { |
oks486 | 0:43cce7b453d0 | 29 | return uuCharTable[i % 64]; |
oks486 | 0:43cce7b453d0 | 30 | } |
oks486 | 0:43cce7b453d0 | 31 | |
oks486 | 0:43cce7b453d0 | 32 | |
oks486 | 0:43cce7b453d0 | 33 | void UartIspBase::disableEchoBack() { |
oks486 | 0:43cce7b453d0 | 34 | writeString("A 0\n"); |
oks486 | 0:43cce7b453d0 | 35 | echoBack = 0; |
oks486 | 0:43cce7b453d0 | 36 | } |
oks486 | 0:43cce7b453d0 | 37 | |
oks486 | 0:43cce7b453d0 | 38 | |
oks486 | 0:43cce7b453d0 | 39 | void UartIspBase::writeString(const char val) { |
oks486 | 0:43cce7b453d0 | 40 | writeSerial(val); |
oks486 | 0:43cce7b453d0 | 41 | if (echoBack) { |
oks486 | 0:43cce7b453d0 | 42 | readSerial(); |
oks486 | 0:43cce7b453d0 | 43 | } |
oks486 | 0:43cce7b453d0 | 44 | } |
oks486 | 0:43cce7b453d0 | 45 | |
oks486 | 0:43cce7b453d0 | 46 | |
oks486 | 0:43cce7b453d0 | 47 | void UartIspBase::writeString(const char* str) { |
oks486 | 0:43cce7b453d0 | 48 | int length = strlen(str); |
oks486 | 0:43cce7b453d0 | 49 | for (int i = 0; i < length; i++) { |
oks486 | 0:43cce7b453d0 | 50 | writeSerial(*(str+i)); |
oks486 | 0:43cce7b453d0 | 51 | |
oks486 | 0:43cce7b453d0 | 52 | if (echoBack) { |
oks486 | 0:43cce7b453d0 | 53 | while(!readable()); |
oks486 | 0:43cce7b453d0 | 54 | readSerial(); |
oks486 | 0:43cce7b453d0 | 55 | } |
oks486 | 0:43cce7b453d0 | 56 | } |
oks486 | 0:43cce7b453d0 | 57 | } |
oks486 | 0:43cce7b453d0 | 58 | |
oks486 | 0:43cce7b453d0 | 59 | |
oks486 | 0:43cce7b453d0 | 60 | int UartIspBase::isRecieveStringMatch(const char* checkString) { |
oks486 | 0:43cce7b453d0 | 61 | int length = strlen(checkString); |
oks486 | 0:43cce7b453d0 | 62 | |
oks486 | 0:43cce7b453d0 | 63 | for(int i = 0; i < length; i++) { |
oks486 | 0:43cce7b453d0 | 64 | char b = readSerial(); |
oks486 | 0:43cce7b453d0 | 65 | if (b != *(checkString+i)) { |
oks486 | 0:43cce7b453d0 | 66 | return 0; // Not matched |
oks486 | 0:43cce7b453d0 | 67 | } |
oks486 | 0:43cce7b453d0 | 68 | } |
oks486 | 0:43cce7b453d0 | 69 | |
oks486 | 0:43cce7b453d0 | 70 | return 1; // Matched |
oks486 | 0:43cce7b453d0 | 71 | } |
oks486 | 0:43cce7b453d0 | 72 | |
oks486 | 0:43cce7b453d0 | 73 | |
oks486 | 0:43cce7b453d0 | 74 | int UartIspBase::openIsp(int mcufreq) { |
oks486 | 0:43cce7b453d0 | 75 | // Sequence of synchronization for MCU uart |
oks486 | 0:43cce7b453d0 | 76 | for (int i = 0; i < SYNC_RETRY_NUM; i++) { |
oks486 | 0:43cce7b453d0 | 77 | if (i > 0) { |
oks486 | 0:43cce7b453d0 | 78 | sleep(3000); |
oks486 | 0:43cce7b453d0 | 79 | } |
oks486 | 0:43cce7b453d0 | 80 | // step 1 |
oks486 | 0:43cce7b453d0 | 81 | writeSerial('?'); |
oks486 | 0:43cce7b453d0 | 82 | if (!isRecieveStringMatch("Synchronized\r\n")) { |
oks486 | 0:43cce7b453d0 | 83 | writeString("\n"); |
oks486 | 0:43cce7b453d0 | 84 | continue; |
oks486 | 0:43cce7b453d0 | 85 | } |
oks486 | 0:43cce7b453d0 | 86 | // step 2 |
oks486 | 0:43cce7b453d0 | 87 | writeString("Synchronized\n"); |
oks486 | 0:43cce7b453d0 | 88 | if (!isRecieveStringMatch("OK\r\n")) { |
oks486 | 0:43cce7b453d0 | 89 | writeString("\n"); |
oks486 | 0:43cce7b453d0 | 90 | continue; |
oks486 | 0:43cce7b453d0 | 91 | } |
oks486 | 0:43cce7b453d0 | 92 | // step 3 |
oks486 | 0:43cce7b453d0 | 93 | char str[32]; |
oks486 | 0:43cce7b453d0 | 94 | sprintf(str, "%d\n", mcufreq); |
oks486 | 0:43cce7b453d0 | 95 | writeString(str); |
oks486 | 0:43cce7b453d0 | 96 | if (!isRecieveStringMatch("OK\r\n")) { |
oks486 | 0:43cce7b453d0 | 97 | writeString("\n"); |
oks486 | 0:43cce7b453d0 | 98 | continue; |
oks486 | 0:43cce7b453d0 | 99 | } |
oks486 | 0:43cce7b453d0 | 100 | return RETURN_NORMAL; |
oks486 | 0:43cce7b453d0 | 101 | } |
oks486 | 0:43cce7b453d0 | 102 | // when MCU does not sync |
oks486 | 0:43cce7b453d0 | 103 | return RETURN_FAULT; |
oks486 | 0:43cce7b453d0 | 104 | } |
oks486 | 0:43cce7b453d0 | 105 | |
oks486 | 0:43cce7b453d0 | 106 | |
oks486 | 0:43cce7b453d0 | 107 | int UartIspBase::unlockFlash() { |
oks486 | 0:43cce7b453d0 | 108 | // Unlock Flash Write and Erase |
oks486 | 0:43cce7b453d0 | 109 | writeString("U 23130\n"); |
oks486 | 0:43cce7b453d0 | 110 | if (!isRecieveStringMatch("0\r\n")) { |
oks486 | 0:43cce7b453d0 | 111 | return RETURN_FAULT; |
oks486 | 0:43cce7b453d0 | 112 | } |
oks486 | 0:43cce7b453d0 | 113 | return RETURN_NORMAL; |
oks486 | 0:43cce7b453d0 | 114 | } |
oks486 | 0:43cce7b453d0 | 115 | |
oks486 | 0:43cce7b453d0 | 116 | |
oks486 | 0:43cce7b453d0 | 117 | int UartIspBase::eraseFlash(int startSector, int endSector) { |
oks486 | 0:43cce7b453d0 | 118 | // Prepare command |
oks486 | 0:43cce7b453d0 | 119 | char str[32]; |
oks486 | 0:43cce7b453d0 | 120 | sprintf(str, "P %d %d\n", startSector, endSector); |
oks486 | 0:43cce7b453d0 | 121 | writeString(str); |
oks486 | 0:43cce7b453d0 | 122 | if (!isRecieveStringMatch("0\r\n")) { |
oks486 | 0:43cce7b453d0 | 123 | return RETURN_FAULT; |
oks486 | 0:43cce7b453d0 | 124 | } |
oks486 | 0:43cce7b453d0 | 125 | |
oks486 | 0:43cce7b453d0 | 126 | // Erase command (All sectors) |
oks486 | 0:43cce7b453d0 | 127 | sprintf(str, "E %d %d\n", startSector, endSector); |
oks486 | 0:43cce7b453d0 | 128 | writeString(str); |
oks486 | 0:43cce7b453d0 | 129 | if (!isRecieveStringMatch("0\r\n")) { |
oks486 | 0:43cce7b453d0 | 130 | return RETURN_FAULT; |
oks486 | 0:43cce7b453d0 | 131 | } |
oks486 | 0:43cce7b453d0 | 132 | |
oks486 | 0:43cce7b453d0 | 133 | return RETURN_NORMAL; |
oks486 | 0:43cce7b453d0 | 134 | } |
oks486 | 0:43cce7b453d0 | 135 | |
oks486 | 0:43cce7b453d0 | 136 | |
oks486 | 0:43cce7b453d0 | 137 | int UartIspBase::writeToRam(char buffer[], unsigned int ramAddress, int length) { |
oks486 | 0:43cce7b453d0 | 138 | int normalizeLength = ((length + 2) / 3) * 3; // normalize multiples of 3 |
oks486 | 0:43cce7b453d0 | 139 | unsigned int checksum = 0; |
oks486 | 0:43cce7b453d0 | 140 | unsigned int data3bytes = 0; |
oks486 | 0:43cce7b453d0 | 141 | int bufPos = 0; |
oks486 | 0:43cce7b453d0 | 142 | int lineNum = 0; |
oks486 | 0:43cce7b453d0 | 143 | int lineBytes; |
oks486 | 0:43cce7b453d0 | 144 | char str[32]; |
oks486 | 0:43cce7b453d0 | 145 | |
oks486 | 0:43cce7b453d0 | 146 | // Send W command |
oks486 | 0:43cce7b453d0 | 147 | sprintf(str, "W %d %d\n", ramAddress, length); |
oks486 | 0:43cce7b453d0 | 148 | writeString(str); |
oks486 | 0:43cce7b453d0 | 149 | if (!isRecieveStringMatch("0\r\n")) { |
oks486 | 0:43cce7b453d0 | 150 | writeSerial(0x1B); // send ESC |
oks486 | 0:43cce7b453d0 | 151 | return RETURN_FAULT; |
oks486 | 0:43cce7b453d0 | 152 | } |
oks486 | 0:43cce7b453d0 | 153 | |
oks486 | 0:43cce7b453d0 | 154 | while (bufPos < length) { |
oks486 | 0:43cce7b453d0 | 155 | // the number of sending bytes of a line |
oks486 | 0:43cce7b453d0 | 156 | if (bufPos <= length - UUENCODE_LINE_BYTES) { |
oks486 | 0:43cce7b453d0 | 157 | lineBytes = UUENCODE_LINE_BYTES; |
oks486 | 0:43cce7b453d0 | 158 | writeString(getUuString(lineBytes)); |
oks486 | 0:43cce7b453d0 | 159 | } else { |
oks486 | 0:43cce7b453d0 | 160 | lineBytes = normalizeLength - bufPos; |
oks486 | 0:43cce7b453d0 | 161 | writeString(getUuString(length - bufPos)); |
oks486 | 0:43cce7b453d0 | 162 | } |
oks486 | 0:43cce7b453d0 | 163 | |
oks486 | 0:43cce7b453d0 | 164 | // send data of a line |
oks486 | 0:43cce7b453d0 | 165 | for (int i = 0; i < lineBytes; i++) { |
oks486 | 0:43cce7b453d0 | 166 | unsigned char data; |
oks486 | 0:43cce7b453d0 | 167 | if (bufPos + i < length) { |
oks486 | 0:43cce7b453d0 | 168 | data = buffer[bufPos + i]; |
oks486 | 0:43cce7b453d0 | 169 | } else { |
oks486 | 0:43cce7b453d0 | 170 | data = 0; |
oks486 | 0:43cce7b453d0 | 171 | } |
oks486 | 0:43cce7b453d0 | 172 | checksum += data; |
oks486 | 0:43cce7b453d0 | 173 | |
oks486 | 0:43cce7b453d0 | 174 | // Encode uuencode data and store array |
oks486 | 0:43cce7b453d0 | 175 | if ((i % 3) == 0) { |
oks486 | 0:43cce7b453d0 | 176 | data3bytes = data; |
oks486 | 0:43cce7b453d0 | 177 | } else { |
oks486 | 0:43cce7b453d0 | 178 | data3bytes = (data3bytes << 8) + data; |
oks486 | 0:43cce7b453d0 | 179 | } |
oks486 | 0:43cce7b453d0 | 180 | |
oks486 | 0:43cce7b453d0 | 181 | if ((i % 3) == 2) { |
oks486 | 0:43cce7b453d0 | 182 | writeString(getUuString( (data3bytes >> 18) & 0x3F ) ); |
oks486 | 0:43cce7b453d0 | 183 | writeString(getUuString( (data3bytes >> 12) & 0x3F ) ); |
oks486 | 0:43cce7b453d0 | 184 | writeString(getUuString( (data3bytes >> 6) & 0x3F ) ); |
oks486 | 0:43cce7b453d0 | 185 | writeString(getUuString( (data3bytes) & 0x3F ) ); |
oks486 | 0:43cce7b453d0 | 186 | } |
oks486 | 0:43cce7b453d0 | 187 | } |
oks486 | 0:43cce7b453d0 | 188 | writeString("\n"); |
oks486 | 0:43cce7b453d0 | 189 | lineNum++; |
oks486 | 0:43cce7b453d0 | 190 | bufPos += UUENCODE_LINE_BYTES; |
oks486 | 0:43cce7b453d0 | 191 | |
oks486 | 0:43cce7b453d0 | 192 | if (bufPos >= length || (lineNum % 20) == 0) { |
oks486 | 0:43cce7b453d0 | 193 | sprintf(str, "%d\n", checksum); |
oks486 | 0:43cce7b453d0 | 194 | writeString(str); |
oks486 | 0:43cce7b453d0 | 195 | if (echoBack) { // workaround for response (UART ISP bug?) |
oks486 | 0:43cce7b453d0 | 196 | if (!isRecieveStringMatch("OK\r\n")) { |
oks486 | 0:43cce7b453d0 | 197 | writeSerial(0x1B); // send ESC |
oks486 | 0:43cce7b453d0 | 198 | return RETURN_FAULT; |
oks486 | 0:43cce7b453d0 | 199 | } |
oks486 | 0:43cce7b453d0 | 200 | } else { |
oks486 | 0:43cce7b453d0 | 201 | if (!isRecieveStringMatch("0\r\n")) { |
oks486 | 0:43cce7b453d0 | 202 | writeSerial(0x1B); // send ESC |
oks486 | 0:43cce7b453d0 | 203 | return RETURN_FAULT; |
oks486 | 0:43cce7b453d0 | 204 | } |
oks486 | 0:43cce7b453d0 | 205 | } |
oks486 | 0:43cce7b453d0 | 206 | checksum = 0; |
oks486 | 0:43cce7b453d0 | 207 | } |
oks486 | 0:43cce7b453d0 | 208 | } |
oks486 | 0:43cce7b453d0 | 209 | |
oks486 | 0:43cce7b453d0 | 210 | return RETURN_NORMAL; |
oks486 | 0:43cce7b453d0 | 211 | } |
oks486 | 0:43cce7b453d0 | 212 | |
oks486 | 0:43cce7b453d0 | 213 | |
oks486 | 0:43cce7b453d0 | 214 | int UartIspBase::prepareFlash(int startSector, int endSector) { |
oks486 | 0:43cce7b453d0 | 215 | // Send P command |
oks486 | 0:43cce7b453d0 | 216 | char str[32]; |
oks486 | 0:43cce7b453d0 | 217 | sprintf(str, "P %d %d\n", startSector, endSector); |
oks486 | 0:43cce7b453d0 | 218 | writeString(str); |
oks486 | 0:43cce7b453d0 | 219 | |
oks486 | 0:43cce7b453d0 | 220 | if (!isRecieveStringMatch("0\r\n")) { |
oks486 | 0:43cce7b453d0 | 221 | writeSerial(0x1B); // send ESC |
oks486 | 0:43cce7b453d0 | 222 | return RETURN_FAULT; |
oks486 | 0:43cce7b453d0 | 223 | } |
oks486 | 0:43cce7b453d0 | 224 | return RETURN_NORMAL; |
oks486 | 0:43cce7b453d0 | 225 | } |
oks486 | 0:43cce7b453d0 | 226 | |
oks486 | 0:43cce7b453d0 | 227 | |
oks486 | 0:43cce7b453d0 | 228 | int UartIspBase::copyToFlash(unsigned int flashAddress, unsigned int ramAddress, int length) { |
oks486 | 0:43cce7b453d0 | 229 | // Copy program data from RAM to Flash |
oks486 | 0:43cce7b453d0 | 230 | char str[32]; |
oks486 | 0:43cce7b453d0 | 231 | sprintf(str, "C %d %d %d\n", flashAddress, ramAddress, length); |
oks486 | 0:43cce7b453d0 | 232 | writeString(str); |
oks486 | 0:43cce7b453d0 | 233 | |
oks486 | 0:43cce7b453d0 | 234 | if (!isRecieveStringMatch("0\r\n")) { |
oks486 | 0:43cce7b453d0 | 235 | writeSerial(0x1B); // send ESC |
oks486 | 0:43cce7b453d0 | 236 | return RETURN_FAULT; |
oks486 | 0:43cce7b453d0 | 237 | } |
oks486 | 0:43cce7b453d0 | 238 | |
oks486 | 0:43cce7b453d0 | 239 | // Verify RAM and Flash data |
oks486 | 0:43cce7b453d0 | 240 | if (flashAddress < 64) { |
oks486 | 0:43cce7b453d0 | 241 | sprintf(str, "M 64 %d %d\n", ramAddress + 64, length - 64); |
oks486 | 0:43cce7b453d0 | 242 | } else { |
oks486 | 0:43cce7b453d0 | 243 | sprintf(str, "M %d %d %d\n", flashAddress, ramAddress, length); |
oks486 | 0:43cce7b453d0 | 244 | } |
oks486 | 0:43cce7b453d0 | 245 | writeString(str); |
oks486 | 0:43cce7b453d0 | 246 | |
oks486 | 0:43cce7b453d0 | 247 | if (!isRecieveStringMatch("0\r\n")) { |
oks486 | 0:43cce7b453d0 | 248 | writeSerial(0x1B); // send ESC |
oks486 | 0:43cce7b453d0 | 249 | return RETURN_FAULT; |
oks486 | 0:43cce7b453d0 | 250 | } |
oks486 | 0:43cce7b453d0 | 251 | |
oks486 | 0:43cce7b453d0 | 252 | return RETURN_NORMAL; |
oks486 | 0:43cce7b453d0 | 253 | } |