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

Dependencies:   mbed

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

UartIsp/UartIsp.cpp

Committer:
oks486
Date:
2016-08-21
Revision:
2:daf6c4719496
Parent:
1:11f73f269fdc

File content as of revision 2:daf6c4719496:

#include "mbed.h"
#include "UartIsp.h"
#include "FatfsIjfwConfigurable.h"

// Target MCU definitions
const unsigned int RAM_BASE_ADDRESS = 268435456+1024;   // address = 0x10000000 + 0x400
const int SECTOR_NUM = 8;
const int SECTOR_SIZE = 4096;
const int CHUNK_SIZE = 1024;                            // must be multiples of 512
const int BUF_SIZE = 512;                               // CHUNK_SIZE / 2^n
const int MCU_FREQ = 48000;


UartIsp::UartIsp(RawSerial* _serial, FatfsIjfwConfigurable* _fs)
    : serial(_serial), fs(_fs) {
}


UartIsp::~UartIsp() {

}


void UartIsp::writeSerial(const char val) {
    serial->putc(val);
}


char UartIsp::readSerial() {
    return (char)serial->getc();
}


int UartIsp::readable() {
    return serial->readable();
}


void UartIsp::sleep(int msec) {
    wait_ms((double)msec);
}


UartIsp::ISP_RESULT UartIsp::runUartIsp(const char* filename) {
    // Open bin file
    fs->mount();
    int res = fs->open(filename, MODE_RO);
    if (res != FR_OK) {
        return ERR_FILE_OPEN;
    }
    
    buffer = new char[BUF_SIZE];

    // Clear Rx Buffer
    while(readable()) {
        readSerial();
    }

    // Open ISP mode and Synchronization of serial port
    if (!openIsp(MCU_FREQ)) {
        return ERR_SYNC_MCU;
    }
    // Disable echo back
//    disableEchoBack();

    // Unlock Flash
    unlockFlash();
    // Erase all area
    if (!eraseFlash(0, 7)) {
        return ERR_UNLOCK_FLASH;
    }
    wait_ms(10);

    // Get bin data length
    int binDataLength = fs->filesize();
    if (binDataLength < 0) {
        return ERR_FILE_READ;
    }

    // Flash writting process
    int finishWrite = 0;
    int sector = 1;

    while (!finishWrite) {
        // Adjust sector size
        int sectorStart = SECTOR_SIZE * sector;

        int dataLength;
        unsigned int readAddress;

        for (int sectorPos = 0; sectorPos < SECTOR_SIZE; sectorPos += CHUNK_SIZE) {
            for (int chunkPos = 0; chunkPos < CHUNK_SIZE; chunkPos += BUF_SIZE) {

                // Calculate data length to write
                dataLength = BUF_SIZE;
                readAddress = sectorStart + sectorPos + chunkPos;
                if (readAddress + BUF_SIZE > binDataLength) {
                    dataLength = binDataLength - readAddress;
                }
                if (dataLength <= 0) {
                    continue;
                }

                // Move to file offset to read 
                if (fs->lseek(readAddress) != FR_OK) {
                    return ERR_FILE_READ;
                }
                // Read memory card and store buffer
                if (fs->read(buffer, dataLength) != dataLength) {
                    return ERR_FILE_READ;
                }

                // Calculate checksum of interrupt vector area
                if (sector == 0 && sectorPos == 0 && chunkPos < BUF_SIZE) {
                    buffer[0x1C] = 0;
                    buffer[0x1C + 1] = 0;
                    buffer[0x1C + 2] = 0;
                    buffer[0x1C + 3] = 0;

                    int checksum = 0;
                    for (int i = 0; i < 8; i++) {
                        checksum += buffer[i*4];
                        checksum += buffer[i*4 + 1] << 8;
                        checksum += buffer[i*4 + 2] << 16;
                        checksum += buffer[i*4 + 3] << 24;
                    }
                    checksum = 0 - checksum;

                    buffer[0x1C] = checksum & 0xFF;
                    buffer[0x1C + 1] = (checksum >> 8) & 0xFF;
                    buffer[0x1C + 2] = (checksum >> 16) & 0xFF;
                    buffer[0x1C + 3] = (checksum >> 24) & 0xFF;
                }

                // Write to RAM
                unsigned int ramAddress = RAM_BASE_ADDRESS + (unsigned int)chunkPos;
                if (!writeToRam(buffer, ramAddress, dataLength)) {
                    return ERR_WRITE_TO_RAM;
                }
            }

            // Copy from RAM to Flash
            prepareFlash(sector, sector);

            unsigned int flashAddress = sectorStart + sectorPos;
            if (!copyToFlash(flashAddress, RAM_BASE_ADDRESS, CHUNK_SIZE)) {
                return ERR_COPY_TO_FLASH;
            }
        }

        // sector access order => 1, 2, ... , 6, 7, 0
        if (sector >= SECTOR_NUM - 1) {
            sector = 0;
        } else if (dataLength < BUF_SIZE) {
            sector = 0;
        } else if (sector == 0) {
            finishWrite = 1;
            wait_ms(300);
        } else {
            sector++;
        }
    }
    
    // BIN file close and delete
    fs->close();
    fs->deleteFirmFile(filename);
    delete [] buffer;

    return NOERROR;
}