Update KSDK SDHC driver for K64F & K66F

1. Use function pointer for interrupt handler, this should reduce the code-size
   for applications that do not use this driver
2. Fix the wait for initialization of the SD card
3. Fix SDHC driver support for non-word aligned accesses
4. Remove some redundant code & assert function calls.
5. Updated various comments

Signed-off-by: Mahadevan Mahesh <Mahesh.Mahadevan@nxp.com>
pull/2775/head
Mahadevan Mahesh 2016-09-21 12:04:58 -05:00
parent e4a40cd6a7
commit c3b4a43bec
4 changed files with 374 additions and 262 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, Freescale Semiconductor, Inc. * Copyright (c) 2016, Freescale Semiconductor, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -50,6 +50,9 @@
#define SDHC_NEXT_CLKFS(x) ((x) <<= 1U) #define SDHC_NEXT_CLKFS(x) ((x) <<= 1U)
#define SDHC_PREV_CLKFS(x) ((x) >>= 1U) #define SDHC_PREV_CLKFS(x) ((x) >>= 1U)
/* Typedef for interrupt handler. */
typedef void (*sdhc_isr_t)(SDHC_Type *base, sdhc_handle_t *handle);
/*! @brief ADMA table configuration */ /*! @brief ADMA table configuration */
typedef struct _sdhc_adma_table_config typedef struct _sdhc_adma_table_config
{ {
@ -230,6 +233,9 @@ static const IRQn_Type s_sdhcIRQ[] = SDHC_IRQS;
/*! @brief SDHC clock array name */ /*! @brief SDHC clock array name */
static const clock_ip_name_t s_sdhcClock[] = SDHC_CLOCKS; static const clock_ip_name_t s_sdhcClock[] = SDHC_CLOCKS;
/* SDHC ISR for transactional APIs. */
static sdhc_isr_t s_sdhcIsr;
/******************************************************************************* /*******************************************************************************
* Code * Code
******************************************************************************/ ******************************************************************************/
@ -288,10 +294,8 @@ static void SDHC_SetTransferInterrupt(SDHC_Type *base, bool usingInterruptSignal
static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_data_t *data) static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_data_t *data)
{ {
assert(command);
uint32_t flags = 0U; uint32_t flags = 0U;
sdhc_transfer_config_t sdhcTransferConfig; sdhc_transfer_config_t sdhcTransferConfig = {0};
sdhc_dma_mode_t dmaMode; sdhc_dma_mode_t dmaMode;
/* Define the flag corresponding to each response type. */ /* Define the flag corresponding to each response type. */
@ -315,7 +319,7 @@ static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_da
flags |= (kSDHC_ResponseLength48Flag); flags |= (kSDHC_ResponseLength48Flag);
break; break;
case kSDHC_ResponseTypeR5: /* Response 5 */ case kSDHC_ResponseTypeR5: /* Response 5 */
flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag); flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag);
break; break;
case kSDHC_ResponseTypeR5b: /* Response 5 with busy */ case kSDHC_ResponseTypeR5b: /* Response 5 with busy */
flags |= (kSDHC_ResponseLength48BusyFlag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag); flags |= (kSDHC_ResponseLength48BusyFlag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag);
@ -355,18 +359,9 @@ static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_da
flags |= kSDHC_EnableAutoCommand12Flag; flags |= kSDHC_EnableAutoCommand12Flag;
} }
} }
if (data->blockCount > SDHC_MAX_BLOCK_COUNT)
{
sdhcTransferConfig.dataBlockSize = data->blockSize;
sdhcTransferConfig.dataBlockCount = SDHC_MAX_BLOCK_COUNT;
flags &= ~(uint32_t)kSDHC_EnableBlockCountFlag; sdhcTransferConfig.dataBlockSize = data->blockSize;
} sdhcTransferConfig.dataBlockCount = data->blockCount;
else
{
sdhcTransferConfig.dataBlockSize = data->blockSize;
sdhcTransferConfig.dataBlockCount = data->blockCount;
}
} }
else else
{ {
@ -382,8 +377,6 @@ static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_da
static void SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command) static void SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command)
{ {
assert(command);
uint32_t i; uint32_t i;
if (command->responseType != kSDHC_ResponseTypeNone) if (command->responseType != kSDHC_ResponseTypeNone)
@ -412,13 +405,22 @@ static void SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command
static uint32_t SDHC_ReadDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords) static uint32_t SDHC_ReadDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords)
{ {
assert(data);
uint32_t i; uint32_t i;
uint32_t totalWords; uint32_t totalWords;
uint32_t wordsCanBeRead; /* The words can be read at this time. */ uint32_t wordsCanBeRead; /* The words can be read at this time. */
uint32_t readWatermark = ((base->WML & SDHC_WML_RDWML_MASK) >> SDHC_WML_RDWML_SHIFT); uint32_t readWatermark = ((base->WML & SDHC_WML_RDWML_MASK) >> SDHC_WML_RDWML_SHIFT);
/*
* Add non aligned access support ,user need make sure your buffer size is big
* enough to hold the data,in other words,user need make sure the buffer size
* is 4 byte aligned
*/
if (data->blockSize % sizeof(uint32_t) != 0U)
{
data->blockSize +=
sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */
}
totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t)); totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t));
/* If watermark level is equal or bigger than totalWords, transfers totalWords data. */ /* If watermark level is equal or bigger than totalWords, transfers totalWords data. */
@ -451,12 +453,21 @@ static uint32_t SDHC_ReadDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t t
static status_t SDHC_ReadByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data) static status_t SDHC_ReadByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data)
{ {
assert(data);
uint32_t totalWords; uint32_t totalWords;
uint32_t transferredWords = 0U; uint32_t transferredWords = 0U;
status_t error = kStatus_Success; status_t error = kStatus_Success;
/*
* Add non aligned access support ,user need make sure your buffer size is big
* enough to hold the data,in other words,user need make sure the buffer size
* is 4 byte aligned
*/
if (data->blockSize % sizeof(uint32_t) != 0U)
{
data->blockSize +=
sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */
}
totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t)); totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t));
while ((error == kStatus_Success) && (transferredWords < totalWords)) while ((error == kStatus_Success) && (transferredWords < totalWords))
@ -489,13 +500,22 @@ static status_t SDHC_ReadByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data)
static uint32_t SDHC_WriteDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords) static uint32_t SDHC_WriteDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords)
{ {
assert(data);
uint32_t i; uint32_t i;
uint32_t totalWords; uint32_t totalWords;
uint32_t wordsCanBeWrote; /* Words can be wrote at this time. */ uint32_t wordsCanBeWrote; /* Words can be wrote at this time. */
uint32_t writeWatermark = ((base->WML & SDHC_WML_WRWML_MASK) >> SDHC_WML_WRWML_SHIFT); uint32_t writeWatermark = ((base->WML & SDHC_WML_WRWML_MASK) >> SDHC_WML_WRWML_SHIFT);
/*
* Add non aligned access support ,user need make sure your buffer size is big
* enough to hold the data,in other words,user need make sure the buffer size
* is 4 byte aligned
*/
if (data->blockSize % sizeof(uint32_t) != 0U)
{
data->blockSize +=
sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */
}
totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t)); totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t));
/* If watermark level is equal or bigger than totalWords, transfers totalWords data.*/ /* If watermark level is equal or bigger than totalWords, transfers totalWords data.*/
@ -528,12 +548,21 @@ static uint32_t SDHC_WriteDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t
static status_t SDHC_WriteByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data) static status_t SDHC_WriteByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data)
{ {
assert(data);
uint32_t totalWords; uint32_t totalWords;
uint32_t transferredWords = 0U; uint32_t transferredWords = 0U;
status_t error = kStatus_Success; status_t error = kStatus_Success;
/*
* Add non aligned access support ,user need make sure your buffer size is big
* enough to hold the data,in other words,user need make sure the buffer size
* is 4 byte aligned
*/
if (data->blockSize % sizeof(uint32_t) != 0U)
{
data->blockSize +=
sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */
}
totalWords = (data->blockCount * data->blockSize) / sizeof(uint32_t); totalWords = (data->blockCount * data->blockSize) / sizeof(uint32_t);
while ((error == kStatus_Success) && (transferredWords < totalWords)) while ((error == kStatus_Success) && (transferredWords < totalWords))
@ -576,8 +605,6 @@ static status_t SDHC_WriteByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data)
static status_t SDHC_SendCommandBlocking(SDHC_Type *base, sdhc_command_t *command) static status_t SDHC_SendCommandBlocking(SDHC_Type *base, sdhc_command_t *command)
{ {
assert(command);
status_t error = kStatus_Success; status_t error = kStatus_Success;
/* Wait command complete or SDHC encounters error. */ /* Wait command complete or SDHC encounters error. */
@ -602,8 +629,6 @@ static status_t SDHC_SendCommandBlocking(SDHC_Type *base, sdhc_command_t *comman
static status_t SDHC_TransferByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data) static status_t SDHC_TransferByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data)
{ {
assert(data);
status_t error = kStatus_Success; status_t error = kStatus_Success;
if (data->rxData) if (data->rxData)
@ -669,8 +694,6 @@ static status_t SDHC_TransferDataBlocking(sdhc_dma_mode_t dmaMode, SDHC_Type *ba
static void SDHC_TransferHandleCardDetect(sdhc_handle_t *handle, uint32_t interruptFlags) static void SDHC_TransferHandleCardDetect(sdhc_handle_t *handle, uint32_t interruptFlags)
{ {
assert(interruptFlags & kSDHC_CardDetectFlag);
if (interruptFlags & kSDHC_CardInsertionFlag) if (interruptFlags & kSDHC_CardInsertionFlag)
{ {
if (handle->callback.CardInserted) if (handle->callback.CardInserted)
@ -689,7 +712,7 @@ static void SDHC_TransferHandleCardDetect(sdhc_handle_t *handle, uint32_t interr
static void SDHC_TransferHandleCommand(SDHC_Type *base, sdhc_handle_t *handle, uint32_t interruptFlags) static void SDHC_TransferHandleCommand(SDHC_Type *base, sdhc_handle_t *handle, uint32_t interruptFlags)
{ {
assert(interruptFlags & kSDHC_CommandFlag); assert(handle->command);
if ((interruptFlags & kSDHC_CommandErrorFlag) && (!(handle->data)) && (handle->callback.TransferComplete)) if ((interruptFlags & kSDHC_CommandErrorFlag) && (!(handle->data)) && (handle->callback.TransferComplete))
{ {
@ -709,7 +732,6 @@ static void SDHC_TransferHandleCommand(SDHC_Type *base, sdhc_handle_t *handle, u
static void SDHC_TransferHandleData(SDHC_Type *base, sdhc_handle_t *handle, uint32_t interruptFlags) static void SDHC_TransferHandleData(SDHC_Type *base, sdhc_handle_t *handle, uint32_t interruptFlags)
{ {
assert(handle->data); assert(handle->data);
assert(interruptFlags & kSDHC_DataFlag);
if ((!(handle->data->enableIgnoreError)) && (interruptFlags & (kSDHC_DataErrorFlag | kSDHC_DmaErrorFlag)) && if ((!(handle->data->enableIgnoreError)) && (interruptFlags & (kSDHC_DataErrorFlag | kSDHC_DmaErrorFlag)) &&
(handle->callback.TransferComplete)) (handle->callback.TransferComplete))
@ -759,6 +781,8 @@ void SDHC_Init(SDHC_Type *base, const sdhc_config_t *config)
#if !defined FSL_SDHC_ENABLE_ADMA1 #if !defined FSL_SDHC_ENABLE_ADMA1
assert(config->dmaMode != kSDHC_DmaModeAdma1); assert(config->dmaMode != kSDHC_DmaModeAdma1);
#endif /* FSL_SDHC_ENABLE_ADMA1 */ #endif /* FSL_SDHC_ENABLE_ADMA1 */
assert((config->writeWatermarkLevel >= 1U) && (config->writeWatermarkLevel <= 128U));
assert((config->readWatermarkLevel >= 1U) && (config->readWatermarkLevel <= 128U));
uint32_t proctl; uint32_t proctl;
uint32_t wml; uint32_t wml;
@ -850,7 +874,8 @@ void SDHC_GetCapability(SDHC_Type *base, sdhc_capability_t *capability)
uint32_t SDHC_SetSdClock(SDHC_Type *base, uint32_t srcClock_Hz, uint32_t busClock_Hz) uint32_t SDHC_SetSdClock(SDHC_Type *base, uint32_t srcClock_Hz, uint32_t busClock_Hz)
{ {
assert(busClock_Hz && (busClock_Hz < srcClock_Hz)); assert(srcClock_Hz != 0U);
assert((busClock_Hz != 0U) && (busClock_Hz <= srcClock_Hz));
uint32_t divisor; uint32_t divisor;
uint32_t prescaler; uint32_t prescaler;
@ -898,7 +923,7 @@ bool SDHC_SetCardActive(SDHC_Type *base, uint32_t timeout)
{ {
base->SYSCTL |= SDHC_SYSCTL_INITA_MASK; base->SYSCTL |= SDHC_SYSCTL_INITA_MASK;
/* Delay some time to wait card become active state. */ /* Delay some time to wait card become active state. */
while (!(base->SYSCTL & SDHC_SYSCTL_INITA_MASK)) while (base->SYSCTL & SDHC_SYSCTL_INITA_MASK)
{ {
if (!timeout) if (!timeout)
{ {
@ -913,6 +938,8 @@ bool SDHC_SetCardActive(SDHC_Type *base, uint32_t timeout)
void SDHC_SetTransferConfig(SDHC_Type *base, const sdhc_transfer_config_t *config) void SDHC_SetTransferConfig(SDHC_Type *base, const sdhc_transfer_config_t *config)
{ {
assert(config); assert(config);
assert(config->dataBlockSize <= (SDHC_BLKATTR_BLKSIZE_MASK >> SDHC_BLKATTR_BLKSIZE_SHIFT));
assert(config->dataBlockCount <= (SDHC_BLKATTR_BLKCNT_MASK >> SDHC_BLKATTR_BLKCNT_SHIFT));
base->BLKATTR = ((base->BLKATTR & ~(SDHC_BLKATTR_BLKSIZE_MASK | SDHC_BLKATTR_BLKCNT_MASK)) | base->BLKATTR = ((base->BLKATTR & ~(SDHC_BLKATTR_BLKSIZE_MASK | SDHC_BLKATTR_BLKCNT_MASK)) |
(SDHC_BLKATTR_BLKSIZE(config->dataBlockSize) | SDHC_BLKATTR_BLKCNT(config->dataBlockCount))); (SDHC_BLKATTR_BLKSIZE(config->dataBlockSize) | SDHC_BLKATTR_BLKCNT(config->dataBlockCount)));
@ -975,12 +1002,13 @@ void SDHC_EnableSdioControl(SDHC_Type *base, uint32_t mask, bool enable)
void SDHC_SetMmcBootConfig(SDHC_Type *base, const sdhc_boot_config_t *config) void SDHC_SetMmcBootConfig(SDHC_Type *base, const sdhc_boot_config_t *config)
{ {
assert(config); assert(config);
assert(config->ackTimeoutCount <= (SDHC_MMCBOOT_DTOCVACK_MASK >> SDHC_MMCBOOT_DTOCVACK_SHIFT));
assert(config->blockCount <= (SDHC_MMCBOOT_BOOTBLKCNT_MASK >> SDHC_MMCBOOT_BOOTBLKCNT_SHIFT));
uint32_t mmcboot; uint32_t mmcboot = 0U;
mmcboot = base->MMCBOOT; mmcboot = (SDHC_MMCBOOT_DTOCVACK(config->ackTimeoutCount) | SDHC_MMCBOOT_BOOTMODE(config->bootMode) |
mmcboot |= (SDHC_MMCBOOT_DTOCVACK(config->ackTimeoutCount) | SDHC_MMCBOOT_BOOTMODE(config->bootMode) | SDHC_MMCBOOT_BOOTBLKCNT(config->blockCount));
SDHC_MMCBOOT_BOOTBLKCNT(config->blockCount));
if (config->enableBootAck) if (config->enableBootAck)
{ {
mmcboot |= SDHC_MMCBOOT_BOOTACK_MASK; mmcboot |= SDHC_MMCBOOT_BOOTACK_MASK;
@ -1016,6 +1044,9 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base,
(!data) || (!dataBytes) (!data) || (!dataBytes)
#if !defined FSL_SDHC_ENABLE_ADMA1 #if !defined FSL_SDHC_ENABLE_ADMA1
|| (dmaMode == kSDHC_DmaModeAdma1) || (dmaMode == kSDHC_DmaModeAdma1)
#else
/* Buffer address configured in ADMA1 descriptor must be 4KB aligned. */
|| ((dmaMode == kSDHC_DmaModeAdma1) && (((uint32_t)data % SDHC_ADMA1_LENGTH_ALIGN) != 0U))
#endif /* FSL_SDHC_ENABLE_ADMA1 */ #endif /* FSL_SDHC_ENABLE_ADMA1 */
) )
{ {
@ -1029,6 +1060,17 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base,
break; break;
#if defined FSL_SDHC_ENABLE_ADMA1 #if defined FSL_SDHC_ENABLE_ADMA1
case kSDHC_DmaModeAdma1: case kSDHC_DmaModeAdma1:
/*
* Add non aligned access support ,user need make sure your buffer size is big
* enough to hold the data,in other words,user need make sure the buffer size
* is 4 byte aligned
*/
if (dataBytes % sizeof(uint32_t) != 0U)
{
dataBytes +=
sizeof(uint32_t) - (dataBytes % sizeof(uint32_t)); /* make the data length as word-aligned */
}
startAddress = data; startAddress = data;
/* Check if ADMA descriptor's number is enough. */ /* Check if ADMA descriptor's number is enough. */
entries = ((dataBytes / SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U); entries = ((dataBytes / SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U);
@ -1054,7 +1096,7 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base,
adma1EntryAddress[i + 1U] = adma1EntryAddress[i + 1U] =
((uint32_t)(startAddress) << SDHC_ADMA1_DESCRIPTOR_ADDRESS_SHIFT); ((uint32_t)(startAddress) << SDHC_ADMA1_DESCRIPTOR_ADDRESS_SHIFT);
adma1EntryAddress[i + 1U] |= adma1EntryAddress[i + 1U] |=
(SDHC_ADMA1_DESCRIPTOR_TYPE_TRANSFER | SDHC_ADMA1_DESCRIPTOR_END_MASK); (kSDHC_Adma1DescriptorTypeTransfer | kSDHC_Adma1DescriptorEndFlag);
} }
else else
{ {
@ -1075,6 +1117,17 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base,
break; break;
#endif /* FSL_SDHC_ENABLE_ADMA1 */ #endif /* FSL_SDHC_ENABLE_ADMA1 */
case kSDHC_DmaModeAdma2: case kSDHC_DmaModeAdma2:
/*
* Add non aligned access support ,user need make sure your buffer size is big
* enough to hold the data,in other words,user need make sure the buffer size
* is 4 byte aligned
*/
if (dataBytes % sizeof(uint32_t) != 0U)
{
dataBytes +=
sizeof(uint32_t) - (dataBytes % sizeof(uint32_t)); /* make the data length as word-aligned */
}
startAddress = data; startAddress = data;
/* Check if ADMA descriptor's number is enough. */ /* Check if ADMA descriptor's number is enough. */
entries = ((dataBytes / SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U); entries = ((dataBytes / SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U);
@ -1125,15 +1178,14 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base,
status_t SDHC_TransferBlocking(SDHC_Type *base, uint32_t *admaTable, uint32_t admaTableWords, sdhc_transfer_t *transfer) status_t SDHC_TransferBlocking(SDHC_Type *base, uint32_t *admaTable, uint32_t admaTableWords, sdhc_transfer_t *transfer)
{ {
assert(transfer); assert(transfer);
assert(transfer->command); /* Command must not be NULL, data can be NULL. */
status_t error = kStatus_Success; status_t error = kStatus_Success;
sdhc_dma_mode_t dmaMode = (sdhc_dma_mode_t)((base->PROCTL & SDHC_PROCTL_DMAS_MASK) >> SDHC_PROCTL_DMAS_SHIFT); sdhc_dma_mode_t dmaMode = (sdhc_dma_mode_t)((base->PROCTL & SDHC_PROCTL_DMAS_MASK) >> SDHC_PROCTL_DMAS_SHIFT);
sdhc_command_t *command = transfer->command; sdhc_command_t *command = transfer->command;
sdhc_data_t *data = transfer->data; sdhc_data_t *data = transfer->data;
/* DATA-PORT is 32-bit align, ADMA2 4 bytes align, ADMA1 is 4096 bytes align */ /* make sure the cmd/block count is valid */
if ((!command) || (data && (data->blockSize % 4U))) if ((!command) || (data && (data->blockCount > SDHC_MAX_BLOCK_COUNT)))
{ {
error = kStatus_InvalidArgument; error = kStatus_InvalidArgument;
} }
@ -1147,7 +1199,7 @@ status_t SDHC_TransferBlocking(SDHC_Type *base, uint32_t *admaTable, uint32_t ad
{ {
} }
/* Update ADMA descriptor table if data isn't NULL. */ /* Update ADMA descriptor table according to different DMA mode(no DMA, ADMA1, ADMA2).*/
if (data && (kStatus_Success != SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords, if (data && (kStatus_Success != SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords,
(data->rxData ? data->rxData : data->txData), (data->rxData ? data->rxData : data->txData),
(data->blockCount * data->blockSize)))) (data->blockCount * data->blockSize))))
@ -1156,9 +1208,8 @@ status_t SDHC_TransferBlocking(SDHC_Type *base, uint32_t *admaTable, uint32_t ad
} }
else else
{ {
SDHC_StartTransfer(base, command, data);
/* Send command and receive data. */ /* Send command and receive data. */
SDHC_StartTransfer(base, command, data);
if (kStatus_Success != SDHC_SendCommandBlocking(base, command)) if (kStatus_Success != SDHC_SendCommandBlocking(base, command))
{ {
error = kStatus_SDHC_SendCommandFailed; error = kStatus_SDHC_SendCommandFailed;
@ -1200,6 +1251,10 @@ void SDHC_TransferCreateHandle(SDHC_Type *base,
/* Enable interrupt in NVIC. */ /* Enable interrupt in NVIC. */
SDHC_SetTransferInterrupt(base, true); SDHC_SetTransferInterrupt(base, true);
/* save IRQ handler */
s_sdhcIsr = SDHC_TransferHandleIRQ;
EnableIRQ(s_sdhcIRQ[SDHC_GetInstance(base)]); EnableIRQ(s_sdhcIRQ[SDHC_GetInstance(base)]);
} }
@ -1213,8 +1268,8 @@ status_t SDHC_TransferNonBlocking(
sdhc_command_t *command = transfer->command; sdhc_command_t *command = transfer->command;
sdhc_data_t *data = transfer->data; sdhc_data_t *data = transfer->data;
/* DATA-PORT is 32-bit align, ADMA2 4 bytes align, ADMA1 is 4096 bytes align */ /* make sure cmd/block count is valid */
if ((!(transfer->command)) || ((transfer->data) && (transfer->data->blockSize % 4U))) if ((!command) || (data && (data->blockCount > SDHC_MAX_BLOCK_COUNT)))
{ {
error = kStatus_InvalidArgument; error = kStatus_InvalidArgument;
} }
@ -1228,7 +1283,7 @@ status_t SDHC_TransferNonBlocking(
} }
else else
{ {
/* Update ADMA descriptor table and reset transferred words if data isn't NULL. */ /* Update ADMA descriptor table according to different DMA mode(no DMA, ADMA1, ADMA2).*/
if (data && (kStatus_Success != SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords, if (data && (kStatus_Success != SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords,
(data->rxData ? data->rxData : data->txData), (data->rxData ? data->rxData : data->txData),
(data->blockCount * data->blockSize)))) (data->blockCount * data->blockSize))))
@ -1243,6 +1298,7 @@ status_t SDHC_TransferNonBlocking(
handle->interruptFlags = 0U; handle->interruptFlags = 0U;
/* transferredWords will only be updated in ISR when transfer way is DATAPORT. */ /* transferredWords will only be updated in ISR when transfer way is DATAPORT. */
handle->transferredWords = 0U; handle->transferredWords = 0U;
SDHC_StartTransfer(base, command, data); SDHC_StartTransfer(base, command, data);
} }
} }
@ -1289,6 +1345,6 @@ void SDHC_DriverIRQHandler(void)
{ {
assert(s_sdhcHandle[0]); assert(s_sdhcHandle[0]);
SDHC_TransferHandleIRQ(SDHC, s_sdhcHandle[0]); s_sdhcIsr(SDHC, s_sdhcHandle[0]);
} }
#endif #endif

View File

@ -37,16 +37,14 @@
* @{ * @{
*/ */
/*! @file */
/****************************************************************************** /******************************************************************************
* Definitions. * Definitions.
*****************************************************************************/ *****************************************************************************/
/*! @name Driver version */ /*! @name Driver version */
/*@{*/ /*@{*/
/*! @brief Driver version 2.0.0. */ /*! @brief Driver version 2.1.2. */
#define FSL_SDHC_DRIVER_VERSION (MAKE_VERSION(2U, 0U, 0U)) #define FSL_SDHC_DRIVER_VERSION (MAKE_VERSION(2U, 1U, 2U))
/*@}*/ /*@}*/
/*! @brief Maximum block count can be set one time */ /*! @brief Maximum block count can be set one time */
@ -350,7 +348,7 @@ typedef enum _sdhc_response_type
#define SDHC_ADMA1_DESCRIPTOR_LENGTH_SHIFT (12U) #define SDHC_ADMA1_DESCRIPTOR_LENGTH_SHIFT (12U)
/*! @brief The mask for LENGTH field in ADMA1's descriptor */ /*! @brief The mask for LENGTH field in ADMA1's descriptor */
#define SDHC_ADMA1_DESCRIPTOR_LENGTH_MASK (0xFFFFU) #define SDHC_ADMA1_DESCRIPTOR_LENGTH_MASK (0xFFFFU)
/*! @brief The max value of LENGTH filed in ADMA1's descriptor */ /*! @brief The maximum value of LENGTH filed in ADMA1's descriptor */
#define SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY (SDHC_ADMA1_DESCRIPTOR_LENGTH_MASK + 1U) #define SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY (SDHC_ADMA1_DESCRIPTOR_LENGTH_MASK + 1U)
/*! @brief The mask for the control/status field in ADMA1 descriptor */ /*! @brief The mask for the control/status field in ADMA1 descriptor */
@ -395,7 +393,7 @@ enum _sdhc_adma1_descriptor_flag
#define SDHC_ADMA2_DESCRIPTOR_LENGTH_SHIFT (16U) #define SDHC_ADMA2_DESCRIPTOR_LENGTH_SHIFT (16U)
/*! @brief The bit mask for LENGTH field in ADMA2's descriptor */ /*! @brief The bit mask for LENGTH field in ADMA2's descriptor */
#define SDHC_ADMA2_DESCRIPTOR_LENGTH_MASK (0xFFFFU) #define SDHC_ADMA2_DESCRIPTOR_LENGTH_MASK (0xFFFFU)
/*! @brief The max value of LENGTH field in ADMA2's descriptor */ /*! @brief The maximum value of LENGTH field in ADMA2's descriptor */
#define SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY (SDHC_ADMA2_DESCRIPTOR_LENGTH_MASK) #define SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY (SDHC_ADMA2_DESCRIPTOR_LENGTH_MASK)
/*! @brief ADMA1 descriptor control and status mask */ /*! @brief ADMA1 descriptor control and status mask */
@ -416,10 +414,10 @@ enum _sdhc_adma2_descriptor_flag
kSDHC_Adma2DescriptorValidFlag), /*!< Link type */ kSDHC_Adma2DescriptorValidFlag), /*!< Link type */
}; };
/*! @brief Define the adma1 descriptor structure. */ /*! @brief Defines the adma1 descriptor structure. */
typedef uint32_t sdhc_adma1_descriptor_t; typedef uint32_t sdhc_adma1_descriptor_t;
/*! @brief Define the ADMA2 descriptor structure. */ /*! @brief Defines the ADMA2 descriptor structure. */
typedef struct _sdhc_adma2_descriptor typedef struct _sdhc_adma2_descriptor
{ {
uint32_t attribute; /*!< The control and status field */ uint32_t attribute; /*!< The control and status field */
@ -429,7 +427,7 @@ typedef struct _sdhc_adma2_descriptor
/*! /*!
* @brief SDHC capability information. * @brief SDHC capability information.
* *
* Define structure to save the capability information of SDHC. * Defines a structure to save the capability information of SDHC.
*/ */
typedef struct _sdhc_capability typedef struct _sdhc_capability
{ {
@ -457,9 +455,9 @@ typedef struct _sdhc_transfer_config
/*! @brief Data structure to configure the MMC boot feature */ /*! @brief Data structure to configure the MMC boot feature */
typedef struct _sdhc_boot_config typedef struct _sdhc_boot_config
{ {
uint32_t ackTimeoutCount; /*!< Timeout value for the boot ACK */ uint32_t ackTimeoutCount; /*!< Timeout value for the boot ACK. The available range is 0 ~ 15. */
sdhc_boot_mode_t bootMode; /*!< Boot mode selection. */ sdhc_boot_mode_t bootMode; /*!< Boot mode selection. */
uint32_t blockCount; /*!< Stop at block gap value of automatic mode */ uint32_t blockCount; /*!< Stop at block gap value of automatic mode. Available range is 0 ~ 65535. */
bool enableBootAck; /*!< Enable or disable boot ACK */ bool enableBootAck; /*!< Enable or disable boot ACK */
bool enableBoot; /*!< Enable or disable fast boot */ bool enableBoot; /*!< Enable or disable fast boot */
bool enableAutoStopAtBlockGap; /*!< Enable or disable auto stop at block gap function in boot period */ bool enableAutoStopAtBlockGap; /*!< Enable or disable auto stop at block gap function in boot period */
@ -471,15 +469,15 @@ typedef struct _sdhc_config
bool cardDetectDat3; /*!< Enable DAT3 as card detection pin */ bool cardDetectDat3; /*!< Enable DAT3 as card detection pin */
sdhc_endian_mode_t endianMode; /*!< Endian mode */ sdhc_endian_mode_t endianMode; /*!< Endian mode */
sdhc_dma_mode_t dmaMode; /*!< DMA mode */ sdhc_dma_mode_t dmaMode; /*!< DMA mode */
uint32_t readWatermarkLevel; /*!< Watermark level for DMA read operation */ uint32_t readWatermarkLevel; /*!< Watermark level for DMA read operation. Available range is 1 ~ 128. */
uint32_t writeWatermarkLevel; /*!< Watermark level for DMA write operation */ uint32_t writeWatermarkLevel; /*!< Watermark level for DMA write operation. Available range is 1 ~ 128. */
} sdhc_config_t; } sdhc_config_t;
/*! /*!
* @brief Card data descriptor * @brief Card data descriptor
* *
* Define structure to contain data-related attribute. 'enableIgnoreError' is used for the case that upper card driver * Defines a structure to contain data-related attribute. 'enableIgnoreError' is used for the case that upper card
* want to ignore the error event to read/write all the data not to stop read/write immediately when error event * driver want to ignore the error event to read/write all the data not to stop read/write immediately when error event
* happen for example bus testing procedure for MMC card. * happen for example bus testing procedure for MMC card.
*/ */
typedef struct _sdhc_data typedef struct _sdhc_data
@ -530,10 +528,11 @@ typedef struct _sdhc_transfer_callback
} sdhc_transfer_callback_t; } sdhc_transfer_callback_t;
/*! /*!
* @brief Host descriptor * @brief SDHC handle
* *
* Define the structure to save the SDHC state information and callback function. The detail interrupt status when * Defines the structure to save the SDHC state information and callback function. The detailed interrupt status when
* send command or transfer data can be got from interruptFlags field by using mask defined in sdhc_interrupt_flag_t; * sending a command or transfering data can be obtained from the interruptFlags field by using the mask defined in
* sdhc_interrupt_flag_t.
* *
* @note All the fields except interruptFlags and transferredWords must be allocated by the user. * @note All the fields except interruptFlags and transferredWords must be allocated by the user.
*/ */
@ -580,16 +579,16 @@ extern "C" {
/*! /*!
* @brief SDHC module initialization function. * @brief SDHC module initialization function.
* *
* Configure the SDHC according to the user configuration. * Configures the SDHC according to the user configuration.
* *
* Example: * Example:
@code @code
sdhc_config_t config; sdhc_config_t config;
config.enableDat3AsCDPin = false; config.cardDetectDat3 = false;
config.endianMode = kSDHC_EndianModeLittle; config.endianMode = kSDHC_EndianModeLittle;
config.dmaMode = kSDHC_DmaModeAdma2; config.dmaMode = kSDHC_DmaModeAdma2;
config.readWatermarkLevel = 512U; config.readWatermarkLevel = 128U;
config.writeWatermarkLevel = 512U; config.writeWatermarkLevel = 128U;
SDHC_Init(SDHC, &config); SDHC_Init(SDHC, &config);
@endcode @endcode
* *
@ -600,14 +599,14 @@ extern "C" {
void SDHC_Init(SDHC_Type *base, const sdhc_config_t *config); void SDHC_Init(SDHC_Type *base, const sdhc_config_t *config);
/*! /*!
* @brief Deinitialize the SDHC. * @brief Deinitializes the SDHC.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
*/ */
void SDHC_Deinit(SDHC_Type *base); void SDHC_Deinit(SDHC_Type *base);
/*! /*!
* @brief Reset the SDHC. * @brief Resets the SDHC.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param mask The reset type mask(_sdhc_reset). * @param mask The reset type mask(_sdhc_reset).
@ -625,7 +624,7 @@ bool SDHC_Reset(SDHC_Type *base, uint32_t mask, uint32_t timeout);
*/ */
/*! /*!
* @brief Set ADMA descriptor table configuration. * @brief Sets the ADMA descriptor table configuration.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param dmaMode DMA mode. * @param dmaMode DMA mode.
@ -651,7 +650,7 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base,
*/ */
/*! /*!
* @brief Enable interrupt status * @brief Enables the interrupt status.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param mask Interrupt status flags mask(_sdhc_interrupt_status_flag). * @param mask Interrupt status flags mask(_sdhc_interrupt_status_flag).
@ -662,7 +661,7 @@ static inline void SDHC_EnableInterruptStatus(SDHC_Type *base, uint32_t mask)
} }
/*! /*!
* @brief Disable interrupt status. * @brief Disables the interrupt status.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param mask The interrupt status flags mask(_sdhc_interrupt_status_flag). * @param mask The interrupt status flags mask(_sdhc_interrupt_status_flag).
@ -673,7 +672,7 @@ static inline void SDHC_DisableInterruptStatus(SDHC_Type *base, uint32_t mask)
} }
/*! /*!
* @brief Enable interrupts signal corresponding to the interrupt status flag. * @brief Enables the interrupt signal corresponding to the interrupt status flag.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param mask The interrupt status flags mask(_sdhc_interrupt_status_flag). * @param mask The interrupt status flags mask(_sdhc_interrupt_status_flag).
@ -684,7 +683,7 @@ static inline void SDHC_EnableInterruptSignal(SDHC_Type *base, uint32_t mask)
} }
/*! /*!
* @brief Disable interrupts signal corresponding to the interrupt status flag. * @brief Disables the interrupt signal corresponding to the interrupt status flag.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param mask The interrupt status flags mask(_sdhc_interrupt_status_flag). * @param mask The interrupt status flags mask(_sdhc_interrupt_status_flag).
@ -702,7 +701,7 @@ static inline void SDHC_DisableInterruptSignal(SDHC_Type *base, uint32_t mask)
*/ */
/*! /*!
* @brief Get current interrupt status. * @brief Gets the current interrupt status.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @return Current interrupt status flags mask(_sdhc_interrupt_status_flag). * @return Current interrupt status flags mask(_sdhc_interrupt_status_flag).
@ -713,7 +712,7 @@ static inline uint32_t SDHC_GetInterruptStatusFlags(SDHC_Type *base)
} }
/*! /*!
* @brief Clear specified interrupt status. * @brief Clears a specified interrupt status.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param mask The interrupt status flags mask(_sdhc_interrupt_status_flag). * @param mask The interrupt status flags mask(_sdhc_interrupt_status_flag).
@ -724,7 +723,7 @@ static inline void SDHC_ClearInterruptStatusFlags(SDHC_Type *base, uint32_t mask
} }
/*! /*!
* @brief Get the status of auto command 12 error. * @brief Gets the status of auto command 12 error.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @return Auto command 12 error status flags mask(_sdhc_auto_command12_error_status_flag). * @return Auto command 12 error status flags mask(_sdhc_auto_command12_error_status_flag).
@ -735,7 +734,7 @@ static inline uint32_t SDHC_GetAutoCommand12ErrorStatusFlags(SDHC_Type *base)
} }
/*! /*!
* @brief Get the status of ADMA error. * @brief Gets the status of the ADMA error.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @return ADMA error status flags mask(_sdhc_adma_error_status_flag). * @return ADMA error status flags mask(_sdhc_adma_error_status_flag).
@ -746,9 +745,9 @@ static inline uint32_t SDHC_GetAdmaErrorStatusFlags(SDHC_Type *base)
} }
/*! /*!
* @brief Get present status. * @brief Gets a present status.
* *
* This function gets the present SDHC's status except for interrupt status and error status. * This function gets the present SDHC's status except for an interrupt status and an error status.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @return Present SDHC's status flags mask(_sdhc_present_status_flag). * @return Present SDHC's status flags mask(_sdhc_present_status_flag).
@ -766,7 +765,7 @@ static inline uint32_t SDHC_GetPresentStatusFlags(SDHC_Type *base)
*/ */
/*! /*!
* @brief Get the capability information * @brief Gets the capability information.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param capability Structure to save capability information. * @param capability Structure to save capability information.
@ -774,7 +773,7 @@ static inline uint32_t SDHC_GetPresentStatusFlags(SDHC_Type *base)
void SDHC_GetCapability(SDHC_Type *base, sdhc_capability_t *capability); void SDHC_GetCapability(SDHC_Type *base, sdhc_capability_t *capability);
/*! /*!
* @brief Enable or disable SD bus clock. * @brief Enables or disables the SD bus clock.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param enable True to enable, false to disable. * @param enable True to enable, false to disable.
@ -792,7 +791,7 @@ static inline void SDHC_EnableSdClock(SDHC_Type *base, bool enable)
} }
/*! /*!
* @brief Set SD bus clock frequency. * @brief Sets the SD bus clock frequency.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param srcClock_Hz SDHC source clock frequency united in Hz. * @param srcClock_Hz SDHC source clock frequency united in Hz.
@ -803,9 +802,10 @@ static inline void SDHC_EnableSdClock(SDHC_Type *base, bool enable)
uint32_t SDHC_SetSdClock(SDHC_Type *base, uint32_t srcClock_Hz, uint32_t busClock_Hz); uint32_t SDHC_SetSdClock(SDHC_Type *base, uint32_t srcClock_Hz, uint32_t busClock_Hz);
/*! /*!
* @brief Send 80 clocks to the card to set it to be active state. * @brief Sends 80 clocks to the card to set it to the active state.
* *
* This function must be called after each time the card is inserted to make card can receive command correctly. * This function must be called each time the card is inserted to ensure that the card can receive the command
* correctly.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param timeout Timeout to initialize card. * @param timeout Timeout to initialize card.
@ -815,7 +815,7 @@ uint32_t SDHC_SetSdClock(SDHC_Type *base, uint32_t srcClock_Hz, uint32_t busCloc
bool SDHC_SetCardActive(SDHC_Type *base, uint32_t timeout); bool SDHC_SetCardActive(SDHC_Type *base, uint32_t timeout);
/*! /*!
* @brief Set the data transfer width. * @brief Sets the data transfer width.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param width Data transfer width. * @param width Data transfer width.
@ -826,10 +826,10 @@ static inline void SDHC_SetDataBusWidth(SDHC_Type *base, sdhc_data_bus_width_t w
} }
/*! /*!
* @brief Set card transfer-related configuration. * @brief Sets the card transfer-related configuration.
* *
* This function fills card transfer-related command argument/transfer flag/data size. Command and data will be sent by * This function fills the card transfer-related command argument/transfer flag/data size. The command and data are sent
* SDHC after calling this function. * by SDHC after calling this function.
* *
* Example: * Example:
@code @code
@ -848,7 +848,7 @@ static inline void SDHC_SetDataBusWidth(SDHC_Type *base, sdhc_data_bus_width_t w
void SDHC_SetTransferConfig(SDHC_Type *base, const sdhc_transfer_config_t *config); void SDHC_SetTransferConfig(SDHC_Type *base, const sdhc_transfer_config_t *config);
/*! /*!
* @brief Get the command response. * @brief Gets the command response.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param index The index of response register, range from 0 to 3. * @param index The index of response register, range from 0 to 3.
@ -862,9 +862,9 @@ static inline uint32_t SDHC_GetCommandResponse(SDHC_Type *base, uint32_t index)
} }
/*! /*!
* @brief Fill the the data port. * @brief Fills the the data port.
* *
* This function is mainly used to implement the data transfer by Data Port instead of DMA. * This function is used to implement the data transfer by Data Port instead of DMA.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param data The data about to be sent. * @param data The data about to be sent.
@ -875,9 +875,9 @@ static inline void SDHC_WriteData(SDHC_Type *base, uint32_t data)
} }
/*! /*!
* @brief Retrieve the data from the data port. * @brief Retrieves the data from the data port.
* *
* This function is mainly used to implement the data transfer by Data Port instead of DMA. * This function is used to implement the data transfer by Data Port instead of DMA.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @return The data has been read. * @return The data has been read.
@ -888,7 +888,7 @@ static inline uint32_t SDHC_ReadData(SDHC_Type *base)
} }
/*! /*!
* @brief Enable or disable wakeup event in low power mode * @brief Enables or disables a wakeup event in low-power mode.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param mask Wakeup events mask(_sdhc_wakeup_event). * @param mask Wakeup events mask(_sdhc_wakeup_event).
@ -907,7 +907,7 @@ static inline void SDHC_EnableWakeupEvent(SDHC_Type *base, uint32_t mask, bool e
} }
/*! /*!
* @brief Enable or disable card detection level for test. * @brief Enables or disables the card detection level for testing.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param enable True to enable, false to disable. * @param enable True to enable, false to disable.
@ -925,11 +925,11 @@ static inline void SDHC_EnableCardDetectTest(SDHC_Type *base, bool enable)
} }
/*! /*!
* @brief Set card detection test level. * @brief Sets the card detection test level.
* *
* This function set the card detection test level to indicate whether the card is inserted into SDHC when DAT[3]/ * This function sets the card detection test level to indicate whether the card is inserted into the SDHC when DAT[3]/
* CD pin is selected as card detection pin. This function can also assert the pin logic when DAT[3]/CD pin is select * CD pin is selected as a card detection pin. This function can also assert the pin logic when DAT[3]/CD pin is
* as the card detection pin. * selected as the card detection pin.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param high True to set the card detect level to high. * @param high True to set the card detect level to high.
@ -947,7 +947,7 @@ static inline void SDHC_SetCardDetectTestLevel(SDHC_Type *base, bool high)
} }
/*! /*!
* @brief Enable or disable SDIO card control. * @brief Enables or disables the SDIO card control.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param mask SDIO card control flags mask(_sdhc_sdio_control_flag). * @param mask SDIO card control flags mask(_sdhc_sdio_control_flag).
@ -956,7 +956,7 @@ static inline void SDHC_SetCardDetectTestLevel(SDHC_Type *base, bool high)
void SDHC_EnableSdioControl(SDHC_Type *base, uint32_t mask, bool enable); void SDHC_EnableSdioControl(SDHC_Type *base, uint32_t mask, bool enable);
/*! /*!
* @brief Restart a transaction which has stopped at the block gap for SDIO card. * @brief Restarts a transaction which has stopped at the block GAP for the SDIO card.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
*/ */
@ -966,18 +966,18 @@ static inline void SDHC_SetContinueRequest(SDHC_Type *base)
} }
/*! /*!
* @brief Configure the MMC boot feature. * @brief Configures the MMC boot feature.
* *
* Example: * Example:
@code @code
sdhc_boot_config_t bootConfig; sdhc_boot_config_t config;
bootConfig.ackTimeoutCount = 4; config.ackTimeoutCount = 4;
bootConfig.bootMode = kSDHC_BootModeNormal; config.bootMode = kSDHC_BootModeNormal;
bootConfig.blockCount = 5; config.blockCount = 5;
bootConfig.enableBootAck = true; config.enableBootAck = true;
bootConfig.enableBoot = true; config.enableBoot = true;
enableBoot.enableAutoStopAtBlockGap = true; config.enableAutoStopAtBlockGap = true;
SDHC_SetMmcBootConfig(SDHC, &bootConfig); SDHC_SetMmcBootConfig(SDHC, &config);
@endcode @endcode
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
@ -986,7 +986,7 @@ static inline void SDHC_SetContinueRequest(SDHC_Type *base)
void SDHC_SetMmcBootConfig(SDHC_Type *base, const sdhc_boot_config_t *config); void SDHC_SetMmcBootConfig(SDHC_Type *base, const sdhc_boot_config_t *config);
/*! /*!
* @brief Force to generate events according to the given mask. * @brief Forces generating events according to the given mask.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param mask The force events mask(_sdhc_force_event). * @param mask The force events mask(_sdhc_force_event).
@ -1004,13 +1004,13 @@ static inline void SDHC_SetForceEvent(SDHC_Type *base, uint32_t mask)
*/ */
/*! /*!
* @brief Transfer command/data using blocking way. * @brief Transfers the command/data using a blocking method.
* *
* This function waits until the command response/data is got or SDHC encounters error by polling the status flag. * This function waits until the command response/data is received or the SDHC encounters an error by polling the status
* Application must not call this API in multiple threads at the same time because of that this API doesn't support * flag. The application must not call this API in multiple threads at the same time. Because of that this API doesn't support
* reentry mechanism. * the re-entry mechanism.
* *
* @note Needn't to call the API 'SDHC_TransferCreateHandle' when calling this API. * @note There is no need to call the API 'SDHC_TransferCreateHandle' when calling this API.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param admaTable ADMA table address, can't be null if transfer way is ADMA1/ADMA2. * @param admaTable ADMA table address, can't be null if transfer way is ADMA1/ADMA2.
@ -1028,7 +1028,7 @@ status_t SDHC_TransferBlocking(SDHC_Type *base,
sdhc_transfer_t *transfer); sdhc_transfer_t *transfer);
/*! /*!
* @brief Create the SDHC handle. * @brief Creates the SDHC handle.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param handle SDHC handle pointer. * @param handle SDHC handle pointer.
@ -1041,13 +1041,13 @@ void SDHC_TransferCreateHandle(SDHC_Type *base,
void *userData); void *userData);
/*! /*!
* @brief Transfer command/data using interrupt and asynchronous way. * @brief Transfers the command/data using an interrupt and an asynchronous method.
* *
* This function send command and data and return immediately. It doesn't wait the transfer complete or encounter error. * This function sends a command and data and returns immediately. It doesn't wait the transfer complete or encounter an
* Application must not call this API in multiple threads at the same time because of that this API doesn't support * error. The application must not call this API in multiple threads at the same time. Because of that this API doesn't support
* reentry mechanism. * the re-entry mechanism.
* *
* @note Must call the API 'SDHC_TransferCreateHandle' when calling this API. * @note Call the API 'SDHC_TransferCreateHandle' when calling this API.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param handle SDHC handle. * @param handle SDHC handle.
@ -1063,9 +1063,9 @@ status_t SDHC_TransferNonBlocking(
SDHC_Type *base, sdhc_handle_t *handle, uint32_t *admaTable, uint32_t admaTableWords, sdhc_transfer_t *transfer); SDHC_Type *base, sdhc_handle_t *handle, uint32_t *admaTable, uint32_t admaTableWords, sdhc_transfer_t *transfer);
/*! /*!
* @brief IRQ handler for SDHC * @brief IRQ handler for the SDHC.
* *
* This function deals with IRQs on the given host controller. * This function deals with the IRQs on the given host controller.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param handle SDHC handle. * @param handle SDHC handle.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, Freescale Semiconductor, Inc. * Copyright (c) 2016, Freescale Semiconductor, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -50,6 +50,9 @@
#define SDHC_NEXT_CLKFS(x) ((x) <<= 1U) #define SDHC_NEXT_CLKFS(x) ((x) <<= 1U)
#define SDHC_PREV_CLKFS(x) ((x) >>= 1U) #define SDHC_PREV_CLKFS(x) ((x) >>= 1U)
/* Typedef for interrupt handler. */
typedef void (*sdhc_isr_t)(SDHC_Type *base, sdhc_handle_t *handle);
/*! @brief ADMA table configuration */ /*! @brief ADMA table configuration */
typedef struct _sdhc_adma_table_config typedef struct _sdhc_adma_table_config
{ {
@ -230,6 +233,9 @@ static const IRQn_Type s_sdhcIRQ[] = SDHC_IRQS;
/*! @brief SDHC clock array name */ /*! @brief SDHC clock array name */
static const clock_ip_name_t s_sdhcClock[] = SDHC_CLOCKS; static const clock_ip_name_t s_sdhcClock[] = SDHC_CLOCKS;
/* SDHC ISR for transactional APIs. */
static sdhc_isr_t s_sdhcIsr;
/******************************************************************************* /*******************************************************************************
* Code * Code
******************************************************************************/ ******************************************************************************/
@ -288,10 +294,8 @@ static void SDHC_SetTransferInterrupt(SDHC_Type *base, bool usingInterruptSignal
static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_data_t *data) static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_data_t *data)
{ {
assert(command);
uint32_t flags = 0U; uint32_t flags = 0U;
sdhc_transfer_config_t sdhcTransferConfig; sdhc_transfer_config_t sdhcTransferConfig = {0};
sdhc_dma_mode_t dmaMode; sdhc_dma_mode_t dmaMode;
/* Define the flag corresponding to each response type. */ /* Define the flag corresponding to each response type. */
@ -315,7 +319,7 @@ static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_da
flags |= (kSDHC_ResponseLength48Flag); flags |= (kSDHC_ResponseLength48Flag);
break; break;
case kSDHC_ResponseTypeR5: /* Response 5 */ case kSDHC_ResponseTypeR5: /* Response 5 */
flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag); flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag);
break; break;
case kSDHC_ResponseTypeR5b: /* Response 5 with busy */ case kSDHC_ResponseTypeR5b: /* Response 5 with busy */
flags |= (kSDHC_ResponseLength48BusyFlag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag); flags |= (kSDHC_ResponseLength48BusyFlag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag);
@ -355,18 +359,9 @@ static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_da
flags |= kSDHC_EnableAutoCommand12Flag; flags |= kSDHC_EnableAutoCommand12Flag;
} }
} }
if (data->blockCount > SDHC_MAX_BLOCK_COUNT)
{
sdhcTransferConfig.dataBlockSize = data->blockSize;
sdhcTransferConfig.dataBlockCount = SDHC_MAX_BLOCK_COUNT;
flags &= ~(uint32_t)kSDHC_EnableBlockCountFlag; sdhcTransferConfig.dataBlockSize = data->blockSize;
} sdhcTransferConfig.dataBlockCount = data->blockCount;
else
{
sdhcTransferConfig.dataBlockSize = data->blockSize;
sdhcTransferConfig.dataBlockCount = data->blockCount;
}
} }
else else
{ {
@ -382,8 +377,6 @@ static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_da
static void SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command) static void SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command)
{ {
assert(command);
uint32_t i; uint32_t i;
if (command->responseType != kSDHC_ResponseTypeNone) if (command->responseType != kSDHC_ResponseTypeNone)
@ -412,13 +405,22 @@ static void SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command
static uint32_t SDHC_ReadDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords) static uint32_t SDHC_ReadDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords)
{ {
assert(data);
uint32_t i; uint32_t i;
uint32_t totalWords; uint32_t totalWords;
uint32_t wordsCanBeRead; /* The words can be read at this time. */ uint32_t wordsCanBeRead; /* The words can be read at this time. */
uint32_t readWatermark = ((base->WML & SDHC_WML_RDWML_MASK) >> SDHC_WML_RDWML_SHIFT); uint32_t readWatermark = ((base->WML & SDHC_WML_RDWML_MASK) >> SDHC_WML_RDWML_SHIFT);
/*
* Add non aligned access support ,user need make sure your buffer size is big
* enough to hold the data,in other words,user need make sure the buffer size
* is 4 byte aligned
*/
if (data->blockSize % sizeof(uint32_t) != 0U)
{
data->blockSize +=
sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */
}
totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t)); totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t));
/* If watermark level is equal or bigger than totalWords, transfers totalWords data. */ /* If watermark level is equal or bigger than totalWords, transfers totalWords data. */
@ -451,12 +453,21 @@ static uint32_t SDHC_ReadDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t t
static status_t SDHC_ReadByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data) static status_t SDHC_ReadByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data)
{ {
assert(data);
uint32_t totalWords; uint32_t totalWords;
uint32_t transferredWords = 0U; uint32_t transferredWords = 0U;
status_t error = kStatus_Success; status_t error = kStatus_Success;
/*
* Add non aligned access support ,user need make sure your buffer size is big
* enough to hold the data,in other words,user need make sure the buffer size
* is 4 byte aligned
*/
if (data->blockSize % sizeof(uint32_t) != 0U)
{
data->blockSize +=
sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */
}
totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t)); totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t));
while ((error == kStatus_Success) && (transferredWords < totalWords)) while ((error == kStatus_Success) && (transferredWords < totalWords))
@ -489,13 +500,22 @@ static status_t SDHC_ReadByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data)
static uint32_t SDHC_WriteDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords) static uint32_t SDHC_WriteDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords)
{ {
assert(data);
uint32_t i; uint32_t i;
uint32_t totalWords; uint32_t totalWords;
uint32_t wordsCanBeWrote; /* Words can be wrote at this time. */ uint32_t wordsCanBeWrote; /* Words can be wrote at this time. */
uint32_t writeWatermark = ((base->WML & SDHC_WML_WRWML_MASK) >> SDHC_WML_WRWML_SHIFT); uint32_t writeWatermark = ((base->WML & SDHC_WML_WRWML_MASK) >> SDHC_WML_WRWML_SHIFT);
/*
* Add non aligned access support ,user need make sure your buffer size is big
* enough to hold the data,in other words,user need make sure the buffer size
* is 4 byte aligned
*/
if (data->blockSize % sizeof(uint32_t) != 0U)
{
data->blockSize +=
sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */
}
totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t)); totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t));
/* If watermark level is equal or bigger than totalWords, transfers totalWords data.*/ /* If watermark level is equal or bigger than totalWords, transfers totalWords data.*/
@ -528,12 +548,21 @@ static uint32_t SDHC_WriteDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t
static status_t SDHC_WriteByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data) static status_t SDHC_WriteByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data)
{ {
assert(data);
uint32_t totalWords; uint32_t totalWords;
uint32_t transferredWords = 0U; uint32_t transferredWords = 0U;
status_t error = kStatus_Success; status_t error = kStatus_Success;
/*
* Add non aligned access support ,user need make sure your buffer size is big
* enough to hold the data,in other words,user need make sure the buffer size
* is 4 byte aligned
*/
if (data->blockSize % sizeof(uint32_t) != 0U)
{
data->blockSize +=
sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */
}
totalWords = (data->blockCount * data->blockSize) / sizeof(uint32_t); totalWords = (data->blockCount * data->blockSize) / sizeof(uint32_t);
while ((error == kStatus_Success) && (transferredWords < totalWords)) while ((error == kStatus_Success) && (transferredWords < totalWords))
@ -576,8 +605,6 @@ static status_t SDHC_WriteByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data)
static status_t SDHC_SendCommandBlocking(SDHC_Type *base, sdhc_command_t *command) static status_t SDHC_SendCommandBlocking(SDHC_Type *base, sdhc_command_t *command)
{ {
assert(command);
status_t error = kStatus_Success; status_t error = kStatus_Success;
/* Wait command complete or SDHC encounters error. */ /* Wait command complete or SDHC encounters error. */
@ -602,8 +629,6 @@ static status_t SDHC_SendCommandBlocking(SDHC_Type *base, sdhc_command_t *comman
static status_t SDHC_TransferByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data) static status_t SDHC_TransferByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data)
{ {
assert(data);
status_t error = kStatus_Success; status_t error = kStatus_Success;
if (data->rxData) if (data->rxData)
@ -669,8 +694,6 @@ static status_t SDHC_TransferDataBlocking(sdhc_dma_mode_t dmaMode, SDHC_Type *ba
static void SDHC_TransferHandleCardDetect(sdhc_handle_t *handle, uint32_t interruptFlags) static void SDHC_TransferHandleCardDetect(sdhc_handle_t *handle, uint32_t interruptFlags)
{ {
assert(interruptFlags & kSDHC_CardDetectFlag);
if (interruptFlags & kSDHC_CardInsertionFlag) if (interruptFlags & kSDHC_CardInsertionFlag)
{ {
if (handle->callback.CardInserted) if (handle->callback.CardInserted)
@ -689,7 +712,7 @@ static void SDHC_TransferHandleCardDetect(sdhc_handle_t *handle, uint32_t interr
static void SDHC_TransferHandleCommand(SDHC_Type *base, sdhc_handle_t *handle, uint32_t interruptFlags) static void SDHC_TransferHandleCommand(SDHC_Type *base, sdhc_handle_t *handle, uint32_t interruptFlags)
{ {
assert(interruptFlags & kSDHC_CommandFlag); assert(handle->command);
if ((interruptFlags & kSDHC_CommandErrorFlag) && (!(handle->data)) && (handle->callback.TransferComplete)) if ((interruptFlags & kSDHC_CommandErrorFlag) && (!(handle->data)) && (handle->callback.TransferComplete))
{ {
@ -709,7 +732,6 @@ static void SDHC_TransferHandleCommand(SDHC_Type *base, sdhc_handle_t *handle, u
static void SDHC_TransferHandleData(SDHC_Type *base, sdhc_handle_t *handle, uint32_t interruptFlags) static void SDHC_TransferHandleData(SDHC_Type *base, sdhc_handle_t *handle, uint32_t interruptFlags)
{ {
assert(handle->data); assert(handle->data);
assert(interruptFlags & kSDHC_DataFlag);
if ((!(handle->data->enableIgnoreError)) && (interruptFlags & (kSDHC_DataErrorFlag | kSDHC_DmaErrorFlag)) && if ((!(handle->data->enableIgnoreError)) && (interruptFlags & (kSDHC_DataErrorFlag | kSDHC_DmaErrorFlag)) &&
(handle->callback.TransferComplete)) (handle->callback.TransferComplete))
@ -759,6 +781,8 @@ void SDHC_Init(SDHC_Type *base, const sdhc_config_t *config)
#if !defined FSL_SDHC_ENABLE_ADMA1 #if !defined FSL_SDHC_ENABLE_ADMA1
assert(config->dmaMode != kSDHC_DmaModeAdma1); assert(config->dmaMode != kSDHC_DmaModeAdma1);
#endif /* FSL_SDHC_ENABLE_ADMA1 */ #endif /* FSL_SDHC_ENABLE_ADMA1 */
assert((config->writeWatermarkLevel >= 1U) && (config->writeWatermarkLevel <= 128U));
assert((config->readWatermarkLevel >= 1U) && (config->readWatermarkLevel <= 128U));
uint32_t proctl; uint32_t proctl;
uint32_t wml; uint32_t wml;
@ -850,7 +874,8 @@ void SDHC_GetCapability(SDHC_Type *base, sdhc_capability_t *capability)
uint32_t SDHC_SetSdClock(SDHC_Type *base, uint32_t srcClock_Hz, uint32_t busClock_Hz) uint32_t SDHC_SetSdClock(SDHC_Type *base, uint32_t srcClock_Hz, uint32_t busClock_Hz)
{ {
assert(busClock_Hz && (busClock_Hz < srcClock_Hz)); assert(srcClock_Hz != 0U);
assert((busClock_Hz != 0U) && (busClock_Hz <= srcClock_Hz));
uint32_t divisor; uint32_t divisor;
uint32_t prescaler; uint32_t prescaler;
@ -898,7 +923,7 @@ bool SDHC_SetCardActive(SDHC_Type *base, uint32_t timeout)
{ {
base->SYSCTL |= SDHC_SYSCTL_INITA_MASK; base->SYSCTL |= SDHC_SYSCTL_INITA_MASK;
/* Delay some time to wait card become active state. */ /* Delay some time to wait card become active state. */
while (!(base->SYSCTL & SDHC_SYSCTL_INITA_MASK)) while (base->SYSCTL & SDHC_SYSCTL_INITA_MASK)
{ {
if (!timeout) if (!timeout)
{ {
@ -913,6 +938,8 @@ bool SDHC_SetCardActive(SDHC_Type *base, uint32_t timeout)
void SDHC_SetTransferConfig(SDHC_Type *base, const sdhc_transfer_config_t *config) void SDHC_SetTransferConfig(SDHC_Type *base, const sdhc_transfer_config_t *config)
{ {
assert(config); assert(config);
assert(config->dataBlockSize <= (SDHC_BLKATTR_BLKSIZE_MASK >> SDHC_BLKATTR_BLKSIZE_SHIFT));
assert(config->dataBlockCount <= (SDHC_BLKATTR_BLKCNT_MASK >> SDHC_BLKATTR_BLKCNT_SHIFT));
base->BLKATTR = ((base->BLKATTR & ~(SDHC_BLKATTR_BLKSIZE_MASK | SDHC_BLKATTR_BLKCNT_MASK)) | base->BLKATTR = ((base->BLKATTR & ~(SDHC_BLKATTR_BLKSIZE_MASK | SDHC_BLKATTR_BLKCNT_MASK)) |
(SDHC_BLKATTR_BLKSIZE(config->dataBlockSize) | SDHC_BLKATTR_BLKCNT(config->dataBlockCount))); (SDHC_BLKATTR_BLKSIZE(config->dataBlockSize) | SDHC_BLKATTR_BLKCNT(config->dataBlockCount)));
@ -975,12 +1002,13 @@ void SDHC_EnableSdioControl(SDHC_Type *base, uint32_t mask, bool enable)
void SDHC_SetMmcBootConfig(SDHC_Type *base, const sdhc_boot_config_t *config) void SDHC_SetMmcBootConfig(SDHC_Type *base, const sdhc_boot_config_t *config)
{ {
assert(config); assert(config);
assert(config->ackTimeoutCount <= (SDHC_MMCBOOT_DTOCVACK_MASK >> SDHC_MMCBOOT_DTOCVACK_SHIFT));
assert(config->blockCount <= (SDHC_MMCBOOT_BOOTBLKCNT_MASK >> SDHC_MMCBOOT_BOOTBLKCNT_SHIFT));
uint32_t mmcboot; uint32_t mmcboot = 0U;
mmcboot = base->MMCBOOT; mmcboot = (SDHC_MMCBOOT_DTOCVACK(config->ackTimeoutCount) | SDHC_MMCBOOT_BOOTMODE(config->bootMode) |
mmcboot |= (SDHC_MMCBOOT_DTOCVACK(config->ackTimeoutCount) | SDHC_MMCBOOT_BOOTMODE(config->bootMode) | SDHC_MMCBOOT_BOOTBLKCNT(config->blockCount));
SDHC_MMCBOOT_BOOTBLKCNT(config->blockCount));
if (config->enableBootAck) if (config->enableBootAck)
{ {
mmcboot |= SDHC_MMCBOOT_BOOTACK_MASK; mmcboot |= SDHC_MMCBOOT_BOOTACK_MASK;
@ -1016,6 +1044,9 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base,
(!data) || (!dataBytes) (!data) || (!dataBytes)
#if !defined FSL_SDHC_ENABLE_ADMA1 #if !defined FSL_SDHC_ENABLE_ADMA1
|| (dmaMode == kSDHC_DmaModeAdma1) || (dmaMode == kSDHC_DmaModeAdma1)
#else
/* Buffer address configured in ADMA1 descriptor must be 4KB aligned. */
|| ((dmaMode == kSDHC_DmaModeAdma1) && (((uint32_t)data % SDHC_ADMA1_LENGTH_ALIGN) != 0U))
#endif /* FSL_SDHC_ENABLE_ADMA1 */ #endif /* FSL_SDHC_ENABLE_ADMA1 */
) )
{ {
@ -1029,6 +1060,17 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base,
break; break;
#if defined FSL_SDHC_ENABLE_ADMA1 #if defined FSL_SDHC_ENABLE_ADMA1
case kSDHC_DmaModeAdma1: case kSDHC_DmaModeAdma1:
/*
* Add non aligned access support ,user need make sure your buffer size is big
* enough to hold the data,in other words,user need make sure the buffer size
* is 4 byte aligned
*/
if (dataBytes % sizeof(uint32_t) != 0U)
{
dataBytes +=
sizeof(uint32_t) - (dataBytes % sizeof(uint32_t)); /* make the data length as word-aligned */
}
startAddress = data; startAddress = data;
/* Check if ADMA descriptor's number is enough. */ /* Check if ADMA descriptor's number is enough. */
entries = ((dataBytes / SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U); entries = ((dataBytes / SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U);
@ -1054,7 +1096,7 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base,
adma1EntryAddress[i + 1U] = adma1EntryAddress[i + 1U] =
((uint32_t)(startAddress) << SDHC_ADMA1_DESCRIPTOR_ADDRESS_SHIFT); ((uint32_t)(startAddress) << SDHC_ADMA1_DESCRIPTOR_ADDRESS_SHIFT);
adma1EntryAddress[i + 1U] |= adma1EntryAddress[i + 1U] |=
(SDHC_ADMA1_DESCRIPTOR_TYPE_TRANSFER | SDHC_ADMA1_DESCRIPTOR_END_MASK); (kSDHC_Adma1DescriptorTypeTransfer | kSDHC_Adma1DescriptorEndFlag);
} }
else else
{ {
@ -1075,6 +1117,17 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base,
break; break;
#endif /* FSL_SDHC_ENABLE_ADMA1 */ #endif /* FSL_SDHC_ENABLE_ADMA1 */
case kSDHC_DmaModeAdma2: case kSDHC_DmaModeAdma2:
/*
* Add non aligned access support ,user need make sure your buffer size is big
* enough to hold the data,in other words,user need make sure the buffer size
* is 4 byte aligned
*/
if (dataBytes % sizeof(uint32_t) != 0U)
{
dataBytes +=
sizeof(uint32_t) - (dataBytes % sizeof(uint32_t)); /* make the data length as word-aligned */
}
startAddress = data; startAddress = data;
/* Check if ADMA descriptor's number is enough. */ /* Check if ADMA descriptor's number is enough. */
entries = ((dataBytes / SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U); entries = ((dataBytes / SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U);
@ -1125,15 +1178,14 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base,
status_t SDHC_TransferBlocking(SDHC_Type *base, uint32_t *admaTable, uint32_t admaTableWords, sdhc_transfer_t *transfer) status_t SDHC_TransferBlocking(SDHC_Type *base, uint32_t *admaTable, uint32_t admaTableWords, sdhc_transfer_t *transfer)
{ {
assert(transfer); assert(transfer);
assert(transfer->command); /* Command must not be NULL, data can be NULL. */
status_t error = kStatus_Success; status_t error = kStatus_Success;
sdhc_dma_mode_t dmaMode = (sdhc_dma_mode_t)((base->PROCTL & SDHC_PROCTL_DMAS_MASK) >> SDHC_PROCTL_DMAS_SHIFT); sdhc_dma_mode_t dmaMode = (sdhc_dma_mode_t)((base->PROCTL & SDHC_PROCTL_DMAS_MASK) >> SDHC_PROCTL_DMAS_SHIFT);
sdhc_command_t *command = transfer->command; sdhc_command_t *command = transfer->command;
sdhc_data_t *data = transfer->data; sdhc_data_t *data = transfer->data;
/* DATA-PORT is 32-bit align, ADMA2 4 bytes align, ADMA1 is 4096 bytes align */ /* make sure the cmd/block count is valid */
if ((!command) || (data && (data->blockSize % 4U))) if ((!command) || (data && (data->blockCount > SDHC_MAX_BLOCK_COUNT)))
{ {
error = kStatus_InvalidArgument; error = kStatus_InvalidArgument;
} }
@ -1147,7 +1199,7 @@ status_t SDHC_TransferBlocking(SDHC_Type *base, uint32_t *admaTable, uint32_t ad
{ {
} }
/* Update ADMA descriptor table if data isn't NULL. */ /* Update ADMA descriptor table according to different DMA mode(no DMA, ADMA1, ADMA2).*/
if (data && (kStatus_Success != SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords, if (data && (kStatus_Success != SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords,
(data->rxData ? data->rxData : data->txData), (data->rxData ? data->rxData : data->txData),
(data->blockCount * data->blockSize)))) (data->blockCount * data->blockSize))))
@ -1156,9 +1208,8 @@ status_t SDHC_TransferBlocking(SDHC_Type *base, uint32_t *admaTable, uint32_t ad
} }
else else
{ {
SDHC_StartTransfer(base, command, data);
/* Send command and receive data. */ /* Send command and receive data. */
SDHC_StartTransfer(base, command, data);
if (kStatus_Success != SDHC_SendCommandBlocking(base, command)) if (kStatus_Success != SDHC_SendCommandBlocking(base, command))
{ {
error = kStatus_SDHC_SendCommandFailed; error = kStatus_SDHC_SendCommandFailed;
@ -1200,6 +1251,10 @@ void SDHC_TransferCreateHandle(SDHC_Type *base,
/* Enable interrupt in NVIC. */ /* Enable interrupt in NVIC. */
SDHC_SetTransferInterrupt(base, true); SDHC_SetTransferInterrupt(base, true);
/* save IRQ handler */
s_sdhcIsr = SDHC_TransferHandleIRQ;
EnableIRQ(s_sdhcIRQ[SDHC_GetInstance(base)]); EnableIRQ(s_sdhcIRQ[SDHC_GetInstance(base)]);
} }
@ -1213,8 +1268,8 @@ status_t SDHC_TransferNonBlocking(
sdhc_command_t *command = transfer->command; sdhc_command_t *command = transfer->command;
sdhc_data_t *data = transfer->data; sdhc_data_t *data = transfer->data;
/* DATA-PORT is 32-bit align, ADMA2 4 bytes align, ADMA1 is 4096 bytes align */ /* make sure cmd/block count is valid */
if ((!(transfer->command)) || ((transfer->data) && (transfer->data->blockSize % 4U))) if ((!command) || (data && (data->blockCount > SDHC_MAX_BLOCK_COUNT)))
{ {
error = kStatus_InvalidArgument; error = kStatus_InvalidArgument;
} }
@ -1228,7 +1283,7 @@ status_t SDHC_TransferNonBlocking(
} }
else else
{ {
/* Update ADMA descriptor table and reset transferred words if data isn't NULL. */ /* Update ADMA descriptor table according to different DMA mode(no DMA, ADMA1, ADMA2).*/
if (data && (kStatus_Success != SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords, if (data && (kStatus_Success != SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords,
(data->rxData ? data->rxData : data->txData), (data->rxData ? data->rxData : data->txData),
(data->blockCount * data->blockSize)))) (data->blockCount * data->blockSize))))
@ -1243,6 +1298,7 @@ status_t SDHC_TransferNonBlocking(
handle->interruptFlags = 0U; handle->interruptFlags = 0U;
/* transferredWords will only be updated in ISR when transfer way is DATAPORT. */ /* transferredWords will only be updated in ISR when transfer way is DATAPORT. */
handle->transferredWords = 0U; handle->transferredWords = 0U;
SDHC_StartTransfer(base, command, data); SDHC_StartTransfer(base, command, data);
} }
} }
@ -1289,6 +1345,6 @@ void SDHC_DriverIRQHandler(void)
{ {
assert(s_sdhcHandle[0]); assert(s_sdhcHandle[0]);
SDHC_TransferHandleIRQ(SDHC, s_sdhcHandle[0]); s_sdhcIsr(SDHC, s_sdhcHandle[0]);
} }
#endif #endif

View File

@ -37,16 +37,14 @@
* @{ * @{
*/ */
/*! @file */
/****************************************************************************** /******************************************************************************
* Definitions. * Definitions.
*****************************************************************************/ *****************************************************************************/
/*! @name Driver version */ /*! @name Driver version */
/*@{*/ /*@{*/
/*! @brief Driver version 2.0.0. */ /*! @brief Driver version 2.1.2. */
#define FSL_SDHC_DRIVER_VERSION (MAKE_VERSION(2U, 0U, 0U)) #define FSL_SDHC_DRIVER_VERSION (MAKE_VERSION(2U, 1U, 2U))
/*@}*/ /*@}*/
/*! @brief Maximum block count can be set one time */ /*! @brief Maximum block count can be set one time */
@ -350,7 +348,7 @@ typedef enum _sdhc_response_type
#define SDHC_ADMA1_DESCRIPTOR_LENGTH_SHIFT (12U) #define SDHC_ADMA1_DESCRIPTOR_LENGTH_SHIFT (12U)
/*! @brief The mask for LENGTH field in ADMA1's descriptor */ /*! @brief The mask for LENGTH field in ADMA1's descriptor */
#define SDHC_ADMA1_DESCRIPTOR_LENGTH_MASK (0xFFFFU) #define SDHC_ADMA1_DESCRIPTOR_LENGTH_MASK (0xFFFFU)
/*! @brief The max value of LENGTH filed in ADMA1's descriptor */ /*! @brief The maximum value of LENGTH filed in ADMA1's descriptor */
#define SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY (SDHC_ADMA1_DESCRIPTOR_LENGTH_MASK + 1U) #define SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY (SDHC_ADMA1_DESCRIPTOR_LENGTH_MASK + 1U)
/*! @brief The mask for the control/status field in ADMA1 descriptor */ /*! @brief The mask for the control/status field in ADMA1 descriptor */
@ -395,7 +393,7 @@ enum _sdhc_adma1_descriptor_flag
#define SDHC_ADMA2_DESCRIPTOR_LENGTH_SHIFT (16U) #define SDHC_ADMA2_DESCRIPTOR_LENGTH_SHIFT (16U)
/*! @brief The bit mask for LENGTH field in ADMA2's descriptor */ /*! @brief The bit mask for LENGTH field in ADMA2's descriptor */
#define SDHC_ADMA2_DESCRIPTOR_LENGTH_MASK (0xFFFFU) #define SDHC_ADMA2_DESCRIPTOR_LENGTH_MASK (0xFFFFU)
/*! @brief The max value of LENGTH field in ADMA2's descriptor */ /*! @brief The maximum value of LENGTH field in ADMA2's descriptor */
#define SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY (SDHC_ADMA2_DESCRIPTOR_LENGTH_MASK) #define SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY (SDHC_ADMA2_DESCRIPTOR_LENGTH_MASK)
/*! @brief ADMA1 descriptor control and status mask */ /*! @brief ADMA1 descriptor control and status mask */
@ -416,10 +414,10 @@ enum _sdhc_adma2_descriptor_flag
kSDHC_Adma2DescriptorValidFlag), /*!< Link type */ kSDHC_Adma2DescriptorValidFlag), /*!< Link type */
}; };
/*! @brief Define the adma1 descriptor structure. */ /*! @brief Defines the adma1 descriptor structure. */
typedef uint32_t sdhc_adma1_descriptor_t; typedef uint32_t sdhc_adma1_descriptor_t;
/*! @brief Define the ADMA2 descriptor structure. */ /*! @brief Defines the ADMA2 descriptor structure. */
typedef struct _sdhc_adma2_descriptor typedef struct _sdhc_adma2_descriptor
{ {
uint32_t attribute; /*!< The control and status field */ uint32_t attribute; /*!< The control and status field */
@ -429,7 +427,7 @@ typedef struct _sdhc_adma2_descriptor
/*! /*!
* @brief SDHC capability information. * @brief SDHC capability information.
* *
* Define structure to save the capability information of SDHC. * Defines a structure to save the capability information of SDHC.
*/ */
typedef struct _sdhc_capability typedef struct _sdhc_capability
{ {
@ -457,9 +455,9 @@ typedef struct _sdhc_transfer_config
/*! @brief Data structure to configure the MMC boot feature */ /*! @brief Data structure to configure the MMC boot feature */
typedef struct _sdhc_boot_config typedef struct _sdhc_boot_config
{ {
uint32_t ackTimeoutCount; /*!< Timeout value for the boot ACK */ uint32_t ackTimeoutCount; /*!< Timeout value for the boot ACK. The available range is 0 ~ 15. */
sdhc_boot_mode_t bootMode; /*!< Boot mode selection. */ sdhc_boot_mode_t bootMode; /*!< Boot mode selection. */
uint32_t blockCount; /*!< Stop at block gap value of automatic mode */ uint32_t blockCount; /*!< Stop at block gap value of automatic mode. Available range is 0 ~ 65535. */
bool enableBootAck; /*!< Enable or disable boot ACK */ bool enableBootAck; /*!< Enable or disable boot ACK */
bool enableBoot; /*!< Enable or disable fast boot */ bool enableBoot; /*!< Enable or disable fast boot */
bool enableAutoStopAtBlockGap; /*!< Enable or disable auto stop at block gap function in boot period */ bool enableAutoStopAtBlockGap; /*!< Enable or disable auto stop at block gap function in boot period */
@ -471,15 +469,15 @@ typedef struct _sdhc_config
bool cardDetectDat3; /*!< Enable DAT3 as card detection pin */ bool cardDetectDat3; /*!< Enable DAT3 as card detection pin */
sdhc_endian_mode_t endianMode; /*!< Endian mode */ sdhc_endian_mode_t endianMode; /*!< Endian mode */
sdhc_dma_mode_t dmaMode; /*!< DMA mode */ sdhc_dma_mode_t dmaMode; /*!< DMA mode */
uint32_t readWatermarkLevel; /*!< Watermark level for DMA read operation */ uint32_t readWatermarkLevel; /*!< Watermark level for DMA read operation. Available range is 1 ~ 128. */
uint32_t writeWatermarkLevel; /*!< Watermark level for DMA write operation */ uint32_t writeWatermarkLevel; /*!< Watermark level for DMA write operation. Available range is 1 ~ 128. */
} sdhc_config_t; } sdhc_config_t;
/*! /*!
* @brief Card data descriptor * @brief Card data descriptor
* *
* Define structure to contain data-related attribute. 'enableIgnoreError' is used for the case that upper card driver * Defines a structure to contain data-related attribute. 'enableIgnoreError' is used for the case that upper card
* want to ignore the error event to read/write all the data not to stop read/write immediately when error event * driver want to ignore the error event to read/write all the data not to stop read/write immediately when error event
* happen for example bus testing procedure for MMC card. * happen for example bus testing procedure for MMC card.
*/ */
typedef struct _sdhc_data typedef struct _sdhc_data
@ -530,10 +528,11 @@ typedef struct _sdhc_transfer_callback
} sdhc_transfer_callback_t; } sdhc_transfer_callback_t;
/*! /*!
* @brief Host descriptor * @brief SDHC handle
* *
* Define the structure to save the SDHC state information and callback function. The detail interrupt status when * Defines the structure to save the SDHC state information and callback function. The detailed interrupt status when
* send command or transfer data can be obtained from interruptFlags field by using mask defined in sdhc_interrupt_flag_t; * sending a command or transfering data can be obtained from the interruptFlags field by using the mask defined in
* sdhc_interrupt_flag_t.
* *
* @note All the fields except interruptFlags and transferredWords must be allocated by the user. * @note All the fields except interruptFlags and transferredWords must be allocated by the user.
*/ */
@ -580,16 +579,16 @@ extern "C" {
/*! /*!
* @brief SDHC module initialization function. * @brief SDHC module initialization function.
* *
* Configure the SDHC according to the user configuration. * Configures the SDHC according to the user configuration.
* *
* Example: * Example:
@code @code
sdhc_config_t config; sdhc_config_t config;
config.enableDat3AsCDPin = false; config.cardDetectDat3 = false;
config.endianMode = kSDHC_EndianModeLittle; config.endianMode = kSDHC_EndianModeLittle;
config.dmaMode = kSDHC_DmaModeAdma2; config.dmaMode = kSDHC_DmaModeAdma2;
config.readWatermarkLevel = 512U; config.readWatermarkLevel = 128U;
config.writeWatermarkLevel = 512U; config.writeWatermarkLevel = 128U;
SDHC_Init(SDHC, &config); SDHC_Init(SDHC, &config);
@endcode @endcode
* *
@ -600,14 +599,14 @@ extern "C" {
void SDHC_Init(SDHC_Type *base, const sdhc_config_t *config); void SDHC_Init(SDHC_Type *base, const sdhc_config_t *config);
/*! /*!
* @brief Deinitialize the SDHC. * @brief Deinitializes the SDHC.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
*/ */
void SDHC_Deinit(SDHC_Type *base); void SDHC_Deinit(SDHC_Type *base);
/*! /*!
* @brief Reset the SDHC. * @brief Resets the SDHC.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param mask The reset type mask(_sdhc_reset). * @param mask The reset type mask(_sdhc_reset).
@ -625,7 +624,7 @@ bool SDHC_Reset(SDHC_Type *base, uint32_t mask, uint32_t timeout);
*/ */
/*! /*!
* @brief Set ADMA descriptor table configuration. * @brief Sets the ADMA descriptor table configuration.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param dmaMode DMA mode. * @param dmaMode DMA mode.
@ -651,7 +650,7 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base,
*/ */
/*! /*!
* @brief Enable interrupt status * @brief Enables the interrupt status.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param mask Interrupt status flags mask(_sdhc_interrupt_status_flag). * @param mask Interrupt status flags mask(_sdhc_interrupt_status_flag).
@ -662,7 +661,7 @@ static inline void SDHC_EnableInterruptStatus(SDHC_Type *base, uint32_t mask)
} }
/*! /*!
* @brief Disable interrupt status. * @brief Disables the interrupt status.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param mask The interrupt status flags mask(_sdhc_interrupt_status_flag). * @param mask The interrupt status flags mask(_sdhc_interrupt_status_flag).
@ -673,7 +672,7 @@ static inline void SDHC_DisableInterruptStatus(SDHC_Type *base, uint32_t mask)
} }
/*! /*!
* @brief Enable interrupts signal corresponding to the interrupt status flag. * @brief Enables the interrupt signal corresponding to the interrupt status flag.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param mask The interrupt status flags mask(_sdhc_interrupt_status_flag). * @param mask The interrupt status flags mask(_sdhc_interrupt_status_flag).
@ -684,7 +683,7 @@ static inline void SDHC_EnableInterruptSignal(SDHC_Type *base, uint32_t mask)
} }
/*! /*!
* @brief Disable interrupts signal corresponding to the interrupt status flag. * @brief Disables the interrupt signal corresponding to the interrupt status flag.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param mask The interrupt status flags mask(_sdhc_interrupt_status_flag). * @param mask The interrupt status flags mask(_sdhc_interrupt_status_flag).
@ -702,7 +701,7 @@ static inline void SDHC_DisableInterruptSignal(SDHC_Type *base, uint32_t mask)
*/ */
/*! /*!
* @brief Get current interrupt status. * @brief Gets the current interrupt status.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @return Current interrupt status flags mask(_sdhc_interrupt_status_flag). * @return Current interrupt status flags mask(_sdhc_interrupt_status_flag).
@ -713,7 +712,7 @@ static inline uint32_t SDHC_GetInterruptStatusFlags(SDHC_Type *base)
} }
/*! /*!
* @brief Clear specified interrupt status. * @brief Clears a specified interrupt status.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param mask The interrupt status flags mask(_sdhc_interrupt_status_flag). * @param mask The interrupt status flags mask(_sdhc_interrupt_status_flag).
@ -724,7 +723,7 @@ static inline void SDHC_ClearInterruptStatusFlags(SDHC_Type *base, uint32_t mask
} }
/*! /*!
* @brief Get the status of auto command 12 error. * @brief Gets the status of auto command 12 error.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @return Auto command 12 error status flags mask(_sdhc_auto_command12_error_status_flag). * @return Auto command 12 error status flags mask(_sdhc_auto_command12_error_status_flag).
@ -735,7 +734,7 @@ static inline uint32_t SDHC_GetAutoCommand12ErrorStatusFlags(SDHC_Type *base)
} }
/*! /*!
* @brief Get the status of ADMA error. * @brief Gets the status of the ADMA error.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @return ADMA error status flags mask(_sdhc_adma_error_status_flag). * @return ADMA error status flags mask(_sdhc_adma_error_status_flag).
@ -746,9 +745,9 @@ static inline uint32_t SDHC_GetAdmaErrorStatusFlags(SDHC_Type *base)
} }
/*! /*!
* @brief Get present status. * @brief Gets a present status.
* *
* This function gets the present SDHC's status except for interrupt status and error status. * This function gets the present SDHC's status except for an interrupt status and an error status.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @return Present SDHC's status flags mask(_sdhc_present_status_flag). * @return Present SDHC's status flags mask(_sdhc_present_status_flag).
@ -766,7 +765,7 @@ static inline uint32_t SDHC_GetPresentStatusFlags(SDHC_Type *base)
*/ */
/*! /*!
* @brief Get the capability information * @brief Gets the capability information.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param capability Structure to save capability information. * @param capability Structure to save capability information.
@ -774,7 +773,7 @@ static inline uint32_t SDHC_GetPresentStatusFlags(SDHC_Type *base)
void SDHC_GetCapability(SDHC_Type *base, sdhc_capability_t *capability); void SDHC_GetCapability(SDHC_Type *base, sdhc_capability_t *capability);
/*! /*!
* @brief Enable or disable SD bus clock. * @brief Enables or disables the SD bus clock.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param enable True to enable, false to disable. * @param enable True to enable, false to disable.
@ -792,7 +791,7 @@ static inline void SDHC_EnableSdClock(SDHC_Type *base, bool enable)
} }
/*! /*!
* @brief Set SD bus clock frequency. * @brief Sets the SD bus clock frequency.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param srcClock_Hz SDHC source clock frequency united in Hz. * @param srcClock_Hz SDHC source clock frequency united in Hz.
@ -803,9 +802,10 @@ static inline void SDHC_EnableSdClock(SDHC_Type *base, bool enable)
uint32_t SDHC_SetSdClock(SDHC_Type *base, uint32_t srcClock_Hz, uint32_t busClock_Hz); uint32_t SDHC_SetSdClock(SDHC_Type *base, uint32_t srcClock_Hz, uint32_t busClock_Hz);
/*! /*!
* @brief Send 80 clocks to the card to set it to be active state. * @brief Sends 80 clocks to the card to set it to the active state.
* *
* This function must be called after each time the card is inserted to make card can receive command correctly. * This function must be called each time the card is inserted to ensure that the card can receive the command
* correctly.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param timeout Timeout to initialize card. * @param timeout Timeout to initialize card.
@ -815,7 +815,7 @@ uint32_t SDHC_SetSdClock(SDHC_Type *base, uint32_t srcClock_Hz, uint32_t busCloc
bool SDHC_SetCardActive(SDHC_Type *base, uint32_t timeout); bool SDHC_SetCardActive(SDHC_Type *base, uint32_t timeout);
/*! /*!
* @brief Set the data transfer width. * @brief Sets the data transfer width.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param width Data transfer width. * @param width Data transfer width.
@ -826,10 +826,10 @@ static inline void SDHC_SetDataBusWidth(SDHC_Type *base, sdhc_data_bus_width_t w
} }
/*! /*!
* @brief Set card transfer-related configuration. * @brief Sets the card transfer-related configuration.
* *
* This function fills card transfer-related command argument/transfer flag/data size. Command and data will be sent by * This function fills the card transfer-related command argument/transfer flag/data size. The command and data are sent
* SDHC after calling this function. * by SDHC after calling this function.
* *
* Example: * Example:
@code @code
@ -848,7 +848,7 @@ static inline void SDHC_SetDataBusWidth(SDHC_Type *base, sdhc_data_bus_width_t w
void SDHC_SetTransferConfig(SDHC_Type *base, const sdhc_transfer_config_t *config); void SDHC_SetTransferConfig(SDHC_Type *base, const sdhc_transfer_config_t *config);
/*! /*!
* @brief Get the command response. * @brief Gets the command response.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param index The index of response register, range from 0 to 3. * @param index The index of response register, range from 0 to 3.
@ -862,9 +862,9 @@ static inline uint32_t SDHC_GetCommandResponse(SDHC_Type *base, uint32_t index)
} }
/*! /*!
* @brief Fill the the data port. * @brief Fills the the data port.
* *
* This function is mainly used to implement the data transfer by Data Port instead of DMA. * This function is used to implement the data transfer by Data Port instead of DMA.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param data The data about to be sent. * @param data The data about to be sent.
@ -875,9 +875,9 @@ static inline void SDHC_WriteData(SDHC_Type *base, uint32_t data)
} }
/*! /*!
* @brief Retrieve the data from the data port. * @brief Retrieves the data from the data port.
* *
* This function is mainly used to implement the data transfer by Data Port instead of DMA. * This function is used to implement the data transfer by Data Port instead of DMA.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @return The data has been read. * @return The data has been read.
@ -888,7 +888,7 @@ static inline uint32_t SDHC_ReadData(SDHC_Type *base)
} }
/*! /*!
* @brief Enable or disable wakeup event in low power mode * @brief Enables or disables a wakeup event in low-power mode.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param mask Wakeup events mask(_sdhc_wakeup_event). * @param mask Wakeup events mask(_sdhc_wakeup_event).
@ -907,7 +907,7 @@ static inline void SDHC_EnableWakeupEvent(SDHC_Type *base, uint32_t mask, bool e
} }
/*! /*!
* @brief Enable or disable card detection level for test. * @brief Enables or disables the card detection level for testing.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param enable True to enable, false to disable. * @param enable True to enable, false to disable.
@ -925,11 +925,11 @@ static inline void SDHC_EnableCardDetectTest(SDHC_Type *base, bool enable)
} }
/*! /*!
* @brief Set card detection test level. * @brief Sets the card detection test level.
* *
* This function set the card detection test level to indicate whether the card is inserted into SDHC when DAT[3]/ * This function sets the card detection test level to indicate whether the card is inserted into the SDHC when DAT[3]/
* CD pin is selected as card detection pin. This function can also assert the pin logic when DAT[3]/CD pin is select * CD pin is selected as a card detection pin. This function can also assert the pin logic when DAT[3]/CD pin is
* as the card detection pin. * selected as the card detection pin.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param high True to set the card detect level to high. * @param high True to set the card detect level to high.
@ -947,7 +947,7 @@ static inline void SDHC_SetCardDetectTestLevel(SDHC_Type *base, bool high)
} }
/*! /*!
* @brief Enable or disable SDIO card control. * @brief Enables or disables the SDIO card control.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param mask SDIO card control flags mask(_sdhc_sdio_control_flag). * @param mask SDIO card control flags mask(_sdhc_sdio_control_flag).
@ -956,7 +956,7 @@ static inline void SDHC_SetCardDetectTestLevel(SDHC_Type *base, bool high)
void SDHC_EnableSdioControl(SDHC_Type *base, uint32_t mask, bool enable); void SDHC_EnableSdioControl(SDHC_Type *base, uint32_t mask, bool enable);
/*! /*!
* @brief Restart a transaction which has stopped at the block gap for SDIO card. * @brief Restarts a transaction which has stopped at the block GAP for the SDIO card.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
*/ */
@ -966,18 +966,18 @@ static inline void SDHC_SetContinueRequest(SDHC_Type *base)
} }
/*! /*!
* @brief Configure the MMC boot feature. * @brief Configures the MMC boot feature.
* *
* Example: * Example:
@code @code
sdhc_boot_config_t bootConfig; sdhc_boot_config_t config;
bootConfig.ackTimeoutCount = 4; config.ackTimeoutCount = 4;
bootConfig.bootMode = kSDHC_BootModeNormal; config.bootMode = kSDHC_BootModeNormal;
bootConfig.blockCount = 5; config.blockCount = 5;
bootConfig.enableBootAck = true; config.enableBootAck = true;
bootConfig.enableBoot = true; config.enableBoot = true;
enableBoot.enableAutoStopAtBlockGap = true; config.enableAutoStopAtBlockGap = true;
SDHC_SetMmcBootConfig(SDHC, &bootConfig); SDHC_SetMmcBootConfig(SDHC, &config);
@endcode @endcode
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
@ -986,7 +986,7 @@ static inline void SDHC_SetContinueRequest(SDHC_Type *base)
void SDHC_SetMmcBootConfig(SDHC_Type *base, const sdhc_boot_config_t *config); void SDHC_SetMmcBootConfig(SDHC_Type *base, const sdhc_boot_config_t *config);
/*! /*!
* @brief Force to generate events according to the given mask. * @brief Forces generating events according to the given mask.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param mask The force events mask(_sdhc_force_event). * @param mask The force events mask(_sdhc_force_event).
@ -1004,13 +1004,13 @@ static inline void SDHC_SetForceEvent(SDHC_Type *base, uint32_t mask)
*/ */
/*! /*!
* @brief Transfer command/data using blocking way. * @brief Transfers the command/data using a blocking method.
* *
* This function waits until the command response/data is got or SDHC encounters error by polling the status flag. * This function waits until the command response/data is received or the SDHC encounters an error by polling the status
* Application must not call this API in multiple threads at the same time because of that this API doesn't support * flag. The application must not call this API in multiple threads at the same time. Because of that this API doesn't support
* reentry mechanism. * the re-entry mechanism.
* *
* @note Needn't to call the API 'SDHC_TransferCreateHandle' when calling this API. * @note There is no need to call the API 'SDHC_TransferCreateHandle' when calling this API.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param admaTable ADMA table address, can't be null if transfer way is ADMA1/ADMA2. * @param admaTable ADMA table address, can't be null if transfer way is ADMA1/ADMA2.
@ -1028,7 +1028,7 @@ status_t SDHC_TransferBlocking(SDHC_Type *base,
sdhc_transfer_t *transfer); sdhc_transfer_t *transfer);
/*! /*!
* @brief Create the SDHC handle. * @brief Creates the SDHC handle.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param handle SDHC handle pointer. * @param handle SDHC handle pointer.
@ -1041,13 +1041,13 @@ void SDHC_TransferCreateHandle(SDHC_Type *base,
void *userData); void *userData);
/*! /*!
* @brief Transfer command/data using interrupt and asynchronous way. * @brief Transfers the command/data using an interrupt and an asynchronous method.
* *
* This function send command and data and return immediately. It doesn't wait the transfer complete or encounter error. * This function sends a command and data and returns immediately. It doesn't wait the transfer complete or encounter an
* Application must not call this API in multiple threads at the same time because of that this API doesn't support * error. The application must not call this API in multiple threads at the same time. Because of that this API doesn't support
* reentry mechanism. * the re-entry mechanism.
* *
* @note Must call the API 'SDHC_TransferCreateHandle' when calling this API. * @note Call the API 'SDHC_TransferCreateHandle' when calling this API.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param handle SDHC handle. * @param handle SDHC handle.
@ -1063,9 +1063,9 @@ status_t SDHC_TransferNonBlocking(
SDHC_Type *base, sdhc_handle_t *handle, uint32_t *admaTable, uint32_t admaTableWords, sdhc_transfer_t *transfer); SDHC_Type *base, sdhc_handle_t *handle, uint32_t *admaTable, uint32_t admaTableWords, sdhc_transfer_t *transfer);
/*! /*!
* @brief IRQ handler for SDHC * @brief IRQ handler for the SDHC.
* *
* This function deals with IRQs on the given host controller. * This function deals with the IRQs on the given host controller.
* *
* @param base SDHC peripheral base address. * @param base SDHC peripheral base address.
* @param handle SDHC handle. * @param handle SDHC handle.