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

Dependencies:   mbed

参考URL http://www.cyberchabudai.org/index.php/entry?tag=IJFW

UartIsp/UartIspBase.cpp

Committer:
oks486
Date:
2016-08-21
Revision:
2:daf6c4719496
Parent:
0:43cce7b453d0

File content as of revision 2:daf6c4719496:

#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;
}