Browse Source

Add Teensy 4.0 SDIO support

main
Bill Greiman 5 years ago
parent
commit
5cb74d4e33
12 changed files with 635 additions and 233 deletions
  1. +2
    -0
      README.md
  2. +1
    -1
      examples/TeensyRtcTimestamp/TeensyRtcTimestamp.ino
  3. +13
    -4
      examples/TeensySdioDemo/TeensySdioDemo.ino
  4. +2
    -1
      examples/bench/bench.ino
  5. +1
    -1
      library.properties
  6. +1
    -0
      src/FreeStack.cpp
  7. +3
    -1
      src/FreeStack.h
  8. +1
    -0
      src/SdCard/CPPLINT.cfg
  9. +0
    -1
      src/SdCard/SdioCard.h
  10. +331
    -224
      src/SdCard/SdioTeensy.cpp
  11. +277
    -0
      src/SdCard/SdioTeensy.h
  12. +3
    -0
      src/SdFatConfig.h

+ 2
- 0
README.md View File

@@ -1,5 +1,7 @@
### Warning: This is an early beta version of SdFat Version 2.

September 19, 2019 - added support for Teensy 4.0 SDIO.

This library is in early development and features may change.
It will clearly have bugs. I am posting this version to get comments and
help finding bugs/compatibility problems.

+ 1
- 1
examples/TeensyRtcTimestamp/TeensyRtcTimestamp.ino View File

@@ -1,4 +1,4 @@
// Test of time-stamp callback with Teensy3.
// Test of time-stamp callback with Teensy 3/4.
// The upload time will be used to set the RTC.
// You must arrange for syncing the RTC.
#include "SdFat.h"

+ 13
- 4
examples/TeensySdioDemo/TeensySdioDemo.ino View File

@@ -1,8 +1,17 @@
// Simple performance test for Teensy 3.5/3.6 SDHC.
// Simple performance test for Teensy 3.5/3.6 4.0 SDHC.
// Demonstrates yield() efficiency for SDIO modes.
// Uses built-in SD for SPI modes.
#include "SdFat.h"

// Use built-in SD for SPI modes on Teensy 3.5/3.6.
// Teensy 4.0 use first SPI port.
// SDCARD_SS_PIN is defined for the built-in SD on some boards.
#ifndef SDCARD_SS_PIN
const uint8_t SD_CS_PIN = SS;
#else // SDCARD_SS_PIN
// Assume built-in SD is used.
const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#endif // SDCARD_SS_PIN

// SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h,
// 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT.
#define SD_FAT_TYPE 3
@@ -181,12 +190,12 @@ void loop() {
}
Serial.println("\nDMA SDIO mode - slow for small transfers.");
} else if (c == '3') {
if (!sd.begin(SdSpiConfig(SDCARD_SS_PIN, DEDICATED_SPI, SD_SCK_MHZ(50)))) {
if (!sd.begin(SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(50)))) {
errorHalt("begin failed");
}
Serial.println("\nDedicated SPI mode.");
} else if (c == '4') {
if (!sd.begin(SdSpiConfig(SDCARD_SS_PIN, SHARED_SPI, SD_SCK_MHZ(50)))) {
if (!sd.begin(SdSpiConfig(SD_CS_PIN, SHARED_SPI, SD_SCK_MHZ(50)))) {
errorHalt("begin failed");
}
Serial.println("\nShared SPI mode - slow for small transfers.");

+ 2
- 1
examples/bench/bench.ino View File

@@ -142,8 +142,9 @@ void loop() {
while (!Serial.available()) {
SysCall::yield();
}
#if HAS_UNUSED_STACK
cout << F("FreeStack: ") << FreeStack() << endl;
#endif // HAS_UNUSED_STACK

if (!sd.begin(SD_CONFIG)) {
sd.initErrorHalt(&Serial);

+ 1
- 1
library.properties View File

@@ -1,5 +1,5 @@
name=SdFat
version=2.0.0-beta.2
version=2.0.0-beta.3
license=MIT
author=Bill Greiman <fat16lib@sbcglobal.net>
maintainer=Bill Greiman <fat16lib@sbcglobal.net>

+ 1
- 0
src/FreeStack.cpp View File

@@ -22,6 +22,7 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#define FREE_STACK_CPP
#include "FreeStack.h"
#if HAS_UNUSED_STACK
#ifdef __AVR__

+ 3
- 1
src/FreeStack.h View File

@@ -49,7 +49,7 @@ inline int FreeStack() {
inline int FreeStack() {
return System.freeMemory();
}
#elif defined(__arm__)
#elif defined(__arm__) && !defined(__IMXRT1062__)
#define HAS_UNUSED_STACK 1
extern "C" char* sbrk(int incr);
inline int FreeStack() {
@@ -57,7 +57,9 @@ inline int FreeStack() {
return reinterpret_cast<char*>(sp) - reinterpret_cast<char*>(sbrk(0));
}
#else // defined(__AVR__) || defined(DOXYGEN)
#ifndef FREE_STACK_CPP
#warning FreeStack is not defined for this system.
#endif // FREE_STACK_CPP
inline int FreeStack() {
return 0;
}

+ 1
- 0
src/SdCard/CPPLINT.cfg View File

@@ -0,0 +1 @@
exclude_files=SdioTeensy.h

+ 0
- 1
src/SdCard/SdioCard.h View File

@@ -240,7 +240,6 @@ class SdioCard : public SdCardInterface {
static const uint8_t READ_STATE = 1;
static const uint8_t WRITE_STATE = 2;
uint32_t m_curSector;
uint32_t m_limitSector;
SdioConfig m_sdioConfig;
uint8_t m_curState;
};

+ 331
- 224
src/SdCard/SdioTeensy.cpp View File

@@ -22,9 +22,11 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
#if defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__)
#include "SdioTeensy.h"
#include "SdCardInfo.h"
#include "SdioCard.h"
//==============================================================================
// limit of K66 due to errata KINETIS_K_0N65N.
const uint32_t MAX_SDHC_COUNT = 0XFFFF;

@@ -33,7 +35,7 @@ const uint32_t RU_MASK = 0X03FF;
//==============================================================================
#define SDHC_PROCTL_DTW_4BIT 0x01
const uint32_t FIFO_WML = 16;
const uint32_t CMD8_RETRIES = 10;
const uint32_t CMD8_RETRIES = 3;
const uint32_t BUSY_TIMEOUT_MICROS = 1000000;
//==============================================================================
const uint32_t SDHC_IRQSTATEN_MASK =
@@ -62,7 +64,7 @@ const uint32_t SDHC_IRQSIGEN_MASK =
SDHC_IRQSIGEN_DTOEIEN | SDHC_IRQSIGEN_CIEIEN |
SDHC_IRQSIGEN_CEBEIEN | SDHC_IRQSIGEN_CCEIEN |
SDHC_IRQSIGEN_CTOEIEN | SDHC_IRQSIGEN_TCIEN;
//=============================================================================
//==============================================================================
const uint32_t CMD_RESP_NONE = SDHC_XFERTYP_RSPTYP(0);

const uint32_t CMD_RESP_R1 = SDHC_XFERTYP_CICEN | SDHC_XFERTYP_CCCEN |
@@ -79,6 +81,7 @@ const uint32_t CMD_RESP_R6 = CMD_RESP_R1;

const uint32_t CMD_RESP_R7 = CMD_RESP_R1;

#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
const uint32_t DATA_READ = SDHC_XFERTYP_DTDSEL | SDHC_XFERTYP_DPSEL;

const uint32_t DATA_READ_DMA = DATA_READ | SDHC_XFERTYP_DMAEN;
@@ -87,16 +90,44 @@ const uint32_t DATA_READ_MULTI_DMA = DATA_READ_DMA | SDHC_XFERTYP_MSBSEL |
SDHC_XFERTYP_AC12EN | SDHC_XFERTYP_BCEN;

const uint32_t DATA_READ_MULTI_PGM = DATA_READ | SDHC_XFERTYP_MSBSEL |
SDHC_XFERTYP_BCEN | SDHC_XFERTYP_AC12EN;
SDHC_XFERTYP_BCEN;

const uint32_t DATA_WRITE_DMA = SDHC_XFERTYP_DPSEL | SDHC_XFERTYP_DMAEN;

const uint32_t DATA_WRITE_MULTI_DMA = DATA_WRITE_DMA | SDHC_XFERTYP_MSBSEL |
SDHC_XFERTYP_AC12EN | SDHC_XFERTYP_BCEN;

const uint32_t DATA_WRITE_MULTI_PGM = SDHC_XFERTYP_DPSEL |
SDHC_XFERTYP_MSBSEL |
SDHC_XFERTYP_BCEN | SDHC_XFERTYP_AC12EN;
const uint32_t DATA_WRITE_MULTI_PGM = SDHC_XFERTYP_DPSEL | SDHC_XFERTYP_MSBSEL |
SDHC_XFERTYP_BCEN;

#elif defined(__IMXRT1062__)
// Use low bits for SDHC_MIX_CTRL since bits 15-0 of SDHC_XFERTYP are reserved.
const uint32_t SDHC_MIX_CTRL_MASK = SDHC_MIX_CTRL_DMAEN | SDHC_MIX_CTRL_BCEN |
SDHC_MIX_CTRL_AC12EN |
SDHC_MIX_CTRL_DDR_EN |
SDHC_MIX_CTRL_DTDSEL |
SDHC_MIX_CTRL_MSBSEL |
SDHC_MIX_CTRL_NIBBLE_POS |
SDHC_MIX_CTRL_AC23EN;

const uint32_t DATA_READ = SDHC_MIX_CTRL_DTDSEL | SDHC_XFERTYP_DPSEL;

const uint32_t DATA_READ_DMA = DATA_READ | SDHC_MIX_CTRL_DMAEN;

const uint32_t DATA_READ_MULTI_DMA = DATA_READ_DMA | SDHC_MIX_CTRL_MSBSEL |
SDHC_MIX_CTRL_AC12EN | SDHC_MIX_CTRL_BCEN;

const uint32_t DATA_READ_MULTI_PGM = DATA_READ | SDHC_MIX_CTRL_MSBSEL;


const uint32_t DATA_WRITE_DMA = SDHC_XFERTYP_DPSEL | SDHC_MIX_CTRL_DMAEN;

const uint32_t DATA_WRITE_MULTI_DMA = DATA_WRITE_DMA | SDHC_MIX_CTRL_MSBSEL |
SDHC_MIX_CTRL_AC12EN | SDHC_MIX_CTRL_BCEN;

const uint32_t DATA_WRITE_MULTI_PGM = SDHC_XFERTYP_DPSEL | SDHC_MIX_CTRL_MSBSEL;

#endif // defined(__MK64FX512__) || defined(__MK66FX1M0__)

const uint32_t ACMD6_XFERTYP = SDHC_XFERTYP_CMDINX(ACMD6) | CMD_RESP_R1;

@@ -150,7 +181,7 @@ const uint32_t CMD38_XFERTYP = SDHC_XFERTYP_CMDINX(CMD38) | CMD_RESP_R1b;

const uint32_t CMD55_XFERTYP = SDHC_XFERTYP_CMDINX(CMD55) | CMD_RESP_R1;

//=============================================================================
//==============================================================================
static bool cardCommand(uint32_t xfertyp, uint32_t arg);
static void enableGPIO(bool enable);
static void enableDmaIrs();
@@ -163,7 +194,7 @@ static void setSdclk(uint32_t kHzMax);
static bool yieldTimeout(bool (*fcn)());
static bool waitDmaStatus();
static bool waitTimeout(bool (*fcn)());
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
static bool (*m_busyFcn)() = 0;
static bool m_initDone = false;
static bool m_version2;
@@ -177,7 +208,8 @@ static uint32_t m_sdClkKhz = 0;
static uint32_t m_ocr;
static cid_t m_cid;
static csd_t m_csd;
//=============================================================================
//==============================================================================
#define DBG_TRACE Serial.print("TRACE."); Serial.println(__LINE__); delay(200);
#define USE_DEBUG_MODE 0
#if USE_DEBUG_MODE
#define DBG_IRQSTAT() if (SDHC_IRQSTAT) {Serial.print(__LINE__);\
@@ -185,6 +217,10 @@ static csd_t m_csd;

static void printRegs(uint32_t line) {
Serial.print(line);
Serial.print(" SDHC_BLKATTR ");
Serial.print(SDHC_BLKATTR, HEX);
Serial.print(" XFERTYP ");
Serial.print(SDHC_XFERTYP, HEX);
Serial.print(" PRSSTAT ");
Serial.print(SDHC_PRSSTAT, HEX);
Serial.print(" PROCTL ");
@@ -197,34 +233,128 @@ static void printRegs(uint32_t line) {
#else // USE_DEBUG_MODE
#define DBG_IRQSTAT()
#endif // USE_DEBUG_MODE
//=============================================================================
//==============================================================================
// Error function and macro.
#define sdError(code) setSdErrorCode(code, __LINE__)
inline bool setSdErrorCode(uint8_t code, uint32_t line) {
m_errorCode = code;
m_errorLine = line;
return false; // setSdErrorCode
#if USE_DEBUG_MODE
printRegs(line);
#endif // USE_DEBUG_MODE
return false;
}
//=============================================================================
//==============================================================================
// ISR
void sdhc_isr() {
static void sdIrs() {
SDHC_IRQSIGEN = 0;
m_irqstat = SDHC_IRQSTAT;
SDHC_IRQSTAT = m_irqstat;
#if defined(__IMXRT1062__)
SDHC_MIX_CTRL &= ~(SDHC_MIX_CTRL_AC23EN | SDHC_MIX_CTRL_DMAEN);
#endif
m_dmaBusy = false;
}
//=============================================================================
//==============================================================================
// GPIO and clock functions.
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
//------------------------------------------------------------------------------
static void enableGPIO(bool enable) {
const uint32_t PORT_CLK = PORT_PCR_MUX(4) | PORT_PCR_DSE;
const uint32_t PORT_CMD_DATA = PORT_CLK | PORT_PCR_PE | PORT_PCR_PS;
const uint32_t PORT_PUP = PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS;

PORTE_PCR0 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_D1
PORTE_PCR1 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_D0
PORTE_PCR2 = enable ? PORT_CLK : PORT_PUP; // SDHC_CLK
PORTE_PCR3 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_CMD
PORTE_PCR4 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_D3
PORTE_PCR5 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_D2
}
//------------------------------------------------------------------------------
static void initClock() {
#ifdef HAS_KINETIS_MPU
// Allow SDHC Bus Master access.
MPU_RGDAAC0 |= 0x0C000000;
#endif // HAS_KINETIS_MPU
// Enable SDHC clock.
SIM_SCGC3 |= SIM_SCGC3_SDHC;
}
static uint32_t baseClock() { return F_CPU;}

#elif defined(__IMXRT1062__)
//------------------------------------------------------------------------------
static void gpioMux(uint8_t mode) {
IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_04 = mode; // DAT2
IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_05 = mode; // DAT3
IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_00 = mode; // CMD
IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_01 = mode; // CLK
IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_02 = mode; // DAT0
IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_03 = mode; // DAT1
}
//------------------------------------------------------------------------------
// add speed strength args?
static void enableGPIO(bool enable) {
const uint32_t CLOCK_MASK = IOMUXC_SW_PAD_CTL_PAD_PKE |
// IOMUXC_SW_PAD_CTL_PAD_DSE(1) |
IOMUXC_SW_PAD_CTL_PAD_DSE(4) | ///// WHG
IOMUXC_SW_PAD_CTL_PAD_SPEED(2);

const uint32_t DATA_MASK = CLOCK_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE |
IOMUXC_SW_PAD_CTL_PAD_PUS(1);
if (enable) {
gpioMux(0);
IOMUXC_SW_PAD_CTL_PAD_GPIO_SD_B0_04 = DATA_MASK; // DAT2
IOMUXC_SW_PAD_CTL_PAD_GPIO_SD_B0_05 = DATA_MASK; // DAT3
IOMUXC_SW_PAD_CTL_PAD_GPIO_SD_B0_00 = DATA_MASK; // CMD
IOMUXC_SW_PAD_CTL_PAD_GPIO_SD_B0_01 = CLOCK_MASK; // CLK
IOMUXC_SW_PAD_CTL_PAD_GPIO_SD_B0_02 = DATA_MASK; // DAT0
IOMUXC_SW_PAD_CTL_PAD_GPIO_SD_B0_03 = DATA_MASK; // DAT1
} else {
gpioMux(5);
}
}
//------------------------------------------------------------------------------
static void initClock() {
/* set PDF_528 PLL2PFD0 */
CCM_ANALOG_PFD_528 |= (1 << 7);
CCM_ANALOG_PFD_528 &= ~(0x3F << 0);
CCM_ANALOG_PFD_528 |= ((24) & 0x3F << 0); // 12 - 35
CCM_ANALOG_PFD_528 &= ~(1 << 7);

/* Enable USDHC clock. */
CCM_CCGR6 |= CCM_CCGR6_USDHC1(CCM_CCGR_ON);
CCM_CSCDR1 &= ~(CCM_CSCDR1_USDHC1_CLK_PODF_MASK);
CCM_CSCMR1 |= CCM_CSCMR1_USDHC1_CLK_SEL; // PLL2PFD0
// CCM_CSCDR1 |= CCM_CSCDR1_USDHC1_CLK_PODF((7)); / &0x7 WHG
CCM_CSCDR1 |= CCM_CSCDR1_USDHC1_CLK_PODF((1));
}
//------------------------------------------------------------------------------
static uint32_t baseClock() {
uint32_t divider = ((CCM_CSCDR1 >> 11) & 0x7) + 1;
return (528000000U * 3)/((CCM_ANALOG_PFD_528 & 0x3F)/6)/divider;
}
#endif // defined(__MK64FX512__) || defined(__MK66FX1M0__)
//==============================================================================
// Static functions.
static bool cardAcmd(uint32_t rca, uint32_t xfertyp, uint32_t arg) {
return cardCommand(CMD55_XFERTYP, rca) && cardCommand (xfertyp, arg);
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
static bool cardCommand(uint32_t xfertyp, uint32_t arg) {
DBG_IRQSTAT();
if (waitTimeout(isBusyCommandInhibit)) {
return false; // Caller will set errorCode.
}
SDHC_CMDARG = arg;
#if defined(__IMXRT1062__)
// Set MIX_CTRL if data transfer.
if (xfertyp & SDHC_XFERTYP_DPSEL) {
SDHC_MIX_CTRL &= ~SDHC_MIX_CTRL_MASK;
SDHC_MIX_CTRL |= xfertyp & SDHC_MIX_CTRL_MASK;
}
xfertyp &= ~SDHC_MIX_CTRL_MASK;
#endif // defined(__IMXRT1062__)
SDHC_XFERTYP = xfertyp;
if (waitTimeout(isBusyCommandComplete)) {
return false; // Caller will set errorCode.
@@ -235,7 +365,7 @@ static bool cardCommand(uint32_t xfertyp, uint32_t arg) {
return (m_irqstat & SDHC_IRQSTAT_CC) &&
!(m_irqstat & SDHC_IRQSTAT_CMD_ERROR);
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
static bool cardCMD6(uint32_t arg, uint8_t* status) {
// CMD6 returns 64 bytes.
if (waitTimeout(isBusyCMD13)) {
@@ -243,50 +373,38 @@ static bool cardCMD6(uint32_t arg, uint8_t* status) {
}
enableDmaIrs();
SDHC_DSADDR = (uint32_t)status;
SDHC_CMDARG = arg;
SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(1) | SDHC_BLKATTR_BLKSIZE(64);
SDHC_IRQSIGEN = SDHC_IRQSIGEN_MASK;
SDHC_XFERTYP = CMD6_XFERTYP;

if (!waitDmaStatus()) {
if (!cardCommand(CMD6_XFERTYP, arg)) {
return sdError(SD_CARD_ERROR_CMD6);
}
if (!waitDmaStatus()) {
return sdError(SD_CARD_ERROR_DMA);
}
return true;
}
//-----------------------------------------------------------------------------
static void enableGPIO(bool enable) {
const uint32_t PORT_CLK = PORT_PCR_MUX(4) | PORT_PCR_DSE;
const uint32_t PORT_CMD_DATA = PORT_CLK | PORT_PCR_PE | PORT_PCR_PS;
const uint32_t PORT_PUP = PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS;

PORTE_PCR0 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_D1
PORTE_PCR1 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_D0
PORTE_PCR2 = enable ? PORT_CLK : PORT_PUP; // SDHC_CLK
PORTE_PCR3 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_CMD
PORTE_PCR4 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_D3
PORTE_PCR5 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_D2
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
static void enableDmaIrs() {
m_dmaBusy = true;
m_irqstat = 0;
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
static void initSDHC() {
#ifdef HAS_KINETIS_MPU
// Allow SDHC Bus Master access.
MPU_RGDAAC0 |= 0x0C000000;
#endif // HAS_KINETIS_MPU
// Enable SDHC clock.
SIM_SCGC3 |= SIM_SCGC3_SDHC;
initClock();

// Disable GPIO clock.
enableGPIO(false);

#if defined (__IMXRT1062__)
SDHC_MIX_CTRL |= 0x80000000;
#endif

// Reset SDHC. Use default Water Mark Level of 16.
SDHC_SYSCTL = SDHC_SYSCTL_RSTA;
SDHC_SYSCTL |= SDHC_SYSCTL_RSTA | SDHC_SYSCTL_SDCLKFS(0x80);

while (SDHC_SYSCTL & SDHC_SYSCTL_RSTA) {
}

// Set initial SCK rate.
setSdclk(400);

@@ -295,6 +413,7 @@ static void initSDHC() {
// Enable desired IRQSTAT bits.
SDHC_IRQSTATEN = SDHC_IRQSTATEN_MASK;

attachInterruptVector(IRQ_SDHC, sdIrs);
NVIC_SET_PRIORITY(IRQ_SDHC, 6*16);
NVIC_ENABLE_IRQ(IRQ_SDHC);

@@ -303,11 +422,11 @@ static void initSDHC() {
while (SDHC_SYSCTL & SDHC_SYSCTL_INITA) {
}
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
static uint32_t statusCMD13() {
return cardCommand(CMD13_XFERTYP, m_rca) ? SDHC_CMDRSP0 : 0;
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
static bool isBusyCMD13() {
if (!cardCommand(CMD13_XFERTYP, m_rca)) {
// Caller will timeout.
@@ -315,31 +434,31 @@ static bool isBusyCMD13() {
}
return !(SDHC_CMDRSP0 & CARD_STATUS_READY_FOR_DATA);
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
static bool isBusyCommandComplete() {
return !(SDHC_IRQSTAT &(SDHC_IRQSTAT_CC | SDHC_IRQSTAT_CMD_ERROR));
return !(SDHC_IRQSTAT & (SDHC_IRQSTAT_CC | SDHC_IRQSTAT_CMD_ERROR));
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
static bool isBusyCommandInhibit() {
return SDHC_PRSSTAT & SDHC_PRSSTAT_CIHB;
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
static bool isBusyDMA() {
return m_dmaBusy;
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
static bool isBusyFifoRead() {
return !(SDHC_PRSSTAT & SDHC_PRSSTAT_BREN);
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
static bool isBusyFifoWrite() {
return !(SDHC_PRSSTAT & SDHC_PRSSTAT_BWEN);
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
static bool isBusyTransferComplete() {
return !(SDHC_IRQSTAT & (SDHC_IRQSTAT_TC | SDHC_IRQSTAT_ERROR));
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
static bool rdWrSectors(uint32_t xfertyp,
uint32_t sector, uint8_t* buf, size_t n) {
if ((3 & (uint32_t)buf) || n == 0) {
@@ -350,14 +469,14 @@ static bool rdWrSectors(uint32_t xfertyp,
}
enableDmaIrs();
SDHC_DSADDR = (uint32_t)buf;
SDHC_CMDARG = m_highCapacity ? sector : 512*sector;
SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(n) | SDHC_BLKATTR_BLKSIZE(512);
SDHC_IRQSIGEN = SDHC_IRQSIGEN_MASK;
SDHC_XFERTYP = xfertyp;

if (!cardCommand(xfertyp, m_highCapacity ? sector : 512*sector)) {
return false;
}
return waitDmaStatus();
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Read 16 byte CID or CSD register.
static bool readReg16(uint32_t xfertyp, void* data) {
uint8_t* d = reinterpret_cast<uint8_t*>(data);
@@ -371,26 +490,28 @@ static bool readReg16(uint32_t xfertyp, void* data) {
d[15] = 0;
return true;
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
static void setSdclk(uint32_t kHzMax) {
const uint32_t DVS_LIMIT = 0X10;
const uint32_t SDCLKFS_LIMIT = 0X100;
uint32_t dvs = 1;
uint32_t sdclkfs = 1;
uint32_t maxSdclk = 1000*kHzMax;
uint32_t base = baseClock();

while ((F_CPU/(sdclkfs*DVS_LIMIT) > maxSdclk) && (sdclkfs < SDCLKFS_LIMIT)) {
while ((base/(sdclkfs*DVS_LIMIT) > maxSdclk) && (sdclkfs < SDCLKFS_LIMIT)) {
sdclkfs <<= 1;
}
while ((F_CPU/(sdclkfs*dvs) > maxSdclk) && (dvs < DVS_LIMIT)) {
while ((base/(sdclkfs*dvs) > maxSdclk) && (dvs < DVS_LIMIT)) {
dvs++;
}
m_sdClkKhz = F_CPU/(1000*sdclkfs*dvs);
m_sdClkKhz = base/(1000*sdclkfs*dvs);
sdclkfs >>= 1;
dvs--;
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
// Disable SDHC clock.
SDHC_SYSCTL &= ~SDHC_SYSCTL_SDCLKEN;
#endif // defined(__MK64FX512__) || defined(__MK66FX1M0__)

// Change dividers.
uint32_t sysctl = SDHC_SYSCTL & ~(SDHC_SYSCTL_DTOCV_MASK
@@ -402,13 +523,14 @@ static void setSdclk(uint32_t kHzMax) {
// Wait until the SDHC clock is stable.
while (!(SDHC_PRSSTAT & SDHC_PRSSTAT_SDSTB)) {
}

#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
// Enable the SDHC clock.
SDHC_SYSCTL |= SDHC_SYSCTL_SDCLKEN;
#endif // defined(__MK64FX512__) || defined(__MK66FX1M0__)
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
static bool transferStop() {
DBG_IRQSTAT();

if (!cardCommand(CMD12_XFERTYP, 0)) {
return sdError(SD_CARD_ERROR_CMD12);
}
@@ -418,17 +540,14 @@ static bool transferStop() {
// Save registers before reset DAT lines.
uint32_t irqsststen = SDHC_IRQSTATEN;
uint32_t proctl = SDHC_PROCTL & ~SDHC_PROCTL_SABGREQ;

// Do reset to clear CDIHB. Should be a better way!
SDHC_SYSCTL |= SDHC_SYSCTL_RSTD;

// Restore registers.
SDHC_IRQSTATEN = irqsststen;
SDHC_PROCTL = proctl;

return true;
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Return true if timeout occurs.
static bool yieldTimeout(bool (*fcn)()) {
m_busyFcn = fcn;
@@ -443,14 +562,14 @@ static bool yieldTimeout(bool (*fcn)()) {
m_busyFcn = 0;
return false; // Caller will set errorCode.
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
static bool waitDmaStatus() {
if (yieldTimeout(isBusyDMA)) {
return false; // Caller will set errorCode.
}
return (m_irqstat & SDHC_IRQSTAT_TC) && !(m_irqstat & SDHC_IRQSTAT_ERROR);
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Return true if timeout occurs.
static bool waitTimeout(bool (*fcn)()) {
uint32_t m = micros();
@@ -461,7 +580,9 @@ static bool waitTimeout(bool (*fcn)()) {
}
return false; // Caller will set errorCode.
}
//=============================================================================
//==============================================================================
// Start of SdioCard member functions.
//==============================================================================
bool SdioCard::begin(SdioConfig sdioConfig) {
uint32_t kHzSdClk;
uint32_t arg;
@@ -474,7 +595,6 @@ bool SdioCard::begin(SdioConfig sdioConfig) {

// initialize controller.
initSDHC();

if (!cardCommand(CMD0_XFERTYP, 0)) {
return sdError(SD_CARD_ERROR_CMD0);
}
@@ -489,14 +609,13 @@ bool SdioCard::begin(SdioConfig sdioConfig) {
}
}
arg = m_version2 ? 0X40300000 : 0x00300000;
uint32_t m = micros();
int m = micros();
do {
if (!cardAcmd(0, ACMD41_XFERTYP, arg) ||
((micros() - m) > BUSY_TIMEOUT_MICROS)) {
return sdError(SD_CARD_ERROR_ACMD41);
}
} while ((SDHC_CMDRSP0 & 0x80000000) == 0);

m_ocr = SDHC_CMDRSP0;
if (SDHC_CMDRSP0 & 0x40000000) {
// Is high capacity.
@@ -530,6 +649,7 @@ bool SdioCard::begin(SdioConfig sdioConfig) {
SDHC_WML = SDHC_WML_RDWML(FIFO_WML) | SDHC_WML_WRWML(FIFO_WML);

// Determine if High Speed mode is supported and set frequency.
// Check status[16] for error 0XF or status[16] for new mode 0X1.
uint8_t status[64];
if (cardCMD6(0X00FFFFFF, status) && (2 & status[13]) &&
cardCMD6(0X80FFFFF1, status) && (status[16] & 0XF) == 1) {
@@ -537,22 +657,18 @@ bool SdioCard::begin(SdioConfig sdioConfig) {
} else {
kHzSdClk = 25000;
}
// disable GPIO
// Disable GPIO.
enableGPIO(false);

// Set the SDHC SCK frequency.
setSdclk(kHzSdClk);

// enable GPIO
// Enable GPIO.
enableGPIO(true);
m_initDone = true;
return true;
}
//-----------------------------------------------------------------------------
uint32_t SdioCard::sectorCount() {
return sdCardCapacity(&m_csd);
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool SdioCard::erase(uint32_t firstSector, uint32_t lastSector) {
// check for single sector erase
if (!m_csd.v1.erase_blk_en) {
@@ -581,27 +697,72 @@ bool SdioCard::erase(uint32_t firstSector, uint32_t lastSector) {
}
return true;
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
uint8_t SdioCard::errorCode() const {
return m_errorCode;
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
uint32_t SdioCard::errorData() const {
return m_irqstat;
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
uint32_t SdioCard::errorLine() const {
return m_errorLine;
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool SdioCard::isBusy() {
return m_busyFcn ? m_busyFcn() : m_initDone && isBusyCMD13();
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
uint32_t SdioCard::kHzSdClk() {
return m_sdClkKhz;
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool SdioCard::readCID(cid_t* cid) {
memcpy(cid, &m_cid, 16);
return true;
}
//------------------------------------------------------------------------------
bool SdioCard::readCSD(csd_t* csd) {
memcpy(csd, &m_csd, 16);
return true;
}
//------------------------------------------------------------------------------
bool SdioCard::readData(uint8_t *dst) {
DBG_IRQSTAT();
uint32_t *p32 = reinterpret_cast<uint32_t*>(dst);

if (!(SDHC_PRSSTAT & SDHC_PRSSTAT_RTA)) {
SDHC_PROCTL &= ~SDHC_PROCTL_SABGREQ;
noInterrupts();
SDHC_PROCTL |= SDHC_PROCTL_CREQ;
SDHC_PROCTL |= SDHC_PROCTL_SABGREQ;
interrupts();
}
if (waitTimeout(isBusyFifoRead)) {
return sdError(SD_CARD_ERROR_READ_FIFO);
}
for (uint32_t iw = 0 ; iw < 512/(4*FIFO_WML); iw++) {
while (0 == (SDHC_PRSSTAT & SDHC_PRSSTAT_BREN)) {
}
for (uint32_t i = 0; i < FIFO_WML; i++) {
p32[i] = SDHC_DATPORT;
}
p32 += FIFO_WML;
}
if (waitTimeout(isBusyTransferComplete)) {
return sdError(SD_CARD_ERROR_READ_TIMEOUT);
}
m_irqstat = SDHC_IRQSTAT;
SDHC_IRQSTAT = m_irqstat;
return (m_irqstat & SDHC_IRQSTAT_TC) && !(m_irqstat & SDHC_IRQSTAT_ERROR);
}
//------------------------------------------------------------------------------
bool SdioCard::readOCR(uint32_t* ocr) {
*ocr = m_ocr;
return true;
}
//------------------------------------------------------------------------------
bool SdioCard::readSector(uint32_t sector, uint8_t* dst) {
if (m_sdioConfig.useDma()) {
uint8_t aligned[512];
@@ -609,7 +770,7 @@ bool SdioCard::readSector(uint32_t sector, uint8_t* dst) {
uint8_t* ptr = (uint32_t)dst & 3 ? aligned : dst;

if (!rdWrSectors(CMD17_DMA_XFERTYP, sector, ptr, 1)) {
return sdError(SD_CARD_ERROR_CMD18);
return sdError(SD_CARD_ERROR_CMD17);
}
if (ptr != dst) {
memcpy(dst, aligned, 512);
@@ -619,24 +780,27 @@ bool SdioCard::readSector(uint32_t sector, uint8_t* dst) {
if (!syncDevice()) {
return false;
}
m_limitSector = (sector + MAX_SDHC_COUNT) & ~RU_MASK;
if (!SdioCard::readStart(sector, m_limitSector - sector)) {
if (!readStart(sector)) {
return false;
}
m_curSector = sector;
m_curState = READ_STATE;
}
if (!SdioCard::readData(dst)) {
if (!readData(dst)) {
return false;
}
m_curSector++;
if (m_curSector >= m_limitSector) {
m_curState = IDLE_STATE;
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
if ((SDHC_BLKATTR & 0XFFFF0000) == 0) {
if (!syncDevice()) {
return false;
}
}
#endif // defined(__MK64FX512__) || defined(__MK66FX1M0__)
m_curSector++;
}
return true;
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool SdioCard::readSectors(uint32_t sector, uint8_t* dst, size_t n) {
if (m_sdioConfig.useDma()) {
if ((uint32_t)dst & 3) {
@@ -659,98 +823,49 @@ bool SdioCard::readSectors(uint32_t sector, uint8_t* dst, size_t n) {
}
return true;
}
//-----------------------------------------------------------------------------
bool SdioCard::readCID(cid_t* cid) {
memcpy(cid, &m_cid, 16);
return true;
}
//-----------------------------------------------------------------------------
bool SdioCard::readCSD(csd_t* csd) {
memcpy(csd, &m_csd, 16);
return true;
}
//-----------------------------------------------------------------------------
bool SdioCard::readData(uint8_t *dst) {
DBG_IRQSTAT();
uint32_t *p32 = reinterpret_cast<uint32_t*>(dst);

if (!(SDHC_PRSSTAT & SDHC_PRSSTAT_RTA)) {
SDHC_PROCTL &= ~SDHC_PROCTL_SABGREQ;
if ((SDHC_BLKATTR & 0XFFFF0000) == 0X10000) {
// Don't stop at sector gap if last sector. Allows auto CMD12.
SDHC_PROCTL |= SDHC_PROCTL_CREQ;
} else {
noInterrupts();
SDHC_PROCTL |= SDHC_PROCTL_CREQ;
SDHC_PROCTL |= SDHC_PROCTL_SABGREQ;
interrupts();
}
}
if (waitTimeout(isBusyFifoRead)) {
return sdError(SD_CARD_ERROR_READ_FIFO);
}
for (uint32_t iw = 0 ; iw < 512/(4*FIFO_WML); iw++) {
while (0 == (SDHC_PRSSTAT & SDHC_PRSSTAT_BREN)) {
}
for (uint32_t i = 0; i < FIFO_WML; i++) {
p32[i] = SDHC_DATPORT;
}
p32 += FIFO_WML;
}
if (waitTimeout(isBusyTransferComplete)) {
return sdError(SD_CARD_ERROR_READ_TIMEOUT);
}
m_irqstat = SDHC_IRQSTAT;
SDHC_IRQSTAT = m_irqstat;
return (m_irqstat & SDHC_IRQSTAT_TC) && !(m_irqstat & SDHC_IRQSTAT_ERROR);
}
//-----------------------------------------------------------------------------
bool SdioCard::readOCR(uint32_t* ocr) {
*ocr = m_ocr;
return true;
}
//-----------------------------------------------------------------------------
bool SdioCard::readStart(uint32_t sector) {
// K66/K65 Errata - SDHC: Does not support Infinite Sector Transfer Mode.
return sdError(SD_CARD_ERROR_FUNCTION_NOT_SUPPORTED);
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// SDHC will do Auto CMD12 after count sectors.
bool SdioCard::readStart(uint32_t sector, uint32_t count) {
bool SdioCard::readStart(uint32_t sector) {
DBG_IRQSTAT();
if (count > 0XFFFF) {
return sdError(SD_CARD_ERROR_READ_START);
}
if (yieldTimeout(isBusyCMD13)) {
return sdError(SD_CARD_ERROR_CMD13);
}
if (count > 1) {
SDHC_PROCTL |= SDHC_PROCTL_SABGREQ;
}
SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(count) | SDHC_BLKATTR_BLKSIZE(512);
SDHC_PROCTL |= SDHC_PROCTL_SABGREQ;
#if defined(__IMXRT1062__)
// Infinite transfer.
SDHC_BLKATTR = SDHC_BLKATTR_BLKSIZE(512);
#else // defined(__IMXRT1062__)
// Errata - can't do infinite transfer.
SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(0XFFFF) | SDHC_BLKATTR_BLKSIZE(512);
#endif // defined(__IMXRT1062__)

if (!cardCommand(CMD18_PGM_XFERTYP, m_highCapacity ? sector : 512*sector)) {
return sdError(SD_CARD_ERROR_CMD18);
}
return true;
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool SdioCard::readStop() {
return transferStop();
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
uint32_t SdioCard::sectorCount() {
return sdCardCapacity(&m_csd);
}
//------------------------------------------------------------------------------
uint32_t SdioCard::status() {
return statusCMD13();
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool SdioCard::syncDevice() {
if (m_curState == READ_STATE) {
m_curState = IDLE_STATE;
if (!SdioCard::readStop()) {
if (!readStop()) {
return false;
}
} else if (m_curState == WRITE_STATE) {
m_curState = IDLE_STATE;
if (!SdioCard::writeStop()) {
if (!writeStop()) {
return false;
}
}
@@ -762,6 +877,33 @@ uint8_t SdioCard::type() const {
SD_CARD_TYPE_SDHC : SD_CARD_TYPE_SD2 : SD_CARD_TYPE_SD1;
}
//------------------------------------------------------------------------------
bool SdioCard::writeData(const uint8_t* src) {
DBG_IRQSTAT();
const uint32_t* p32 = reinterpret_cast<const uint32_t*>(src);
if (!(SDHC_PRSSTAT & SDHC_PRSSTAT_WTA)) {
SDHC_PROCTL &= ~SDHC_PROCTL_SABGREQ;
SDHC_PROCTL |= SDHC_PROCTL_CREQ;
}
SDHC_PROCTL |= SDHC_PROCTL_SABGREQ;
if (waitTimeout(isBusyFifoWrite)) {
return sdError(SD_CARD_ERROR_WRITE_FIFO);
}
for (uint32_t iw = 0 ; iw < 512/(4*FIFO_WML); iw++) {
while (0 == (SDHC_PRSSTAT & SDHC_PRSSTAT_BWEN)) {
}
for (uint32_t i = 0; i < FIFO_WML; i++) {
SDHC_DATPORT = p32[i];
}
p32 += FIFO_WML;
}
if (waitTimeout(isBusyTransferComplete)) {
return sdError(SD_CARD_ERROR_WRITE_TIMEOUT);
}
m_irqstat = SDHC_IRQSTAT;
SDHC_IRQSTAT = m_irqstat;
return (m_irqstat & SDHC_IRQSTAT_TC) && !(m_irqstat & SDHC_IRQSTAT_ERROR);
}
//------------------------------------------------------------------------------
bool SdioCard::writeSector(uint32_t sector, const uint8_t* src) {
if (m_sdioConfig.useDma()) {
uint8_t *ptr;
@@ -772,7 +914,7 @@ bool SdioCard::writeSector(uint32_t sector, const uint8_t* src) {
} else {
ptr = const_cast<uint8_t*>(src);
}
if (!rdWrSectors(CMD24_DMA_XFERTYP, sector, ptr, 1)) {
if (!rdWrSectors(CMD24_DMA_XFERTYP, sector, ptr, 1)) {
return sdError(SD_CARD_ERROR_CMD24);
}
} else {
@@ -780,20 +922,24 @@ bool SdioCard::writeSector(uint32_t sector, const uint8_t* src) {
if (!syncDevice()) {
return false;
}
m_limitSector = (sector + MAX_SDHC_COUNT) & ~RU_MASK;
if (!SdioCard::writeStart(sector , m_limitSector - sector)) {
if (!writeStart(sector )) {
return false;
}
m_curSector = sector;
m_curState = WRITE_STATE;
}
if (!SdioCard::writeData(src)) {
if (!writeData(src)) {
return false;
}
m_curSector++;
if (m_curSector >= m_limitSector) {
m_curState = IDLE_STATE;
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
// End transfer with CMD12 if required.
if ((SDHC_BLKATTR & 0XFFFF0000) == 0) {
if (!syncDevice()) {
return false;
}
}
#endif // defined(__MK64FX512__) || defined(__MK66FX1M0__)
}
return true;
}
@@ -813,74 +959,35 @@ bool SdioCard::writeSectors(uint32_t sector, const uint8_t* src, size_t n) {
return sdError(SD_CARD_ERROR_CMD25);
}
} else {
for (size_t i = 0; i < n; i++) {
if (!writeSector(sector + i, src + i*512UL)) {
return false;
for (size_t i = 0; i < n; i++) {
if (!writeSector(sector + i, src + i*512UL)) {
return false;
}
}
}
}
return true;
}
//------------------------------------------------------------------------------
bool SdioCard::writeData(const uint8_t* src) {
DBG_IRQSTAT();
const uint32_t* p32 = reinterpret_cast<const uint32_t*>(src);

if (!(SDHC_PRSSTAT & SDHC_PRSSTAT_WTA)) {
SDHC_PROCTL &= ~SDHC_PROCTL_SABGREQ;
// Don't stop at sector gap if last sector. Allows auto CMD12.
if ((SDHC_BLKATTR & 0XFFFF0000) == 0X10000) {
SDHC_PROCTL |= SDHC_PROCTL_CREQ;
} else {
SDHC_PROCTL |= SDHC_PROCTL_CREQ;
SDHC_PROCTL |= SDHC_PROCTL_SABGREQ;
}
}
if (waitTimeout(isBusyFifoWrite)) {
return sdError(SD_CARD_ERROR_WRITE_FIFO);
}
for (uint32_t iw = 0 ; iw < 512/(4*FIFO_WML); iw++) {
while (0 == (SDHC_PRSSTAT & SDHC_PRSSTAT_BWEN)) {
}
for (uint32_t i = 0; i < FIFO_WML; i++) {
SDHC_DATPORT = p32[i];
}
p32 += FIFO_WML;
}
if (waitTimeout(isBusyTransferComplete)) {
return sdError(SD_CARD_ERROR_WRITE_TIMEOUT);
}
m_irqstat = SDHC_IRQSTAT;
SDHC_IRQSTAT = m_irqstat;
return (m_irqstat & SDHC_IRQSTAT_TC) && !(m_irqstat & SDHC_IRQSTAT_ERROR);
}
//-----------------------------------------------------------------------------
bool SdioCard::writeStart(uint32_t sector) {
// K66/K65 Errata - SDHC: Does not support Infinite Sector Transfer Mode.
return sdError(SD_CARD_ERROR_FUNCTION_NOT_SUPPORTED);
}
//-----------------------------------------------------------------------------
// SDHC will do Auto CMD12 after count sectors.
bool SdioCard::writeStart(uint32_t sector, uint32_t count) {
if (count > 0XFFFF) {
return sdError(SD_CARD_ERROR_WRITE_START);
}
DBG_IRQSTAT();
if (yieldTimeout(isBusyCMD13)) {
return sdError(SD_CARD_ERROR_CMD13);
}
if (count > 1) {
SDHC_PROCTL |= SDHC_PROCTL_SABGREQ;
}
SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(count) | SDHC_BLKATTR_BLKSIZE(512);
SDHC_PROCTL &= ~SDHC_PROCTL_SABGREQ;

#if defined(__IMXRT1062__)
// Infinite transfer.
SDHC_BLKATTR = SDHC_BLKATTR_BLKSIZE(512);
#else // defined(__IMXRT1062__)
// Errata - can't do infinite transfer.
SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(0XFFFF) | SDHC_BLKATTR_BLKSIZE(512);
#endif // defined(__IMXRT1062__)
if (!cardCommand(CMD25_PGM_XFERTYP, m_highCapacity ? sector : 512*sector)) {
return sdError(SD_CARD_ERROR_CMD25);
}
return true;
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool SdioCard::writeStop() {
return transferStop();
}
#endif // defined(__MK64FX512__) || defined(__MK66FX1M0__)
#endif // defined(__MK64FX512__) defined(__MK66FX1M0__) defined(__IMXRT1062__)

+ 277
- 0
src/SdCard/SdioTeensy.h View File

@@ -0,0 +1,277 @@
#ifndef SdioTeensy_h
#define SdioTeensy_h

// From Paul's SD.h driver.

#if defined(__IMXRT1062__)
#define MAKE_REG_MASK(m,s) (((uint32_t)(((uint32_t)(m) << s))))
#define MAKE_REG_GET(x,m,s) (((uint32_t)(((uint32_t)(x)>>s) & m)))
#define MAKE_REG_SET(x,m,s) (((uint32_t)(((uint32_t)(x) & m) << s)))

#define SDHC_BLKATTR_BLKSIZE_MASK MAKE_REG_MASK(0x1FFF,0) //uint32_t)(((n) & 0x1FFF)<<0) // Transfer Block Size Mask
#define SDHC_BLKATTR_BLKSIZE(n) MAKE_REG_SET(n,0x1FFF,0) //uint32_t)(((n) & 0x1FFF)<<0) // Transfer Block Size
#define SDHC_BLKATTR_BLKCNT_MASK MAKE_REG_MASK(0x1FFF,16) //((uint32_t)0x1FFF<<16)
#define SDHC_BLKATTR_BLKCNT(n) MAKE_REG_SET(n,0x1FFF,16) //(uint32_t)(((n) & 0x1FFF)<<16) // Blocks Count For Current Transfer

#define SDHC_XFERTYP_CMDINX(n) MAKE_REG_SET(n,0x3F,24) //(uint32_t)(((n) & 0x3F)<<24)// Command Index
#define SDHC_XFERTYP_CMDTYP(n) MAKE_REG_SET(n,0x3,22) //(uint32_t)(((n) & 0x3)<<22) // Command Type
#define SDHC_XFERTYP_DPSEL MAKE_REG_MASK(0x1,21) //((uint32_t)0x00200000) // Data Present Select
#define SDHC_XFERTYP_CICEN MAKE_REG_MASK(0x1,20) //((uint32_t)0x00100000) // Command Index Check Enable
#define SDHC_XFERTYP_CCCEN MAKE_REG_MASK(0x1,19) //((uint32_t)0x00080000) // Command CRC Check Enable
#define SDHC_XFERTYP_RSPTYP(n) MAKE_REG_SET(n,0x3,16) //(uint32_t)(((n) & 0x3)<<16) // Response Type Select
#define SDHC_XFERTYP_MSBSEL MAKE_REG_MASK(0x1,5) //((uint32_t)0x00000020) // Multi/Single Block Select
#define SDHC_XFERTYP_DTDSEL MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Data Transfer Direction Select
#define SDHC_XFERTYP_AC12EN MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004) // Auto CMD12 Enable
#define SDHC_XFERTYP_BCEN MAKE_REG_MASK(0x1,1) //((uint32_t)0x00000002) // Block Count Enable
#define SDHC_XFERTYP_DMAEN MAKE_REG_MASK(0x3,0) //((uint32_t)0x00000001) // DMA Enable

#define SDHC_PRSSTAT_DLSL_MASK MAKE_REG_MASK(0xFF,24) //((uint32_t)0xFF000000) // DAT Line Signal Level
#define SDHC_PRSSTAT_CLSL MAKE_REG_MASK(0x1,23) //((uint32_t)0x00800000) // CMD Line Signal Level
#define SDHC_PRSSTAT_WPSPL MAKE_REG_MASK(0x1,19) //
#define SDHC_PRSSTAT_CDPL MAKE_REG_MASK(0x1,18) //
#define SDHC_PRSSTAT_CINS MAKE_REG_MASK(0x1,16) //((uint32_t)0x00010000) // Card Inserted
#define SDHC_PRSSTAT_TSCD MAKE_REG_MASK(0x1,15)
#define SDHC_PRSSTAT_RTR MAKE_REG_MASK(0x1,12)
#define SDHC_PRSSTAT_BREN MAKE_REG_MASK(0x1,11) //((uint32_t)0x00000800) // Buffer Read Enable
#define SDHC_PRSSTAT_BWEN MAKE_REG_MASK(0x1,10) //((uint32_t)0x00000400) // Buffer Write Enable
#define SDHC_PRSSTAT_RTA MAKE_REG_MASK(0x1,9) //((uint32_t)0x00000200) // Read Transfer Active
#define SDHC_PRSSTAT_WTA MAKE_REG_MASK(0x1,8) //((uint32_t)0x00000100) // Write Transfer Active
#define SDHC_PRSSTAT_SDOFF MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // SD Clock Gated Off Internally
#define SDHC_PRSSTAT_PEROFF MAKE_REG_MASK(0x1,6) //((uint32_t)0x00000040) // SDHC clock Gated Off Internally
#define SDHC_PRSSTAT_HCKOFF MAKE_REG_MASK(0x1,5) //((uint32_t)0x00000020) // System Clock Gated Off Internally
#define SDHC_PRSSTAT_IPGOFF MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Bus Clock Gated Off Internally
#define SDHC_PRSSTAT_SDSTB MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008) // SD Clock Stable
#define SDHC_PRSSTAT_DLA MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004) // Data Line Active
#define SDHC_PRSSTAT_CDIHB MAKE_REG_MASK(0x1,1) //((uint32_t)0x00000002) // Command Inhibit (DAT)
#define SDHC_PRSSTAT_CIHB MAKE_REG_MASK(0x1,0) //((uint32_t)0x00000001) // Command Inhibit (CMD)

#define SDHC_PROTCT_NONEXACT_BLKRD MAKE_REG_MASK(0x1,30) //
#define SDHC_PROTCT_BURST_LENEN(n) MAKE_REG_SET(n,0x7,12) //
#define SDHC_PROCTL_WECRM MAKE_REG_MASK(0x1,26) //((uint32_t)0x04000000) // Wakeup Event Enable On SD Card Removal
#define SDHC_PROCTL_WECINS MAKE_REG_MASK(0x1,25) //((uint32_t)0x02000000) // Wakeup Event Enable On SD Card Insertion
#define SDHC_PROCTL_WECINT MAKE_REG_MASK(0x1,24) //((uint32_t)0x01000000) // Wakeup Event Enable On Card Interrupt
#define SDHC_PROCTL_RD_DONE_NOBLK MAKE_REG_MASK(0x1,20) //
#define SDHC_PROCTL_IABG MAKE_REG_MASK(0x1,19) //((uint32_t)0x00080000) // Interrupt At Block Gap
#define SDHC_PROCTL_RWCTL MAKE_REG_MASK(0x1,18) //((uint32_t)0x00040000) // Read Wait Control
#define SDHC_PROCTL_CREQ MAKE_REG_MASK(0x1,17) //((uint32_t)0x00020000) // Continue Request
#define SDHC_PROCTL_SABGREQ MAKE_REG_MASK(0x1,16) //((uint32_t)0x00010000) // Stop At Block Gap Request
#define SDHC_PROCTL_DMAS(n) MAKE_REG_SET(n,0x3,8) //(uint32_t)(((n) & 0x3)<<8) // DMA Select
#define SDHC_PROCTL_CDSS MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // Card Detect Signal Selection
#define SDHC_PROCTL_CDTL MAKE_REG_MASK(0x1,6) //((uint32_t)0x00000040) // Card Detect Test Level
#define SDHC_PROCTL_EMODE(n) MAKE_REG_SET(n,0x3,4) //(uint32_t)(((n) & 0x3)<<4) // Endian Mode
#define SDHC_PROCTL_EMODE_MASK MAKE_REG_MASK(0x3,4) //(uint32_t)((0x3)<<4) // Endian Mode
#define SDHC_PROCTL_D3CD MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008) // DAT3 As Card Detection Pin
#define SDHC_PROCTL_DTW(n) MAKE_REG_SET(n,0x3,1) //(uint32_t)(((n) & 0x3)<<1) // Data Transfer Width, 0=1bit, 1=4bit, 2=8bit
#define SDHC_PROCTL_DTW_MASK MAKE_REG_MASK(0x3,1) //((uint32_t)0x00000006)
#define SDHC_PROCTL_LCTL MAKE_REG_MASK(0x1,0) //((uint32_t)0x00000001) // LED Control

#define SDHC_SYSCTL_RSTT MAKE_REG_MASK(0x1,28) //
#define SDHC_SYSCTL_INITA MAKE_REG_MASK(0x1,27) //((uint32_t)0x08000000) // Initialization Active
#define SDHC_SYSCTL_RSTD MAKE_REG_MASK(0x1,26) //((uint32_t)0x04000000) // Software Reset For DAT Line
#define SDHC_SYSCTL_RSTC MAKE_REG_MASK(0x1,25) //((uint32_t)0x02000000) // Software Reset For CMD Line
#define SDHC_SYSCTL_RSTA MAKE_REG_MASK(0x1,24) //((uint32_t)0x01000000) // Software Reset For ALL
#define SDHC_SYSCTL_DTOCV(n) MAKE_REG_SET(n,0xF,16) //(uint32_t)(((n) & 0xF)<<16) // Data Timeout Counter Value
#define SDHC_SYSCTL_DTOCV_MASK MAKE_REG_MASK(0xF,16) //((uint32_t)0x000F0000)
#define SDHC_SYSCTL_SDCLKFS(n) MAKE_REG_SET(n,0xFF,8) //(uint32_t)(((n) & 0xFF)<<8) // SDCLK Frequency Select
#define SDHC_SYSCTL_SDCLKFS_MASK MAKE_REG_MASK(0xFF,8) //((uint32_t)0x0000FF00)
#define SDHC_SYSCTL_DVS(n) MAKE_REG_SET(n,0xF,4) //(uint32_t)(((n) & 0xF)<<4) // Divisor
#define SDHC_SYSCTL_DVS_MASK MAKE_REG_MASK(0xF,4) //((uint32_t)0x000000F0)

#define SDHC_SYSCTL_SDCLKEN ((uint32_t)0x00000008) // SD Clock Enable
#define SDHC_SYSCTL_PEREN ((uint32_t)0x00000004) // Peripheral Clock Enable
#define SDHC_SYSCTL_HCKEN ((uint32_t)0x00000002) // System Clock Enable
#define SDHC_SYSCTL_IPGEN ((uint32_t)0x00000001) // IPG Clock Enable

#define SDHC_IRQSTAT_DMAE MAKE_REG_MASK(0x1,28) //((uint32_t)0x10000000) // DMA Error
#define SDHC_IRQSTAT_TNE MAKE_REG_MASK(0x1,26) //
#define SDHC_IRQSTAT_AC12E MAKE_REG_MASK(0x1,24) //((uint32_t)0x01000000) // Auto CMD12 Error
#define SDHC_IRQSTAT_DEBE MAKE_REG_MASK(0x1,22) //((uint32_t)0x00400000) // Data End Bit Error
#define SDHC_IRQSTAT_DCE MAKE_REG_MASK(0x1,21) //((uint32_t)0x00200000) // Data CRC Error
#define SDHC_IRQSTAT_DTOE MAKE_REG_MASK(0x1,20) //((uint32_t)0x00100000) // Data Timeout Error
#define SDHC_IRQSTAT_CIE MAKE_REG_MASK(0x1,19) //((uint32_t)0x00080000) // Command Index Error
#define SDHC_IRQSTAT_CEBE MAKE_REG_MASK(0x1,18) //((uint32_t)0x00040000) // Command End Bit Error
#define SDHC_IRQSTAT_CCE MAKE_REG_MASK(0x1,17) //((uint32_t)0x00020000) // Command CRC Error
#define SDHC_IRQSTAT_CTOE MAKE_REG_MASK(0x1,16) //((uint32_t)0x00010000) // Command Timeout Error
#define SDHC_IRQSTAT_TP MAKE_REG_MASK(0x1,14) //
#define SDHC_IRQSTAT_RTE MAKE_REG_MASK(0x1,12) //
#define SDHC_IRQSTAT_CINT MAKE_REG_MASK(0x1,8) //((uint32_t)0x00000100) // Card Interrupt
#define SDHC_IRQSTAT_CRM MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // Card Removal
#define SDHC_IRQSTAT_CINS MAKE_REG_MASK(0x1,6) //((uint32_t)0x00000040) // Card Insertion
#define SDHC_IRQSTAT_BRR MAKE_REG_MASK(0x1,5) //((uint32_t)0x00000020) // Buffer Read Ready
#define SDHC_IRQSTAT_BWR MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Buffer Write Ready
#define SDHC_IRQSTAT_DINT MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008) // DMA Interrupt
#define SDHC_IRQSTAT_BGE MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004) // Block Gap Event
#define SDHC_IRQSTAT_TC MAKE_REG_MASK(0x1,1) //((uint32_t)0x00000002) // Transfer Complete
#define SDHC_IRQSTAT_CC MAKE_REG_MASK(0x1,0) //((uint32_t)0x00000001) // Command Complete

#define SDHC_IRQSTATEN_DMAESEN MAKE_REG_MASK(0x1,28) //((uint32_t)0x10000000) // DMA Error Status Enable
#define SDHC_IRQSTATEN_TNESEN MAKE_REG_MASK(0x1,26) //
#define SDHC_IRQSTATEN_AC12ESEN MAKE_REG_MASK(0x1,24) //((uint32_t)0x01000000) // Auto CMD12 Error Status Enable
#define SDHC_IRQSTATEN_DEBESEN MAKE_REG_MASK(0x1,22) //((uint32_t)0x00400000) // Data End Bit Error Status Enable
#define SDHC_IRQSTATEN_DCESEN MAKE_REG_MASK(0x1,21) //((uint32_t)0x00200000) // Data CRC Error Status Enable
#define SDHC_IRQSTATEN_DTOESEN MAKE_REG_MASK(0x1,20) //((uint32_t)0x00100000) // Data Timeout Error Status Enable
#define SDHC_IRQSTATEN_CIESEN MAKE_REG_MASK(0x1,19) //((uint32_t)0x00080000) // Command Index Error Status Enable
#define SDHC_IRQSTATEN_CEBESEN MAKE_REG_MASK(0x1,18) //((uint32_t)0x00040000) // Command End Bit Error Status Enable
#define SDHC_IRQSTATEN_CCESEN MAKE_REG_MASK(0x1,17) //((uint32_t)0x00020000) // Command CRC Error Status Enable
#define SDHC_IRQSTATEN_CTOESEN MAKE_REG_MASK(0x1,16) //((uint32_t)0x00010000) // Command Timeout Error Status Enable
#define SDHC_IRQSTATEN_TPSEN MAKE_REG_MASK(0x1,14) //
#define SDHC_IRQSTATEN_RTESEN MAKE_REG_MASK(0x1,12) //
#define SDHC_IRQSTATEN_CINTSEN MAKE_REG_MASK(0x1,8) //((uint32_t)0x00000100) // Card Interrupt Status Enable
#define SDHC_IRQSTATEN_CRMSEN MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // Card Removal Status Enable
#define SDHC_IRQSTATEN_CINSEN MAKE_REG_MASK(0x1,6) //((uint32_t)0x00000040) // Card Insertion Status Enable
#define SDHC_IRQSTATEN_BRRSEN MAKE_REG_MASK(0x1,5) //((uint32_t)0x00000020) // Buffer Read Ready Status Enable
#define SDHC_IRQSTATEN_BWRSEN MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Buffer Write Ready Status Enable
#define SDHC_IRQSTATEN_DINTSEN MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008) // DMA Interrupt Status Enable
#define SDHC_IRQSTATEN_BGESEN MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004) // Block Gap Event Status Enable
#define SDHC_IRQSTATEN_TCSEN MAKE_REG_MASK(0x1,1) //((uint32_t)0x00000002) // Transfer Complete Status Enable
#define SDHC_IRQSTATEN_CCSEN MAKE_REG_MASK(0x1,0) //((uint32_t)0x00000001) // Command Complete Status Enable

#define SDHC_IRQSIGEN_DMAEIEN MAKE_REG_MASK(0x1,28) //((uint32_t)0x10000000) // DMA Error Interrupt Enable
#define SDHC_IRQSIGEN_TNEIEN MAKE_REG_MASK(0x1,26) //
#define SDHC_IRQSIGEN_AC12EIEN MAKE_REG_MASK(0x1,24) //((uint32_t)0x01000000) // Auto CMD12 Error Interrupt Enable
#define SDHC_IRQSIGEN_DEBEIEN MAKE_REG_MASK(0x1,22) //((uint32_t)0x00400000) // Data End Bit Error Interrupt Enable
#define SDHC_IRQSIGEN_DCEIEN MAKE_REG_MASK(0x1,21) //((uint32_t)0x00200000) // Data CRC Error Interrupt Enable
#define SDHC_IRQSIGEN_DTOEIEN MAKE_REG_MASK(0x1,20) //((uint32_t)0x00100000) // Data Timeout Error Interrupt Enable
#define SDHC_IRQSIGEN_CIEIEN MAKE_REG_MASK(0x1,19) //((uint32_t)0x00080000) // Command Index Error Interrupt Enable
#define SDHC_IRQSIGEN_CEBEIEN MAKE_REG_MASK(0x1,18) //((uint32_t)0x00040000) // Command End Bit Error Interrupt Enable
#define SDHC_IRQSIGEN_CCEIEN MAKE_REG_MASK(0x1,17) //((uint32_t)0x00020000) // Command CRC Error Interrupt Enable
#define SDHC_IRQSIGEN_CTOEIEN MAKE_REG_MASK(0x1,16) //((uint32_t)0x00010000) // Command Timeout Error Interrupt Enable
#define SDHC_IRQSIGEN_TPIEN MAKE_REG_MASK(0x1,14) //
#define SDHC_IRQSIGEN_RTEIEN MAKE_REG_MASK(0x1,12) //
#define SDHC_IRQSIGEN_CINTIEN MAKE_REG_MASK(0x1,8) //((uint32_t)0x00000100) // Card Interrupt Interrupt Enable
#define SDHC_IRQSIGEN_CRMIEN MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // Card Removal Interrupt Enable
#define SDHC_IRQSIGEN_CINSIEN MAKE_REG_MASK(0x1,6) //((uint32_t)0x00000040) // Card Insertion Interrupt Enable
#define SDHC_IRQSIGEN_BRRIEN MAKE_REG_MASK(0x1,5) //((uint32_t)0x00000020) // Buffer Read Ready Interrupt Enable
#define SDHC_IRQSIGEN_BWRIEN MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Buffer Write Ready Interrupt Enable
#define SDHC_IRQSIGEN_DINTIEN MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008) // DMA Interrupt Interrupt Enable
#define SDHC_IRQSIGEN_BGEIEN MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004) // Block Gap Event Interrupt Enable
#define SDHC_IRQSIGEN_TCIEN MAKE_REG_MASK(0x1,1) //((uint32_t)0x00000002) // Transfer Complete Interrupt Enable
#define SDHC_IRQSIGEN_CCIEN MAKE_REG_MASK(0x1,0) //((uint32_t)0x00000001) // Command Complete Interrupt Enable

#define SDHC_AC12ERR_SMPLCLK_SEL MAKE_REG_MASK(0x1,23) //
#define SDHC_AC12ERR_EXEC_TUNING MAKE_REG_MASK(0x1,22) //
#define SDHC_AC12ERR_CNIBAC12E MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // Command Not Issued By Auto CMD12 Error
#define SDHC_AC12ERR_AC12IE MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Auto CMD12 Index Error
#define SDHC_AC12ERR_AC12CE MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008) // Auto CMD12 CRC Error
#define SDHC_AC12ERR_AC12EBE MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004) // Auto CMD12 End Bit Error
#define SDHC_AC12ERR_AC12TOE MAKE_REG_MASK(0x1,1) //((uint32_t)0x00000002) // Auto CMD12 Timeout Error
#define SDHC_AC12ERR_AC12NE MAKE_REG_MASK(0x1,0) //((uint32_t)0x00000001) // Auto CMD12 Not Executed

#define SDHC_HTCAPBLT_VS18 MAKE_REG_MASK(0x1,26) //
#define SDHC_HTCAPBLT_VS30 MAKE_REG_MASK(0x1,25) //
#define SDHC_HTCAPBLT_VS33 MAKE_REG_MASK(0x1,24) //
#define SDHC_HTCAPBLT_SRS MAKE_REG_MASK(0x1,23) //
#define SDHC_HTCAPBLT_DMAS MAKE_REG_MASK(0x1,22) //
#define SDHC_HTCAPBLT_HSS MAKE_REG_MASK(0x1,21) //
#define SDHC_HTCAPBLT_ADMAS MAKE_REG_MASK(0x1,20) //
#define SDHC_HTCAPBLT_MBL_VAL MAKE_REG_GET((USDHC1_HOST_CTRL_CAP),0x7,16) //
#define SDHC_HTCAPBLT_RETUN_MODE MAKE_REG_GET((USDHC1_HOST_CTRL_CAP),0x3,14) //
#define SDHC_HTCAPBLT_TUNE_SDR50 MAKE_REG_MASK(0x1,13) //
#define SDHC_HTCAPBLT_TIME_RETUN(n) MAKE_REG_SET(n,0xF,8) //

#define SDHC_WML_WR_BRSTLEN_MASK MAKE_REG_MASK(0x1F,24) //
#define SDHC_WML_RD_BRSTLEN_MASK MAKE_REG_MASK(0x1F,8) //
#define SDHC_WML_WR_WML_MASK MAKE_REG_MASK(0xFF,16) //
#define SDHC_WML_RD_WML_MASK MAKE_REG_MASK(0xFF,0) //
#define SDHC_WML_WR_BRSTLEN(n) MAKE_REG_SET(n,0x1F,24) //(uint32_t)(((n) & 0x7F)<<16) // Write Burst Len
#define SDHC_WML_RD_BRSTLEN(n) MAKE_REG_SET(n,0x1F,8) //(uint32_t)(((n) & 0x7F)<<0) // Read Burst Len
#define SDHC_WML_WR_WML(n) MAKE_REG_SET(n,0xFF,16) //(uint32_t)(((n) & 0x7F)<<16) // Write Watermark Level
#define SDHC_WML_RD_WML(n) MAKE_REG_SET(n,0xFF,0) //(uint32_t)(((n) & 0x7F)<<0) // Read Watermark Level
#define SDHC_WML_WRWML(n) MAKE_REG_SET(n,0xFF,16) //(uint32_t)(((n) & 0x7F)<<16) // Write Watermark Level
#define SDHC_WML_RDWML(n) MAKE_REG_SET(n,0xFF,0) //(uint32_t)(((n) & 0x7F)<<0) // Read Watermark Level

// Teensy 4.0 only
#define SDHC_MIX_CTRL_DMAEN MAKE_REG_MASK(0x1,0) //
#define SDHC_MIX_CTRL_BCEN MAKE_REG_MASK(0x1,1) //
#define SDHC_MIX_CTRL_AC12EN MAKE_REG_MASK(0x1,2) //
#define SDHC_MIX_CTRL_DDR_EN MAKE_REG_MASK(0x1,3) //
#define SDHC_MIX_CTRL_DTDSEL MAKE_REG_MASK(0x1,4) //
#define SDHC_MIX_CTRL_MSBSEL MAKE_REG_MASK(0x1,5) //
#define SDHC_MIX_CTRL_NIBBLE_POS MAKE_REG_MASK(0x1,6) //
#define SDHC_MIX_CTRL_AC23EN MAKE_REG_MASK(0x1,7) //

#define SDHC_FEVT_CINT MAKE_REG_MASK(0x1,31) //((uint32_t)0x80000000) // Force Event Card Interrupt
#define SDHC_FEVT_DMAE MAKE_REG_MASK(0x1,28) //((uint32_t)0x10000000) // Force Event DMA Error
#define SDHC_FEVT_AC12E MAKE_REG_MASK(0x1,24) //((uint32_t)0x01000000) // Force Event Auto CMD12 Error
#define SDHC_FEVT_DEBE MAKE_REG_MASK(0x1,22) //((uint32_t)0x00400000) // Force Event Data End Bit Error
#define SDHC_FEVT_DCE MAKE_REG_MASK(0x1,21) //((uint32_t)0x00200000) // Force Event Data CRC Error
#define SDHC_FEVT_DTOE MAKE_REG_MASK(0x1,20) //((uint32_t)0x00100000) // Force Event Data Timeout Error
#define SDHC_FEVT_CIE MAKE_REG_MASK(0x1,19) //((uint32_t)0x00080000) // Force Event Command Index Error
#define SDHC_FEVT_CEBE MAKE_REG_MASK(0x1,18) //((uint32_t)0x00040000) // Force Event Command End Bit Error
#define SDHC_FEVT_CCE MAKE_REG_MASK(0x1,17) //((uint32_t)0x00020000) // Force Event Command CRC Error
#define SDHC_FEVT_CTOE MAKE_REG_MASK(0x1,16) //((uint32_t)0x00010000) // Force Event Command Timeout Error
#define SDHC_FEVT_CNIBAC12E MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // Force Event Command Not Executed By Auto Command 12 Error
#define SDHC_FEVT_AC12IE MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Force Event Auto Command 12 Index Error
#define SDHC_FEVT_AC12EBE MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008) // Force Event Auto Command 12 End Bit Error
#define SDHC_FEVT_AC12CE MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004) // Force Event Auto Command 12 CRC Error
#define SDHC_FEVT_AC12TOE MAKE_REG_MASK(0x1,1) //((uint32_t)0x00000002) // Force Event Auto Command 12 Time Out Error
#define SDHC_FEVT_AC12NE MAKE_REG_MASK(0x1,0) //((uint32_t)0x00000001) // Force Event Auto Command 12 Not Executed

#define SDHC_ADMAES_ADMADCE MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008)
#define SDHC_ADMAES_ADMALME MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004)
#define SDHC_ADMAES_ADMAES_MASK MAKE_REG_MASK(0x3,0) //((uint32_t)0x00000003)

#define SDHC_MMCBOOT_BOOTBLKCNT(n) MAKE_REG_MASK(0xFF,16) //(uint32_t)(((n) & 0xFFF)<<16) // stop at block gap value of automatic mode
#define SDHC_MMCBOOT_AUTOSABGEN MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // enable auto stop at block gap function
#define SDHC_MMCBOOT_BOOTEN MAKE_REG_MASK(0x1,6) //((uint32_t)0x00000040) // Boot Mode Enable
#define SDHC_MMCBOOT_BOOTMODE MAKE_REG_MASK(0x1,5) //((uint32_t)0x00000020) // Boot Mode Select
#define SDHC_MMCBOOT_BOOTACK MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Boot Ack Mode Select
#define SDHC_MMCBOOT_DTOCVACK(n) MAKE_REG_MASK(0xF,0) //(uint32_t)(((n) & 0xF)<<0) // Boot ACK Time Out Counter Value
//#define SDHC_HOSTVER (*(volatile uint32_t *)0x400B10FC) // Host Controller Version

#define CCM_ANALOG_PFD_528_PFD0_FRAC_MASK 0x3f
#define CCM_ANALOG_PFD_528_PFD0_FRAC(n) ((n) & CCM_ANALOG_PFD_528_PFD0_FRAC_MASK)
#define CCM_ANALOG_PFD_528_PFD1_FRAC_MASK (0x3f<<8)
#define CCM_ANALOG_PFD_528_PFD1_FRAC(n) (((n)<<8) & CCM_ANALOG_PFD_528_PFD1_FRAC_MASK)
#define CCM_ANALOG_PFD_528_PFD2_FRAC_MASK (0x3f<<16)
#define CCM_ANALOG_PFD_528_PFD2_FRAC(n) (((n)<<16) & CCM_ANALOG_PFD_528_PFD2_FRAC_MASK)
#define CCM_ANALOG_PFD_528_PFD3_FRAC_MASK ((0x3f<<24)
#define CCM_ANALOG_PFD_528_PFD3_FRAC(n) (((n)<<24) & CCM_ANALOG_PFD_528_PFD3_FRAC_MASK)

#define SDHC_DSADDR (USDHC1_DS_ADDR ) // DMA System Address register
#define SDHC_BLKATTR (USDHC1_BLK_ATT) // Block Attributes register
#define SDHC_CMDARG (USDHC1_CMD_ARG) // Command Argument register
#define SDHC_XFERTYP (USDHC1_CMD_XFR_TYP) // Transfer Type register
#define SDHC_CMDRSP0 (USDHC1_CMD_RSP0) // Command Response 0
#define SDHC_CMDRSP1 (USDHC1_CMD_RSP1) // Command Response 1
#define SDHC_CMDRSP2 (USDHC1_CMD_RSP2) // Command Response 2
#define SDHC_CMDRSP3 (USDHC1_CMD_RSP3) // Command Response 3
#define SDHC_DATPORT (USDHC1_DATA_BUFF_ACC_PORT) // Buffer Data Port register
#define SDHC_PRSSTAT (USDHC1_PRES_STATE) // Present State register
#define SDHC_PROCTL (USDHC1_PROT_CTRL) // Protocol Control register
#define SDHC_SYSCTL (USDHC1_SYS_CTRL) // System Control register
#define SDHC_IRQSTAT (USDHC1_INT_STATUS) // Interrupt Status register
#define SDHC_IRQSTATEN (USDHC1_INT_STATUS_EN) // Interrupt Status Enable register
#define SDHC_IRQSIGEN (USDHC1_INT_SIGNAL_EN) // Interrupt Signal Enable register
#define SDHC_AC12ERR (USDHC1_AUTOCMD12_ERR_STATUS) // Auto CMD12 Error Status Register
#define SDHC_HTCAPBLT (USDHC1_HOST_CTRL_CAP) // Host Controller Capabilities
#define SDHC_WML (USDHC1_WTMK_LVL) // Watermark Level Register
#define SDHC_MIX_CTRL (USDHC1_MIX_CTRL) // Mixer Control
#define SDHC_FEVT (USDHC1_FORCE_EVENT) // Force Event register
#define SDHC_ADMAES (USDHC1_ADMA_ERR_STATUS) // ADMA Error Status register
#define SDHC_ADSADDR (USDHC1_ADMA_SYS_ADDR) // ADMA System Addressregister
#define SDHC_VENDOR (USDHC1_VEND_SPEC) // Vendor Specific register
#define SDHC_MMCBOOT (USDHC1_MMC_BOOT) // MMC Boot register
#define SDHC_VENDOR2 (USDHC2_VEND_SPEC2) // Vendor Specific2 register
//
#define IRQ_SDHC IRQ_SDHC1

#define SDHC_MAX_DVS (0xF + 1U)
#define SDHC_MAX_CLKFS (0xFF + 1U)
#define SDHC_PREV_DVS(x) ((x) -= 1U)
#define SDHC_PREV_CLKFS(x, y) ((x) >>= (y))

#define CCM_CSCDR1_USDHC1_CLK_PODF_MASK (0x7<<11)
#define CCM_CSCDR1_USDHC1_CLK_PODF(n) (((n)&0x7)<<11)

#define IOMUXC_SW_PAD_CTL_PAD_SRE ((0x1<)<0)
#define IOMUXC_SW_PAD_CTL_PAD_PKE ((0x1)<<12)
#define IOMUXC_SW_PAD_CTL_PAD_PUE ((0x1)<<13)
#define IOMUXC_SW_PAD_CTL_PAD_HYS ((0x1)<<16)
#define IOMUXC_SW_PAD_CTL_PAD_SPEED(n) (((n)&0x3)<<6)
#define IOMUXC_SW_PAD_CTL_PAD_PUS(n) (((n)&0x3)<<14)
#define IOMUXC_SW_PAD_CTL_PAD_PUS_MASK ((0x3)<<14)
#define IOMUXC_SW_PAD_CTL_PAD_DSE(n) (((n)&0x7)<<3)
#define IOMUXC_SW_PAD_CTL_PAD_DSE_MASK ((0x7)<<3)
#endif // defined(__IMXRT1062__)
#endif // SdioTeensy_h

+ 3
- 0
src/SdFatConfig.h View File

@@ -277,6 +277,9 @@
#endif // SDCARD_SPI
#define HAS_SDIO_CLASS 1
#endif // defined(__MK64FX512__) || defined(__MK66FX1M0__)
#if defined(__IMXRT1062__)
#define HAS_SDIO_CLASS 1
#endif // defined(__IMXRT1062__)
//------------------------------------------------------------------------------
/**
* Determine the default SPI configuration.

Loading…
Cancel
Save