IJFW - IchigoJamのBASICプログラムをメモリカード(MMCまたは互換カード)に保存したり読み出したりできるプログラム。メモリカードにファームウェアのファイルを置くだけで、電源ON時に自動的に書き換える機能も搭載(一応こちらがメイン)。LPC1114FN28専用。
参考URL http://www.cyberchabudai.org/index.php/entry?tag=IJFW
Diff: UartIsp/UartIsp.cpp
- Revision:
- 0:43cce7b453d0
- Child:
- 1:11f73f269fdc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UartIsp/UartIsp.cpp Thu Apr 28 11:23:24 2016 +0000 @@ -0,0 +1,170 @@ +#include "mbed.h" +#include "UartIsp.h" +#include "FatfsIJFW.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, FatfsIJFW* _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->remove(filename); + delete [] buffer; + + return NOERROR; +}