iSDIO library for FlashAir
Dependents: FlashAir_iSDIO_sample FlashAir_iSDIO_16seg_ADT7410_step1 FlashAir_iSDIO_16seg_ADT7410 FlashAir_iSDIO_sample_OS5_ ... more
iSDIO.cpp
- Committer:
- hogejun
- Date:
- 2019-01-19
- Revision:
- 2:b8b33621e7fe
- Parent:
- 1:dc888b9028cf
File content as of revision 2:b8b33621e7fe:
/* mbed SD iSDIO Library * Copyright (C) 2018 by Junichi SHIBA, PIAX Inc. * * Arduino Sdio Library * Copyright (C) 2014 by Munehiro Doi * * This file is an SD extension of the Arduino Sd2Card Library * Copyright (C) 2009 by William Greiman * * This Library is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This Library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with the Arduino Sd2Card Library. If not, see * <http://www.gnu.org/licenses/>. */ #include "mbed.h" #include "iSDIO.h" //------------------------------------------------------------------------------ // SD extension commands /** EXTENSION READ - Extension Register Read Command (Single Block) */ uint8_t const CMD48 = 0X30; /** EXTENSION WRITE - Extension Register Write Command (Single Block) */ uint8_t const CMD49 = 0X31; /** EXTENSION READ - Extension Register Read Command (Multi Block) */ uint8_t const CMD17 = 17; /** EXTENSION READ - Extension Register Read Command (Multi Block) */ uint8_t const CMD24 = 24; //------------------------------------------------------------------------------ // SD extension error codes. /** card returned an error response for CMD48 (read extension block) */ uint8_t const SD_CARD_ERROR_CMD48 = 0X80; /** card returned an error response for CMD49 (write extension block) */ uint8_t const SD_CARD_ERROR_CMD49 = 0X81; //------------------------------------------------------------------------------ iSDIO::iSDIO(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name, Serial* console) : SDFileSystem(mosi, miso, sclk, cs, name) { instance = this; _console = console; sequenceId = 0; if (_console != NULL) _console->printf("new iSDIO\n"); } iSDIO::~iSDIO(void) {} iSDIO* iSDIO::instance = 0; iSDIO* iSDIO::getInstance() { return iSDIO::instance; } uint32_t iSDIO::getSequenceId() { if (_console != NULL) _console->printf("sequenceId: %d\n", sequenceId); return sequenceId; } uint32_t iSDIO::getNextSequenceId() { sequenceId++; if (_console != NULL) _console->printf("Next sequenceId: %d\n", sequenceId); return sequenceId; } uint8_t const DATA_START_BLOCK = 0XFE ; uint8_t const DATA_RES_MASK = 0X1F ; uint8_t const DATA_RES_ACCEPTED = 0X05 ; //------------------------------------------------------------------------------ /** Perform Extention Read. */ uint8_t iSDIO::readExt(uint32_t arg, uint8_t* dst, uint16_t count) { uint16_t i; // send command and argument. if (_cmd(CMD48, arg) && _cmd(CMD17, arg)) { error("SD_CARD_ERROR_CMD48"); _cs = 1; return false; } _cs = 0; // wait for start block token. while (_spi.write(0xFF) == 0xFF); // receive data for (i = 0; i < count; ++i) { dst[i] = _spi.write(0xFF); } // skip dummy bytes and 16-bit crc. for (; i < 514; ++i) { _spi.write(0xFF); } _cs = 1; _spi.write(0xFF); // dummy clock to force FlashAir finish the command. return true; } //------------------------------------------------------------------------------ /** Perform Extention Write. */ uint8_t iSDIO::writeExt(uint32_t arg, const uint8_t* src, uint16_t count) { uint16_t i; uint8_t status; // send command and argument. if (_cmd(CMD49, arg) && _cmd(CMD24, arg)) { error("SD_CARD_ERROR_CMD49"); _cs = 1; return false; } _cs = 0; // send start block token. _spi.write(DATA_START_BLOCK); //////_spi.write(0xFE); // send data for (i = 0; i < count; ++i) { _spi.write(src[i]); } // send dummy bytes until 512 bytes. for (; i < 512; ++i) { _spi.write(0xFF); } // dummy 16-bit crc _spi.write(0xFF); _spi.write(0xFF); // wait a data response token status = _spi.write(0xFF); if ((status & DATA_RES_MASK) != DATA_RES_ACCEPTED) { //////if ((status & 0x1F) != 0x05) { error("SD_CARD_ERROR_WRITE"); _cs = 1; return false; } // wait for flash programming to complete while (_spi.write(0xFF) == 0); _cs = 1; return true; } //------------------------------------------------------------------------------ /** * Read a 512 byte data port in an extension register space. * * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. */ uint8_t iSDIO::readExtDataPort(uint8_t mio, uint8_t func, uint16_t addr, uint8_t* dst) { uint32_t arg = (((uint32_t)mio & 0x1) << 31) | (mio ? (((uint32_t)func & 0x7) << 28) : (((uint32_t)func & 0xF) << 27)) | (((uint32_t)addr & 0x1FE00) << 9); return readExt(arg, dst, 512); } //------------------------------------------------------------------------------ /** * Read an extension register space. * * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. */ uint8_t iSDIO::readExtMemory(uint8_t mio, uint8_t func, uint32_t addr, uint16_t count, uint8_t* dst) { uint32_t offset = addr & 0x1FF; if (offset + count > 512) count = 512 - offset; if (count == 0) return true; uint32_t arg = (((uint32_t)mio & 0x1) << 31) | (mio ? (((uint32_t)func & 0x7) << 28) : (((uint32_t)func & 0xF) << 27)) | ((addr & 0x1FFFF) << 9) | ((count - 1) & 0x1FF); return readExt(arg, dst, count); } //------------------------------------------------------------------------------ /** * Write a 512 byte data port into an extension register space. * * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. */ uint8_t iSDIO::writeExtDataPort(uint8_t mio, uint8_t func, uint16_t addr, const uint8_t* src) { uint32_t arg = (((uint32_t)mio & 0x1) << 31) | (mio ? (((uint32_t)func & 0x7) << 28) : (((uint32_t)func & 0xF) << 27)) | (((uint32_t)addr & 0x1FE00) << 9); if (_console != NULL) _console->printf("arg = %08x\n", arg); return writeExt(arg, src, 512); } //------------------------------------------------------------------------------ /** * Write an extension register space. * * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. */ uint8_t iSDIO::writeExtMemory(uint8_t mio, uint8_t func, uint32_t addr, uint16_t count, const uint8_t* src) { uint32_t arg = (((uint32_t)mio & 0x1) << 31) | (mio ? (((uint32_t)func & 0x7) << 28) : (((uint32_t)func & 0xF) << 27)) | ((addr & 0x1FFFF) << 9) | ((count - 1) & 0x1FF); if (_console != NULL) { _console->printf("writeExtMemory: "); _console->printf(" addr: %08x\n", addr); _console->printf(" src: "); } printHex((uint8_t*)src, (uint32_t)count); if (_console != NULL) _console->printf(" count: %d\n", count); return writeExt(arg, src, count); } //------------------------------------------------------------------------------ /** * Writes a byte-data with mask into an extension register space. * * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. */ uint8_t iSDIO::writeExtMask(uint8_t mio, uint8_t func, uint32_t addr, uint8_t mask, const uint8_t* src) { uint32_t arg = (((uint32_t)mio & 0x1) << 31) | (mio ? (((uint32_t)func & 0x7) << 28) : (((uint32_t)func & 0xF) << 27)) | (0x1 << 26) | ((addr & 0x1FFFF) << 9) | mask; return writeExt(arg, src, 1); } uint8_t iSDIO::waitResponse(uint32_t sequenceId) { uint8_t buffer[ISDIO_STATUS_QUEUE_SIZE]; if(_console != NULL) _console->printf("\nWaiting response "); uint8_t prev = 0xFF; for (int i = 0; i < 20; ++i) { memset(buffer, 0, ISDIO_STATUS_QUEUE_SIZE); // Read command response status. if (!readExtMemory(MIO_IO, FUNC1, ISDIO_STATUS_QUEUE, ISDIO_STATUS_QUEUE_SIZE, buffer)) { return false; } uint8_t resp = get_u8(buffer + 8); if (sequenceId == get_u32(buffer + 4)) { if (prev != resp) { switch (resp) { case 0x00: if (_console != NULL) _console->printf("\n Initial"); break; case 0x01: if (_console != NULL) _console->printf("\n Command Processing"); break; case 0x02: if (_console != NULL) _console->printf("\n Command Rejected"); return false; case 0x03: if (_console != NULL) _console->printf("\n Process Succeeded"); return true; case 0x04: if (_console != NULL) _console->printf("\n Process Terminated"); return false; default: if (_console != NULL) { _console->printf("\n Process Failed "); _console->printf("%x", resp); } return false; } prev = resp; } } if (_console != NULL) _console->printf("."); wait_ms(1000); } return false; } void iSDIO::printByte(uint8_t value) { if (_console != NULL) { _console->printf("%x", value >> 4); _console->printf("%x", value & 0xF); } } void iSDIO::printBytes(uint8_t* p, uint32_t len) { for (int i = 0; i < len; ++i) { printByte(p[i]); } } void iSDIO::printHex(uint8_t* p, uint32_t len) { int i = 0; while (i < len) { if ((i & 0xf) == 0) { if (_console != NULL) _console->printf("\n"); printByte(i >> 4); if (_console != NULL) _console->printf(": "); } printByte(*p++); i++; } if (_console != NULL) _console->printf("\n"); }