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