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

Dependencies:   mbed

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

Revision:
0:43cce7b453d0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FatfsIJFW/FatfsIJFW.cpp	Thu Apr 28 11:23:24 2016 +0000
@@ -0,0 +1,425 @@
+#include "mbed.h"
+#include "ff.h"
+#include "FatfsIJFW.h"
+
+
+// Command of memory card
+const BYTE CMD0 = 0;			// GO_IDLE_STATE
+const BYTE CMD1 = 1;			// SEND_OP_COND
+const BYTE ACMD41 = 0x80+41;	// SEND_OP_COND
+const BYTE CMD8 = 8;			// SEND_IF_COND
+const BYTE CMD12 = 12;			// STOP_TRANSMISSION
+const BYTE CMD16 = 16;			// SET_BLOCKLEN
+const BYTE CMD17 = 17;			// READ_SINGLE_BLOCK
+const BYTE CMD18 = 18;			// READ_MULTIPLE_BLOCK
+const BYTE ACMD23 = 0x80+23;	// SET_WR_BLK_ERASE_COUNT
+const BYTE CMD24 = 24;			// WRITE_BLOCK
+const BYTE CMD25 = 25;			// WRITE_MULTIPLE_BLOCK
+const BYTE CMD55 = 55;			// APP_CMD
+const BYTE CMD58 = 58;			// READ_OCR
+
+// Card type flag
+int CardType;
+
+// Extern to diskio.cpp
+extern FatfsIJFW* _fatfs;
+
+
+FatfsIJFW::FatfsIJFW(SPI* _spi, DigitalOut* _cs) : spi(_spi), cs(_cs) {
+	_fatfs = this;
+	Stat = 0;
+	spi->format(8, 0);
+	f_mount(NULL, "", 0);
+}
+
+
+int FatfsIJFW::mount() {
+	Stat = 0;
+	FRESULT res = f_mount(&fs, "", 1);
+	return (int)res;
+}
+
+
+int FatfsIJFW::open(const char* name, const FileMode mode) {
+	BYTE flags;
+
+	if (mode == MODE_WR) {
+		// Write and Read
+		flags = FA_OPEN_EXISTING | FA_READ | FA_WRITE;
+	} else if (mode == MODE_RO) {
+		// Read Only
+		flags = FA_OPEN_EXISTING | FA_READ;
+	} else if (mode == MODE_APPEND) {
+		// Append write
+		flags = FA_OPEN_ALWAYS | FA_WRITE;
+	} else if (mode == MODE_OVERWRITE) {
+		// Overwrite
+		flags = FA_CREATE_ALWAYS | FA_WRITE;
+	}
+
+    FRESULT res = f_open(&file, name, flags);
+
+	if (mode == MODE_APPEND) {
+		f_lseek(&file, f_size(&file));
+	}
+	
+	return (int)res;
+}
+
+
+int FatfsIJFW::close() {
+	FRESULT res = f_close(&file);
+	return (int)res;
+}
+
+
+int FatfsIJFW::remove(const char* filename) {
+	FRESULT res = f_unlink(filename);
+	return (int)res;
+}
+
+
+int FatfsIJFW::mkdir(const char* filename) {
+	FRESULT res = f_mkdir(filename);
+	return (int)res;
+}
+
+
+int FatfsIJFW::read(char* buf, const int length) {
+	UINT br;
+	f_read(&file, buf, (UINT)length, &br);
+	return (int)br;
+}
+
+
+int FatfsIJFW::write(const char* buf, const int length) {
+	UINT br;
+	f_write(&file, buf, (UINT)length, &br);
+	return (int)br;
+}
+
+
+int FatfsIJFW::lseek(int pos) {
+	return (int)f_lseek(&file, (DWORD)pos);
+}
+
+
+int FatfsIJFW::filesize() {
+	return (int)f_size(&file);
+}
+
+
+void FatfsIJFW::timerproc() {
+	if (timerCount) {
+		timerCount--;
+	}
+}
+
+
+void FatfsIJFW::deselect() {
+	cs->write(1);
+	spi->write(0xFF);
+}
+
+
+int FatfsIJFW::select() {
+	cs->write(0);
+	spi->write(0xFF);
+
+	// Wait for card is ready
+	if (waitReady(500)) {
+		return 1;
+	}
+
+	// Timerout
+	deselect();
+	return 0;
+}
+
+
+int FatfsIJFW::waitReady(int wait) {
+	BYTE res;
+
+	timerCount = wait;
+	do {
+		res = spi->write(0xFF);
+	} while (res != 0xFF && timerCount);
+
+	return (res == 0xFF);
+}
+
+
+char FatfsIJFW::sendCommand(BYTE cmd, DWORD arg) {
+	char res;
+
+	// cmd is ACMD<n>
+	if (cmd & 0x80) {
+		cmd &= 0x7F;
+		res = sendCommand(CMD55, 0);
+		if (res > 1) {
+			return res;
+		}
+	}
+
+	// Select the card and wait for ready except to stop multiple block read
+	if (cmd != CMD12) {
+		deselect();
+		if (!select()) {
+			return 0xFF;
+		}
+	}
+
+	// Send command packet
+	spi->write(0x40 | cmd);
+	spi->write((uint8_t)(arg >> 24));
+	spi->write((uint8_t)(arg >> 16));
+	spi->write((uint8_t)(arg >> 8));
+	spi->write((uint8_t)arg);
+
+	// Send CRC packet
+	BYTE crc;
+	if (cmd == CMD0) {
+		crc = 0x95;
+	} else if (cmd == CMD8) {
+		crc = 0x87;
+	} else {
+		crc = 0x01;
+	}
+	spi->write(crc);
+
+	// Diacard following one byte when CMD12
+	if (cmd == CMD12) {
+		spi->write(0xFF);
+	}
+
+	// Wait for response
+	for (int i = 0; i < 10; i++) {
+		res = spi->write(0xFF);
+		if (!(res & 0x80)) {
+			break;
+		}
+	}
+
+	return res;
+}
+
+
+int FatfsIJFW::rcvDataBlock(BYTE *buff, UINT btr) {
+	BYTE token;
+	timerCount = 200;
+
+	do {
+		token = spi->write(0xFF);
+	} while ((token == 0xFF) && timerCount);
+
+	if(token != 0xFE) {		// if invalid token or timeout
+		return 0;
+	}
+
+	// Receive the data block
+	WORD data;
+	spi->format(16, 0);		// 16bit mode
+
+	for (int i = 0; i < btr; i += 2) {
+		data = spi->write(0xFFFF);
+		buff[i] = data >> 8;
+		buff[i + 1] = data;
+	}
+
+	spi->write(0xFFFF);		// CRC
+	spi->format(8, 0);		// 8bit mkode
+
+	return 1;
+}
+
+
+int FatfsIJFW::sendDataBlock(const BYTE *buff, BYTE token) {
+	// Wait for card is ready
+	if (!waitReady(500)) {
+		return 0;		
+	}
+	
+	spi->write(token);
+	if (token != 0xFD) {		// if token is not StopTran
+		// Send the data block
+		spi->format(16, 0);		// 16bit mode
+
+		for (int i = 0; i < 512; i += 2) {
+			unsigned short data = (buff[i] << 8) | buff[i + 1];
+			spi->write(data);
+		}
+		spi->write(0xFFFF);		// CRC
+		spi->format(8, 0);		// 8bit mode
+
+		BYTE res = spi->write(0xFF);	// Receive data response
+		if ((res & 0x1F) != 0x05) {		// if the data packet was not accepted
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+
+DSTATUS FatfsIJFW::disk_initialize(BYTE drv) {
+	if (drv) {		// drive 0 only
+		return STA_NOINIT;
+	}
+
+	// Set spi slow clock
+	spi->frequency(400000);
+    cs->write(1);
+
+	// Send 80 dummy clocks
+    for (int i = 0; i < 10; i++) {
+		spi->write(0xFF);
+	}
+
+	CardType = 0;
+	if (sendCommand(CMD0, 0) == 1) {	// reset card
+		timerCount = 1000;				// Timeout is 1ms
+
+		if (sendCommand(CMD8, 0x1AA) == 1) {
+			// Get value of R7 response
+			int ocr[4];
+			for (int i = 0; i < 4; i++) {
+				ocr[i] = spi->write(0xFF);
+			}
+
+			if (ocr[2] == 0x01 && ocr[3] == 0xAA) {
+				// Wait for end of initialization
+				while (timerCount > 0 && sendCommand(ACMD41, 1UL << 30));
+
+				if (timerCount && sendCommand(CMD58, 0) == 0) {
+					// Check CCS bit
+					for (int i = 0; i < 4; i++) {
+						ocr[i] = spi->write(0xFF);
+					}
+					if (ocr[0] & 0x40) {
+						CardType = 0x04 | 0x08;
+					} else {
+						CardType = 0x04;
+					}
+				}
+			}
+		} else {
+			if (sendCommand(ACMD41, 0) <= 1) {
+				CardType = 0x02;
+				while (timerCount > 0 && sendCommand(ACMD41, 0));	// initialization
+			} else {
+				CardType = 0x01;
+				while (timerCount > 0 && sendCommand(CMD1, 0));	// initialization
+			}
+
+			if (timerCount == 0 || sendCommand(CMD16, 512) != 0) {
+				CardType = 0;
+			}
+		}
+	}
+
+	deselect();
+
+	if (CardType) {
+		spi->frequency(1000000);	// Set spi 1MHz
+		Stat &= ~STA_NOINIT;		// Clear STA_NOINIT flag
+	} else {
+		select();
+		deselect();
+		Stat = STA_NOINIT;
+	}
+
+	return Stat;
+}
+
+
+DSTATUS FatfsIJFW::disk_status(BYTE drv) {
+	return RES_OK;
+}
+
+
+DRESULT FatfsIJFW::disk_read(BYTE drv, BYTE *buff, DWORD sector, UINT count) {
+	// if drive is not ready
+	if (Stat & STA_NOINIT) {
+		return RES_NOTRDY;
+	}
+
+	if (drv || !count) {
+		return RES_PARERR;
+	}
+
+	// if byte address is BA
+	if (!(CardType & 0x08)) {
+		sector *= 512;
+	}
+
+	// Read a single block or multiple blocks
+	BYTE cmd = count > 1 ? CMD18 : CMD17;
+	if (sendCommand(cmd, sector) == 0) {
+		while (count > 0) {
+			if (!rcvDataBlock(buff, 512)) {
+				if (cmd == CMD18) {
+					sendCommand(CMD12, 0);
+				}
+				break;
+			}
+			buff += 512;
+			count--;
+		}
+	}
+	deselect();
+
+	return count ? RES_ERROR : RES_OK;
+}
+
+
+DRESULT FatfsIJFW::disk_write(BYTE drv, const BYTE *buff, DWORD sector, UINT count) {
+	// if drive is not ready
+	if (Stat & STA_NOINIT) {
+		return RES_NOTRDY;
+	}
+	
+	if (drv || !count) {
+		return RES_PARERR;
+	}
+
+	// if byte address is BA
+	if (!(CardType & 0x08)) {
+		sector *= 512;
+	}
+
+	// Write a single block or multiple blocks
+	DRESULT res = RES_ERROR;
+	if (count > 1) {
+		if (CardType & 0x06) {
+			sendCommand(ACMD23, count);		// Send predefine number of sectors
+		}
+		if (sendCommand(CMD25, sector) == 0) {
+			while (count > 0) {
+				if (!sendDataBlock(buff, 0xFC)) {
+					break;
+				}
+				buff += 512;
+				count--;
+			}
+			if (sendDataBlock(0, 0xFD)) {
+				res = RES_OK;
+			}
+		}
+	} else {
+		if (sendCommand(CMD24, sector) == 0) {
+			if (sendDataBlock(buff, 0xFE)) {
+				res = RES_OK;
+			}
+		}
+	}
+	deselect();
+
+	return res;
+}
+
+
+DRESULT FatfsIJFW::disk_ioctl(BYTE drv, BYTE cmd, void* buff) {
+	// ioctl is not supported
+	return RES_ERROR;
+}
+