iSDIO library for FlashAir
Dependents: FlashAir_iSDIO_sample FlashAir_iSDIO_16seg_ADT7410_step1 FlashAir_iSDIO_16seg_ADT7410 FlashAir_iSDIO_sample_OS5_ ... more
Diff: iSDIO.cpp
- Revision:
- 0:89c6aae3a486
- Child:
- 1:dc888b9028cf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/iSDIO.cpp Thu Aug 23 06:33:32 2018 +0000 @@ -0,0 +1,319 @@ +/* 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; + _console->printf("new iSDIO\n"); +} + +iSDIO::~iSDIO(void) {} + +iSDIO* iSDIO::instance = 0; + +iSDIO* iSDIO::getInstance() +{ + return iSDIO::instance; +} + +uint32_t iSDIO::getSequenceId() +{ + _console->printf("sequenceId: %d\n", sequenceId); + return sequenceId; +} + +uint32_t iSDIO::getNextSequenceId() +{ + sequenceId++; + _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); + _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); + _console->printf("writeExtMemory: "); + _console->printf(" addr: %08x\n", addr); + _console->printf(" src: "); + printHex((uint8_t*)src, (uint32_t)count); + _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]; + + _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: + _console->printf("\n Initial"); + break; + case 0x01: + _console->printf("\n Command Processing"); + break; + case 0x02: + _console->printf("\n Command Rejected"); + return false; + case 0x03: + _console->printf("\n Process Succeeded"); + return true; + case 0x04: + _console->printf("\n Process Terminated"); + return false; + default: + _console->printf("\n Process Failed "); + _console->printf("%x", resp); + return false; + } + prev = resp; + } + } + _console->printf("."); + wait_ms(1000); + } + return false; +} + + + +void iSDIO::printByte(uint8_t value) +{ + _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) { + _console->printf("\n"); + printByte(i >> 4); + _console->printf(": "); + } + printByte(*p++); + i++; + } + _console->printf("\n"); +}