iSDIO library for FlashAir

Dependents:   FlashAir_iSDIO_sample FlashAir_iSDIO_16seg_ADT7410_step1 FlashAir_iSDIO_16seg_ADT7410 FlashAir_iSDIO_sample_OS5_ ... more

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");
+}