IJFW - IchigoJamのBASICプログラムをメモリカード(MMCまたは互換カード)に保存したり読み出したりできるプログラム。メモリカードにファームウェアのファイルを置くだけで、電源ON時に自動的に書き換える機能も搭載(一応こちらがメイン)。LPC1114FN28専用。
FatfsIJFW.cpp
00001 #include "mbed.h" 00002 #include "ff.h" 00003 #include "FatfsIJFW.h" 00004 00005 00006 // Command of memory card 00007 const BYTE CMD0 = 0; // GO_IDLE_STATE 00008 const BYTE CMD1 = 1; // SEND_OP_COND 00009 const BYTE ACMD41 = 0x80+41; // SEND_OP_COND 00010 const BYTE CMD8 = 8; // SEND_IF_COND 00011 const BYTE CMD12 = 12; // STOP_TRANSMISSION 00012 const BYTE CMD16 = 16; // SET_BLOCKLEN 00013 const BYTE CMD17 = 17; // READ_SINGLE_BLOCK 00014 const BYTE CMD18 = 18; // READ_MULTIPLE_BLOCK 00015 const BYTE ACMD23 = 0x80+23; // SET_WR_BLK_ERASE_COUNT 00016 const BYTE CMD24 = 24; // WRITE_BLOCK 00017 const BYTE CMD25 = 25; // WRITE_MULTIPLE_BLOCK 00018 const BYTE CMD55 = 55; // APP_CMD 00019 const BYTE CMD58 = 58; // READ_OCR 00020 00021 // Card type flag 00022 int CardType; 00023 00024 // Extern to diskio.cpp 00025 extern FatfsIJFW* _fatfs; 00026 00027 00028 FatfsIJFW::FatfsIJFW(SPI* _spi, DigitalOut* _cs) : spi(_spi), cs(_cs) { 00029 _fatfs = this; 00030 Stat = 0; 00031 spi->format(8, 0); 00032 f_mount(NULL, "", 0); 00033 } 00034 00035 00036 int FatfsIJFW::mount() { 00037 Stat = 0; 00038 FRESULT res = f_mount(&fs, "", 1); 00039 return (int)res; 00040 } 00041 00042 00043 int FatfsIJFW::open(const char* name, const FileMode mode) { 00044 BYTE flags; 00045 00046 if (mode == MODE_WR) { 00047 // Write and Read 00048 flags = FA_OPEN_EXISTING | FA_READ | FA_WRITE; 00049 } else if (mode == MODE_RO) { 00050 // Read Only 00051 flags = FA_OPEN_EXISTING | FA_READ; 00052 } else if (mode == MODE_APPEND) { 00053 // Append write 00054 flags = FA_OPEN_ALWAYS | FA_WRITE; 00055 } else if (mode == MODE_OVERWRITE) { 00056 // Overwrite 00057 flags = FA_CREATE_ALWAYS | FA_WRITE; 00058 } 00059 00060 FRESULT res = f_open(&file, name, flags); 00061 00062 if (mode == MODE_APPEND) { 00063 f_lseek(&file, f_size(&file)); 00064 } 00065 00066 return (int)res; 00067 } 00068 00069 00070 int FatfsIJFW::close() { 00071 FRESULT res = f_close(&file); 00072 return (int)res; 00073 } 00074 00075 00076 int FatfsIJFW::remove(const char* filename) { 00077 FRESULT res = f_unlink(filename); 00078 return (int)res; 00079 } 00080 00081 00082 int FatfsIJFW::mkdir(const char* filename) { 00083 FRESULT res = f_mkdir(filename); 00084 return (int)res; 00085 } 00086 00087 00088 int FatfsIJFW::read(char* buf, const int length) { 00089 UINT br; 00090 f_read(&file, buf, (UINT)length, &br); 00091 return (int)br; 00092 } 00093 00094 00095 int FatfsIJFW::write(const char* buf, const int length) { 00096 UINT br; 00097 f_write(&file, buf, (UINT)length, &br); 00098 return (int)br; 00099 } 00100 00101 00102 int FatfsIJFW::lseek(int pos) { 00103 return (int)f_lseek(&file, (DWORD)pos); 00104 } 00105 00106 00107 int FatfsIJFW::filesize() { 00108 return (int)f_size(&file); 00109 } 00110 00111 00112 void FatfsIJFW::timerproc() { 00113 if (timerCount) { 00114 timerCount--; 00115 } 00116 } 00117 00118 00119 void FatfsIJFW::deselect() { 00120 cs->write(1); 00121 spi->write(0xFF); 00122 } 00123 00124 00125 int FatfsIJFW::select() { 00126 cs->write(0); 00127 spi->write(0xFF); 00128 00129 // Wait for card is ready 00130 if (waitReady(500)) { 00131 return 1; 00132 } 00133 00134 // Timerout 00135 deselect(); 00136 return 0; 00137 } 00138 00139 00140 int FatfsIJFW::waitReady(int wait) { 00141 BYTE res; 00142 00143 timerCount = wait; 00144 do { 00145 res = spi->write(0xFF); 00146 } while (res != 0xFF && timerCount); 00147 00148 return (res == 0xFF); 00149 } 00150 00151 00152 char FatfsIJFW::sendCommand(BYTE cmd, DWORD arg) { 00153 char res; 00154 00155 // cmd is ACMD<n> 00156 if (cmd & 0x80) { 00157 cmd &= 0x7F; 00158 res = sendCommand(CMD55, 0); 00159 if (res > 1) { 00160 return res; 00161 } 00162 } 00163 00164 // Select the card and wait for ready except to stop multiple block read 00165 if (cmd != CMD12) { 00166 deselect(); 00167 if (!select()) { 00168 return 0xFF; 00169 } 00170 } 00171 00172 // Send command packet 00173 spi->write(0x40 | cmd); 00174 spi->write((uint8_t)(arg >> 24)); 00175 spi->write((uint8_t)(arg >> 16)); 00176 spi->write((uint8_t)(arg >> 8)); 00177 spi->write((uint8_t)arg); 00178 00179 // Send CRC packet 00180 BYTE crc; 00181 if (cmd == CMD0) { 00182 crc = 0x95; 00183 } else if (cmd == CMD8) { 00184 crc = 0x87; 00185 } else { 00186 crc = 0x01; 00187 } 00188 spi->write(crc); 00189 00190 // Diacard following one byte when CMD12 00191 if (cmd == CMD12) { 00192 spi->write(0xFF); 00193 } 00194 00195 // Wait for response 00196 for (int i = 0; i < 10; i++) { 00197 res = spi->write(0xFF); 00198 if (!(res & 0x80)) { 00199 break; 00200 } 00201 } 00202 00203 return res; 00204 } 00205 00206 00207 int FatfsIJFW::rcvDataBlock(BYTE *buff, UINT btr) { 00208 BYTE token; 00209 timerCount = 200; 00210 00211 do { 00212 token = spi->write(0xFF); 00213 } while ((token == 0xFF) && timerCount); 00214 00215 if(token != 0xFE) { // if invalid token or timeout 00216 return 0; 00217 } 00218 00219 // Receive the data block 00220 WORD data; 00221 spi->format(16, 0); // 16bit mode 00222 00223 for (int i = 0; i < btr; i += 2) { 00224 data = spi->write(0xFFFF); 00225 buff[i] = data >> 8; 00226 buff[i + 1] = data; 00227 } 00228 00229 spi->write(0xFFFF); // CRC 00230 spi->format(8, 0); // 8bit mkode 00231 00232 return 1; 00233 } 00234 00235 00236 int FatfsIJFW::sendDataBlock(const BYTE *buff, BYTE token) { 00237 // Wait for card is ready 00238 if (!waitReady(500)) { 00239 return 0; 00240 } 00241 00242 spi->write(token); 00243 if (token != 0xFD) { // if token is not StopTran 00244 // Send the data block 00245 spi->format(16, 0); // 16bit mode 00246 00247 for (int i = 0; i < 512; i += 2) { 00248 unsigned short data = (buff[i] << 8) | buff[i + 1]; 00249 spi->write(data); 00250 } 00251 spi->write(0xFFFF); // CRC 00252 spi->format(8, 0); // 8bit mode 00253 00254 BYTE res = spi->write(0xFF); // Receive data response 00255 if ((res & 0x1F) != 0x05) { // if the data packet was not accepted 00256 return 0; 00257 } 00258 } 00259 00260 return 1; 00261 } 00262 00263 00264 DSTATUS FatfsIJFW::disk_initialize(BYTE drv) { 00265 if (drv) { // drive 0 only 00266 return STA_NOINIT; 00267 } 00268 00269 // Set spi slow clock 00270 spi->frequency(400000); 00271 cs->write(1); 00272 00273 // Send 80 dummy clocks 00274 for (int i = 0; i < 10; i++) { 00275 spi->write(0xFF); 00276 } 00277 00278 CardType = 0; 00279 if (sendCommand(CMD0, 0) == 1) { // reset card 00280 timerCount = 1000; // Timeout is 1ms 00281 00282 if (sendCommand(CMD8, 0x1AA) == 1) { 00283 // Get value of R7 response 00284 int ocr[4]; 00285 for (int i = 0; i < 4; i++) { 00286 ocr[i] = spi->write(0xFF); 00287 } 00288 00289 if (ocr[2] == 0x01 && ocr[3] == 0xAA) { 00290 // Wait for end of initialization 00291 while (timerCount > 0 && sendCommand(ACMD41, 1UL << 30)); 00292 00293 if (timerCount && sendCommand(CMD58, 0) == 0) { 00294 // Check CCS bit 00295 for (int i = 0; i < 4; i++) { 00296 ocr[i] = spi->write(0xFF); 00297 } 00298 if (ocr[0] & 0x40) { 00299 CardType = 0x04 | 0x08; 00300 } else { 00301 CardType = 0x04; 00302 } 00303 } 00304 } 00305 } else { 00306 if (sendCommand(ACMD41, 0) <= 1) { 00307 CardType = 0x02; 00308 while (timerCount > 0 && sendCommand(ACMD41, 0)); // initialization 00309 } else { 00310 CardType = 0x01; 00311 while (timerCount > 0 && sendCommand(CMD1, 0)); // initialization 00312 } 00313 00314 if (timerCount == 0 || sendCommand(CMD16, 512) != 0) { 00315 CardType = 0; 00316 } 00317 } 00318 } 00319 00320 deselect(); 00321 00322 if (CardType) { 00323 spi->frequency(1000000); // Set spi 1MHz 00324 Stat &= ~STA_NOINIT; // Clear STA_NOINIT flag 00325 } else { 00326 select(); 00327 deselect(); 00328 Stat = STA_NOINIT; 00329 } 00330 00331 return Stat; 00332 } 00333 00334 00335 DSTATUS FatfsIJFW::disk_status(BYTE drv) { 00336 return RES_OK; 00337 } 00338 00339 00340 DRESULT FatfsIJFW::disk_read(BYTE drv, BYTE *buff, DWORD sector, UINT count) { 00341 // if drive is not ready 00342 if (Stat & STA_NOINIT) { 00343 return RES_NOTRDY; 00344 } 00345 00346 if (drv || !count) { 00347 return RES_PARERR; 00348 } 00349 00350 // if byte address is BA 00351 if (!(CardType & 0x08)) { 00352 sector *= 512; 00353 } 00354 00355 // Read a single block or multiple blocks 00356 BYTE cmd = count > 1 ? CMD18 : CMD17; 00357 if (sendCommand(cmd, sector) == 0) { 00358 while (count > 0) { 00359 if (!rcvDataBlock(buff, 512)) { 00360 if (cmd == CMD18) { 00361 sendCommand(CMD12, 0); 00362 } 00363 break; 00364 } 00365 buff += 512; 00366 count--; 00367 } 00368 } 00369 deselect(); 00370 00371 return count ? RES_ERROR : RES_OK; 00372 } 00373 00374 00375 DRESULT FatfsIJFW::disk_write(BYTE drv, const BYTE *buff, DWORD sector, UINT count) { 00376 // if drive is not ready 00377 if (Stat & STA_NOINIT) { 00378 return RES_NOTRDY; 00379 } 00380 00381 if (drv || !count) { 00382 return RES_PARERR; 00383 } 00384 00385 // if byte address is BA 00386 if (!(CardType & 0x08)) { 00387 sector *= 512; 00388 } 00389 00390 // Write a single block or multiple blocks 00391 DRESULT res = RES_ERROR; 00392 if (count > 1) { 00393 if (CardType & 0x06) { 00394 sendCommand(ACMD23, count); // Send predefine number of sectors 00395 } 00396 if (sendCommand(CMD25, sector) == 0) { 00397 while (count > 0) { 00398 if (!sendDataBlock(buff, 0xFC)) { 00399 break; 00400 } 00401 buff += 512; 00402 count--; 00403 } 00404 if (sendDataBlock(0, 0xFD)) { 00405 res = RES_OK; 00406 } 00407 } 00408 } else { 00409 if (sendCommand(CMD24, sector) == 0) { 00410 if (sendDataBlock(buff, 0xFE)) { 00411 res = RES_OK; 00412 } 00413 } 00414 } 00415 deselect(); 00416 00417 return res; 00418 } 00419 00420 00421 DRESULT FatfsIJFW::disk_ioctl(BYTE drv, BYTE cmd, void* buff) { 00422 // ioctl is not supported 00423 return RES_ERROR; 00424 } 00425
Generated on Sat Jul 16 2022 19:47:26 by 1.7.2