IJFW - IchigoJamのBASICプログラムをメモリカード(MMCまたは互換カード)に保存したり読み出したりできるプログラム。メモリカードにファームウェアのファイルを置くだけで、電源ON時に自動的に書き換える機能も搭載(一応こちらがメイン)。LPC1114FN28専用。
参考URL http://www.cyberchabudai.org/index.php/entry?tag=IJFW
FatfsIJFW/FatfsIJFW.cpp
- Committer:
- oks486
- Date:
- 2016-08-21
- Revision:
- 2:daf6c4719496
- Parent:
- 0:43cce7b453d0
File content as of revision 2:daf6c4719496:
#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; }