IJFW - IchigoJamのBASICプログラムをメモリカード(MMCまたは互換カード)に保存したり読み出したりできるプログラム。メモリカードにファームウェアのファイルを置くだけで、電源ON時に自動的に書き換える機能も搭載(一応こちらがメイン)。LPC1114FN28専用。
参考URL http://www.cyberchabudai.org/index.php/entry?tag=IJFW
Diff: UartIsp/UartIspBase.cpp
- Revision:
- 0:43cce7b453d0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UartIsp/UartIspBase.cpp Thu Apr 28 11:23:24 2016 +0000 @@ -0,0 +1,253 @@ +#include "UartIspBase.h" +#include <stdio.h> +#include <string.h> + +const int SYNC_RETRY_NUM = 3; +const int UUENCODE_LINE_BYTES = 45; // must be multiples of 3 +const int RETURN_NORMAL = 1; +const int RETURN_FAULT = 0; + + +UartIspBase::UartIspBase() { + // echoback setting + echoBack = 1; + + // Generate UUEncode Table + uuCharTable[0] = 0x60; + for (int i = 1; i < 64; i++) { + uuCharTable[i] = i + 32; + } +} + + +UartIspBase::~UartIspBase() { + +} + + +char UartIspBase::getUuString(int i) { + return uuCharTable[i % 64]; +} + + +void UartIspBase::disableEchoBack() { + writeString("A 0\n"); + echoBack = 0; +} + + +void UartIspBase::writeString(const char val) { + writeSerial(val); + if (echoBack) { + readSerial(); + } +} + + +void UartIspBase::writeString(const char* str) { + int length = strlen(str); + for (int i = 0; i < length; i++) { + writeSerial(*(str+i)); + + if (echoBack) { + while(!readable()); + readSerial(); + } + } +} + + +int UartIspBase::isRecieveStringMatch(const char* checkString) { + int length = strlen(checkString); + + for(int i = 0; i < length; i++) { + char b = readSerial(); + if (b != *(checkString+i)) { + return 0; // Not matched + } + } + + return 1; // Matched +} + + +int UartIspBase::openIsp(int mcufreq) { + // Sequence of synchronization for MCU uart + for (int i = 0; i < SYNC_RETRY_NUM; i++) { + if (i > 0) { + sleep(3000); + } + // step 1 + writeSerial('?'); + if (!isRecieveStringMatch("Synchronized\r\n")) { + writeString("\n"); + continue; + } + // step 2 + writeString("Synchronized\n"); + if (!isRecieveStringMatch("OK\r\n")) { + writeString("\n"); + continue; + } + // step 3 + char str[32]; + sprintf(str, "%d\n", mcufreq); + writeString(str); + if (!isRecieveStringMatch("OK\r\n")) { + writeString("\n"); + continue; + } + return RETURN_NORMAL; + } + // when MCU does not sync + return RETURN_FAULT; +} + + +int UartIspBase::unlockFlash() { + // Unlock Flash Write and Erase + writeString("U 23130\n"); + if (!isRecieveStringMatch("0\r\n")) { + return RETURN_FAULT; + } + return RETURN_NORMAL; +} + + +int UartIspBase::eraseFlash(int startSector, int endSector) { + // Prepare command + char str[32]; + sprintf(str, "P %d %d\n", startSector, endSector); + writeString(str); + if (!isRecieveStringMatch("0\r\n")) { + return RETURN_FAULT; + } + + // Erase command (All sectors) + sprintf(str, "E %d %d\n", startSector, endSector); + writeString(str); + if (!isRecieveStringMatch("0\r\n")) { + return RETURN_FAULT; + } + + return RETURN_NORMAL; +} + + +int UartIspBase::writeToRam(char buffer[], unsigned int ramAddress, int length) { + int normalizeLength = ((length + 2) / 3) * 3; // normalize multiples of 3 + unsigned int checksum = 0; + unsigned int data3bytes = 0; + int bufPos = 0; + int lineNum = 0; + int lineBytes; + char str[32]; + + // Send W command + sprintf(str, "W %d %d\n", ramAddress, length); + writeString(str); + if (!isRecieveStringMatch("0\r\n")) { + writeSerial(0x1B); // send ESC + return RETURN_FAULT; + } + + while (bufPos < length) { + // the number of sending bytes of a line + if (bufPos <= length - UUENCODE_LINE_BYTES) { + lineBytes = UUENCODE_LINE_BYTES; + writeString(getUuString(lineBytes)); + } else { + lineBytes = normalizeLength - bufPos; + writeString(getUuString(length - bufPos)); + } + + // send data of a line + for (int i = 0; i < lineBytes; i++) { + unsigned char data; + if (bufPos + i < length) { + data = buffer[bufPos + i]; + } else { + data = 0; + } + checksum += data; + + // Encode uuencode data and store array + if ((i % 3) == 0) { + data3bytes = data; + } else { + data3bytes = (data3bytes << 8) + data; + } + + if ((i % 3) == 2) { + writeString(getUuString( (data3bytes >> 18) & 0x3F ) ); + writeString(getUuString( (data3bytes >> 12) & 0x3F ) ); + writeString(getUuString( (data3bytes >> 6) & 0x3F ) ); + writeString(getUuString( (data3bytes) & 0x3F ) ); + } + } + writeString("\n"); + lineNum++; + bufPos += UUENCODE_LINE_BYTES; + + if (bufPos >= length || (lineNum % 20) == 0) { + sprintf(str, "%d\n", checksum); + writeString(str); + if (echoBack) { // workaround for response (UART ISP bug?) + if (!isRecieveStringMatch("OK\r\n")) { + writeSerial(0x1B); // send ESC + return RETURN_FAULT; + } + } else { + if (!isRecieveStringMatch("0\r\n")) { + writeSerial(0x1B); // send ESC + return RETURN_FAULT; + } + } + checksum = 0; + } + } + + return RETURN_NORMAL; +} + + +int UartIspBase::prepareFlash(int startSector, int endSector) { + // Send P command + char str[32]; + sprintf(str, "P %d %d\n", startSector, endSector); + writeString(str); + + if (!isRecieveStringMatch("0\r\n")) { + writeSerial(0x1B); // send ESC + return RETURN_FAULT; + } + return RETURN_NORMAL; +} + + +int UartIspBase::copyToFlash(unsigned int flashAddress, unsigned int ramAddress, int length) { + // Copy program data from RAM to Flash + char str[32]; + sprintf(str, "C %d %d %d\n", flashAddress, ramAddress, length); + writeString(str); + + if (!isRecieveStringMatch("0\r\n")) { + writeSerial(0x1B); // send ESC + return RETURN_FAULT; + } + + // Verify RAM and Flash data + if (flashAddress < 64) { + sprintf(str, "M 64 %d %d\n", ramAddress + 64, length - 64); + } else { + sprintf(str, "M %d %d %d\n", flashAddress, ramAddress, length); + } + writeString(str); + + if (!isRecieveStringMatch("0\r\n")) { + writeSerial(0x1B); // send ESC + return RETURN_FAULT; + } + + return RETURN_NORMAL; +}