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

Dependencies:   mbed

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

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