aboutsummaryrefslogtreecommitdiff
path: root/KSDK_1.2.0/platform/composite/src
diff options
context:
space:
mode:
Diffstat (limited to 'KSDK_1.2.0/platform/composite/src')
-rwxr-xr-xKSDK_1.2.0/platform/composite/src/sdcard/fsl_sdcard_spi.c1074
-rwxr-xr-xKSDK_1.2.0/platform/composite/src/sdcard/fsl_sdhc_card.c1576
-rwxr-xr-xKSDK_1.2.0/platform/composite/src/soundcard/fsl_soundcard.c612
3 files changed, 3262 insertions, 0 deletions
diff --git a/KSDK_1.2.0/platform/composite/src/sdcard/fsl_sdcard_spi.c b/KSDK_1.2.0/platform/composite/src/sdcard/fsl_sdcard_spi.c
new file mode 100755
index 0000000..d2caa9a
--- /dev/null
+++ b/KSDK_1.2.0/platform/composite/src/sdcard/fsl_sdcard_spi.c
@@ -0,0 +1,1074 @@
+/*
+ * Copyright (c) 2014, Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include "fsl_os_abstraction.h"
+
+#include "fsl_sdmmc_card.h"
+#include "fsl_sdcard_spi.h"
+
+/* rate unit is divided by 1000 */
+static const uint32_t g_transpeedru[] =
+{
+ /* 100Kbps, 1Mbps, 10Mbps, 100Mbps*/
+ 100, 1000, 10000, 100000,
+};
+
+/* time value multiplied by 1000 */
+static const uint32_t g_transpeedtv[] =
+{
+ 0, 1000, 1200, 1300,
+ 1500, 2000, 2500, 3000,
+ 3500, 4000, 4500, 5000,
+ 5500, 6000, 7000, 8000,
+};
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDSPI_DRV_GenerateCRC7
+ * Description: calculate CRC7
+ *
+ *END*********************************************************************/
+static uint32_t SDSPI_DRV_GenerateCRC7(uint8_t *buffer,
+ uint32_t length,
+ uint32_t crc)
+{
+ uint32_t index;
+
+ static const uint8_t crcTable[] = {
+ 0x00, 0x09, 0x12, 0x1B, 0x24, 0x2D, 0x36, 0x3F,
+ 0x48, 0x41, 0x5A, 0x53, 0x6C, 0x65, 0x7E, 0x77
+ };
+
+ while (length)
+ {
+ index = ((crc >> 3) & 0x0F) ^ ((*buffer) >> 4);
+ crc = (crc << 4) ^ crcTable[index];
+
+ index = ((crc >> 3) & 0x0F) ^ ((*buffer) & 0x0F);
+ crc = (crc << 4) ^ crcTable[index];
+
+ buffer++;
+ length--;
+ }
+
+ return (crc & 0x7F);
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDSPI_DRV_WaitReady
+ * Description: wait ready
+ *
+ *END*********************************************************************/
+static sdspi_status_t SDSPI_DRV_WaitReady(sdspi_spi_t *spi)
+{
+ uint8_t response;
+ uint32_t startTime, elapsedTime;
+
+ startTime = OSA_TimeGetMsec();
+ do
+ {
+ response = spi->ops->sendWord(spi, 0xFF);
+ elapsedTime = OSA_TimeGetMsec() - startTime;
+ } while ((response != 0xFF) && elapsedTime < 500);
+
+ if (response != 0xFF)
+ {
+ return kStatus_SDSPI_CardIsBusyError;
+ }
+
+ return kStatus_SDSPI_NoError;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDSPI_DRV_SendCommand
+ * Description: send command
+ *
+ *END*********************************************************************/
+static sdspi_status_t SDSPI_DRV_SendCommand(sdspi_spi_t *spi,
+ sdspi_request_t *req,
+ uint32_t timeout)
+{
+ uint8_t buffer[6];
+ uint8_t response;
+ uint8_t i;
+ sdspi_status_t result = kStatus_SDSPI_NoError;
+
+ assert(spi);
+ assert(req);
+
+ result = SDSPI_DRV_WaitReady(spi);
+ if ((result == kStatus_SDSPI_CardIsBusyError)
+ && (req->cmdIndex != kGoIdleState))
+ {
+ return result;
+ }
+
+ buffer[0] = SDSPI_MAKE_CMD(req->cmdIndex);
+ buffer[1] = req->argument >> 24 & 0xFF;
+ buffer[2] = req->argument >> 16 & 0xFF;
+ buffer[3] = req->argument >> 8 & 0xFF;
+ buffer[4] = req->argument & 0xFF;
+ buffer[5] = (SDSPI_DRV_GenerateCRC7(buffer, 5, 0) << 1) | 1;
+
+ if (spi->ops->exchange(spi, buffer, NULL, sizeof(buffer)))
+ {
+ return kStatus_SDSPI_TransferFailed;
+ }
+
+ if (req->cmdIndex == kStopTransmission)
+ {
+ spi->ops->sendWord(spi, 0xFF);
+ }
+ /* Wait for the response coming, the left most bit which is transfered first in response is 0 */
+ for (i = 0; i < 9; i++)
+ {
+ response = spi->ops->sendWord(spi, 0xFF);
+ if (!(response & 0x80))
+ {
+ break;
+ }
+ }
+
+ if ((response & 0x80))
+ {
+ return kStatus_SDSPI_Failed;
+ }
+
+ req->response[0] = response;
+ switch(req->respType)
+ {
+ case kSdSpiRespTypeR1:
+ break;
+ case kSdSpiRespTypeR1b:
+ {
+ uint8_t busy = 0;
+ uint32_t startTime, elapsedTime;
+ startTime = OSA_TimeGetMsec();
+ while (busy != 0xFF)
+ {
+ busy = spi->ops->sendWord(spi, 0xFF);
+ elapsedTime = OSA_TimeGetMsec() - startTime;
+ if (elapsedTime > timeout)
+ {
+ break;
+ }
+ }
+ if (busy != 0xFF)
+ {
+ result = kStatus_SDSPI_CardIsBusyError;
+ }
+ break;
+ }
+ case kSdSpiRespTypeR2:
+ req->response[1] = spi->ops->sendWord(spi, 0xFF);
+ break;
+ case kSdSpiRespTypeR3:
+ case kSdSpiRespTypeR7:
+ default:
+ for (i = 1; i <= 4; i++)/* R7 has total 5 bytes in SPI mode. */
+ {
+ req->response[i] = spi->ops->sendWord(spi, 0xFF);
+ }
+ break;
+ }
+
+
+ return kStatus_SDSPI_NoError;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDSPI_DRV_GoIdle
+ * Description: send CMD0
+ *
+ *END*********************************************************************/
+static sdspi_status_t SDSPI_DRV_GoIdle(sdspi_spi_t *spi, sdspi_card_t *card)
+{
+ uint32_t i, j;
+ sdspi_request_t *req;
+ assert(card);
+
+ req = (sdspi_request_t *)OSA_MemAllocZero(sizeof(sdspi_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDSPI_OutOfMemory;
+ }
+
+ /*
+ * SD card will enter SPI mode if the CS is asserted (negative) during the
+ * reception of the reset command (CMD0) and the card is in IDLE state.
+ */
+ for (i = 0; i < 2; i++)
+ {
+ for (j = 0; j < 10; j++)
+ {
+ spi->ops->sendWord(spi, 0xFF);
+ }
+
+ req->cmdIndex = kGoIdleState;
+ req->respType = kSdSpiRespTypeR1;
+ if (kStatus_SDSPI_NoError != SDSPI_DRV_SendCommand(spi, req, SDSPI_TIMEOUT))
+ {
+ OSA_MemFree(req);
+ return kStatus_SDSPI_Failed;
+ }
+
+ if (req->response[0] == SDMMC_SPI_R1_IN_IDLE_STATE)
+ {
+ break;
+ }
+ }
+
+ if (req->response[0] != SDMMC_SPI_R1_IN_IDLE_STATE)
+ {
+ OSA_MemFree(req);
+ return kStatus_SDSPI_Failed;
+ }
+
+ OSA_MemFree(req);
+ return kStatus_SDSPI_NoError;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDSPI_DRV_SendApplicationCmd
+ * Description: send application command to card
+ *
+ *END*********************************************************************/
+static sdspi_status_t SDSPI_DRV_SendApplicationCmd(sdspi_spi_t *spi)
+{
+ sdspi_request_t *req;
+
+ req = (sdspi_request_t *)OSA_MemAllocZero(sizeof(sdspi_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDSPI_OutOfMemory;
+ }
+
+ req->cmdIndex = kAppCmd;
+ req->respType = kSdSpiRespTypeR1;
+ if (kStatus_SDSPI_NoError != SDSPI_DRV_SendCommand(spi, req, SDSPI_TIMEOUT))
+ {
+ OSA_MemFree(req);
+ return kStatus_SDSPI_Failed;
+ }
+
+ if (req->response[0] && !(req->response[0] & SDMMC_SPI_R1_IN_IDLE_STATE))
+ {
+ OSA_MemFree(req);
+ return kStatus_SDSPI_Failed;
+ }
+
+ OSA_MemFree(req);
+ return kStatus_SDSPI_NoError;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDSPI_DRV_AppSendOpCond
+ * Description: Get the card to send its operating condition.
+ *
+ *END*********************************************************************/
+static sdspi_status_t SDSPI_DRV_AppSendOpCond(sdspi_spi_t *spi,
+ sdspi_card_t *card,
+ uint32_t argument,
+ uint8_t *response)
+{
+ sdspi_request_t *req;
+ uint32_t startTime, elapsedTime = 0;
+ assert(card);
+
+ req = (sdspi_request_t *)OSA_MemAllocZero(sizeof(sdspi_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDSPI_OutOfMemory;
+ }
+
+ req->cmdIndex = kSdAppSendOpCond;
+ req->argument = argument;
+ req->respType = kSdSpiRespTypeR1;
+
+ startTime = OSA_TimeGetMsec();
+ do
+ {
+ if (kStatus_SDSPI_NoError == SDSPI_DRV_SendApplicationCmd(spi))
+ {
+ if (kStatus_SDSPI_NoError == SDSPI_DRV_SendCommand(spi, req, SDSPI_TIMEOUT))
+ {
+ if (!req->response[0])
+ {
+ break;
+ }
+ }
+ }
+ elapsedTime = OSA_TimeGetMsec() - startTime;
+ } while (elapsedTime < 1000);
+
+ if (response)
+ {
+ memcpy(response, req->response, sizeof(req->response));
+ }
+ OSA_MemFree(req);
+
+ if (elapsedTime < 1000)
+ {
+ return kStatus_SDSPI_NoError;
+ }
+ return kStatus_SDSPI_TimeoutError;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDSPI_DRV_SendIfCond
+ * Description: check card interface condition, which includes host supply
+ * voltage information and asks the card whether card supports voltage.
+ *
+ *END*********************************************************************/
+static sdspi_status_t SDSPI_DRV_SendIfCond(sdspi_spi_t *spi,
+ sdspi_card_t *card,
+ uint8_t pattern,
+ uint8_t *response)
+{
+ sdspi_request_t *req;
+
+ assert(card);
+ assert(response);
+
+ req = (sdspi_request_t *)OSA_MemAllocZero(sizeof(sdspi_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDSPI_OutOfMemory;
+ }
+
+ req->cmdIndex = kSdSendIfCond;
+ req->argument = 0x100 | (pattern & 0xFF);
+ req->respType = kSdSpiRespTypeR7;
+ if (kStatus_SDSPI_NoError != SDSPI_DRV_SendCommand(spi, req, SDSPI_TIMEOUT))
+ {
+ OSA_MemFree(req);
+ return kStatus_SDSPI_Failed;
+ }
+
+ memcpy(response, req->response, sizeof(req->response));
+
+ OSA_MemFree(req);
+ return kStatus_SDSPI_NoError;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDSPI_DRV_ReadOcr
+ * Description: Get OCR register from card
+ *
+ *END*********************************************************************/
+static sdspi_status_t SDSPI_DRV_ReadOcr(sdspi_spi_t *spi, sdspi_card_t *card)
+{
+ uint32_t i;
+ sdspi_request_t *req;
+ assert(card);
+
+ req = (sdspi_request_t *)OSA_MemAllocZero(sizeof(sdspi_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDSPI_OutOfMemory;
+ }
+ req->cmdIndex = kReadOcr;
+ req->respType = kSdSpiRespTypeR3;
+ if (kStatus_SDSPI_NoError != SDSPI_DRV_SendCommand(spi, req, SDSPI_TIMEOUT))
+ {
+ OSA_MemFree(req);
+ return kStatus_SDSPI_Failed;
+ }
+ if (req->response[0])
+ {
+ OSA_MemFree(req);
+ return kStatus_SDSPI_Failed;
+ }
+
+ card->ocr = 0;
+ for (i = 4; i > 0; i--)
+ {
+ card->ocr |= (uint32_t) req->response[i] << ((4 - i) * 8);
+ }
+
+ OSA_MemFree(req);
+ return kStatus_SDSPI_NoError;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDSPI_DRV_Write
+ * Description: write data to card
+ *
+ *END*********************************************************************/
+static uint32_t SDSPI_DRV_Write(sdspi_spi_t *spi, uint8_t *buffer, uint32_t size, uint8_t token)
+{
+ uint8_t response;
+ assert(spi);
+ assert(spi->ops);
+ assert(spi->ops->exchange);
+
+ if (SDSPI_DRV_WaitReady(spi) != kStatus_SDSPI_NoError)
+ {
+ return 0;
+ }
+
+ spi->ops->sendWord(spi, token);
+
+ if (token == SDMMC_SPI_DT_STOP_TRANSFER)
+ {
+ return size;
+ }
+
+ assert(size);
+ assert(buffer);
+
+ if (spi->ops->exchange(spi, buffer, NULL, size))
+ {
+ return 0;
+ }
+
+ /* Send CRC */
+ spi->ops->sendWord(spi, 0xFF);
+ spi->ops->sendWord(spi, 0xFF);
+
+ response = spi->ops->sendWord(spi, 0xFF);
+ if ((response & SDMMC_SPI_DR_MASK) != SDMMC_SPI_DR_ACCEPTED)
+ {
+ return 0;
+ }
+ return size;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDSPI_DRV_Read
+ * Description: read data from card
+ *
+ *END*********************************************************************/
+static uint32_t SDSPI_DRV_Read(sdspi_spi_t *spi, uint8_t *buffer, uint32_t size)
+{
+ uint32_t startTime, elapsedTime;
+ uint8_t response;
+ assert(spi);
+ assert(spi->ops);
+ assert(spi->ops->exchange);
+ assert(buffer);
+ assert(size);
+ memset(buffer, 0xFF, size);
+ startTime = OSA_TimeGetMsec();
+ do
+ {
+ response = spi->ops->sendWord(spi, 0xFF);
+ elapsedTime = OSA_TimeGetMsec() - startTime;
+ } while ((response == 0xFF) && elapsedTime < 100);
+
+ if (response != SDMMC_SPI_DT_START_SINGLE_BLK)
+ {
+ return 0;
+ }
+
+ if (spi->ops->exchange(spi, buffer, buffer, size))
+ {
+ return 0;
+ }
+
+ spi->ops->sendWord(spi, 0xFF);
+ spi->ops->sendWord(spi, 0xFF);
+
+ return size;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDSPI_DRV_SendCsd
+ * Description: get CSD register from card
+ *
+ *END*********************************************************************/
+static sdspi_status_t SDSPI_DRV_SendCsd(sdspi_spi_t *spi, sdspi_card_t *card)
+{
+ sdspi_request_t *req;
+ assert(card);
+
+ req = (sdspi_request_t *)OSA_MemAllocZero(sizeof(sdspi_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDSPI_OutOfMemory;
+ }
+
+ req->cmdIndex = kSendCsd;
+ req->respType = kSdSpiRespTypeR1;
+ if (kStatus_SDSPI_NoError != SDSPI_DRV_SendCommand(spi, req, SDSPI_TIMEOUT))
+ {
+ OSA_MemFree(req);
+ return kStatus_SDSPI_Failed;
+ }
+ OSA_MemFree(req);
+
+ if (sizeof(card->rawCsd) !=
+ (SDSPI_DRV_Read(spi, card->rawCsd, sizeof(card->rawCsd))))
+ {
+ return kStatus_SDSPI_Failed;
+ }
+
+ /* No start single block token if found */
+ return kStatus_SDSPI_NoError;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDSPI_DRV_SetBlockSize
+ * Description: set the block length in bytes for SDSC cards. For SDHC cards,
+ * it does not affect memory read or write commands, always 512 bytes fixed
+ * block length is used.
+ *
+ *END*********************************************************************/
+static sdspi_status_t SDSPI_DRV_SetBlockSize(sdspi_spi_t *spi, uint32_t blockSize)
+{
+ sdspi_request_t *req = 0;
+
+ req = (sdspi_request_t *)OSA_MemAllocZero(sizeof(sdspi_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDSPI_OutOfMemory;
+ }
+ req->cmdIndex = kSetBlockLen;
+ req->argument = blockSize;
+ req->respType = kSdSpiRespTypeR1;
+
+ if (kStatus_SDSPI_NoError != SDSPI_DRV_SendCommand(spi, req, SDSPI_TIMEOUT))
+ {
+ OSA_MemFree(req);
+ req = NULL;
+ return kStatus_SDSPI_Failed;
+ }
+
+ OSA_MemFree(req);
+ req = NULL;
+ return kStatus_SDSPI_NoError;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDSPI_DRV_CheckCapacity
+ * Description: check card capacity of the card
+ *
+ *END*********************************************************************/
+static void SDSPI_DRV_CheckCapacity(sdspi_card_t *card)
+{
+ uint32_t cSize, cSizeMult, readBlkLen;
+
+ if (SDMMC_CSD_CSDSTRUCTURE_VERSION(card->rawCsd))
+ {
+ /* SD CSD structure v2.xx */
+ cSize = SDV20_CSD_CSIZE(card->rawCsd);
+ if (cSize >= 0xFFFF)
+ {
+ /* extended capacity */
+ card->caps |= SDSPI_CAPS_SDXC;
+ }
+ else
+ {
+ card->caps |= SDSPI_CAPS_SDHC;
+ }
+ cSizeMult = 10;
+ cSize += 1;
+ readBlkLen = 9;
+ }
+ else
+ {
+ /* SD CSD structure v1.xx */
+ cSize = SDMMC_CSD_CSIZE(card->rawCsd) + 1;
+ cSizeMult = SDMMC_CSD_CSIZEMULT(card->rawCsd) + 2;
+ readBlkLen = SDMMC_CSD_READBLK_LEN(card->rawCsd);
+ }
+
+ if (readBlkLen != 9)
+ {
+ /* Force to use 512-byte length block */
+ cSizeMult += (readBlkLen - 9);
+ readBlkLen = 9;
+ }
+
+ card->blockSize = 1 << readBlkLen;
+ card->blockCount = cSize << cSizeMult;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDSPI_DRV_SendCid
+ * Description: get CID information from card
+ *
+ *END*********************************************************************/
+static sdspi_status_t SDSPI_DRV_SendCid(sdspi_spi_t *spi, sdspi_card_t *card)
+{
+ sdspi_request_t *req = 0;
+
+ req = (sdspi_request_t *)OSA_MemAllocZero(sizeof(sdspi_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDSPI_OutOfMemory;
+ }
+ req->cmdIndex = kSendCid;
+ req->respType = kSdSpiRespTypeR1;
+
+ if (kStatus_SDSPI_NoError != SDSPI_DRV_SendCommand(spi, req, SDSPI_TIMEOUT))
+ {
+ OSA_MemFree(req);
+ req = NULL;
+ return kStatus_SDSPI_Failed;
+ }
+
+ OSA_MemFree(req);
+ req = NULL;
+
+ if (sizeof(card->rawCid) !=
+ (SDSPI_DRV_Read(spi, card->rawCid, sizeof(card->rawCid))))
+ {
+ return kStatus_SDSPI_Failed;
+ }
+
+ return kStatus_SDSPI_NoError;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDSPI_DRV_InitSd
+ * Description: initialize SD card
+ *
+ *END*********************************************************************/
+static sdspi_status_t SDSPI_DRV_InitSd(sdspi_spi_t *spi, sdspi_card_t *card)
+{
+ uint32_t maxFrequency;
+ assert(spi);
+ assert(spi->ops);
+ assert(spi->ops->getMaxFrequency);
+ assert(spi->ops->setFrequency);
+ assert(card);
+
+ if (kStatus_SDSPI_NoError != SDSPI_DRV_SendCsd(spi, card))
+ {
+ return kStatus_SDSPI_Failed;
+ }
+
+ /* Calculate frequency */
+ maxFrequency = g_transpeedtv[SDMMC_CSD_TRANSPEED_TV(card->rawCsd)] *
+ g_transpeedru[SDMMC_CSD_TRANSPEED_RU(card->rawCsd)];
+ if (maxFrequency > spi->busBaudRate)
+ {
+ maxFrequency = spi->ops->getMaxFrequency(spi);
+ }
+ spi->ops->setFrequency(spi, maxFrequency);
+
+ SDSPI_DRV_CheckCapacity(card);
+ SDSPI_DRV_CheckReadOnly(spi, card);
+
+ if (kStatus_SDSPI_NoError != SDSPI_DRV_SendCid(spi, card))
+ {
+ return kStatus_SDSPI_Failed;
+ }
+
+ return kStatus_SDSPI_NoError;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDSPI_DRV_Init
+ * Description: initialize card on the given host controller
+ *
+ *END*********************************************************************/
+sdspi_status_t SDSPI_DRV_Init(sdspi_spi_t *spi, sdspi_card_t *card)
+{
+ uint32_t startTime, elapsedTime, acmd41Arg;
+ uint8_t response[5], acmd41resp[5];
+ bool likelyMmc = false, likelySdV1 = false;
+ assert(card);
+ assert(spi);
+ assert(spi->ops);
+ assert(spi->ops->exchange);
+ assert(spi->ops->setFrequency);
+ assert(spi->ops->sendWord);
+
+ card->cardType = kCardTypeUnknown;
+ if (spi->ops->setFrequency(spi, SDMMC_CLK_400KHZ))
+ {
+ return kStatus_SDSPI_Failed;
+ }
+
+ if (kStatus_SDSPI_NoError != SDSPI_DRV_GoIdle(spi, card))
+ {
+ return kStatus_SDSPI_Failed;
+ }
+
+ acmd41Arg = 0;
+ if (kStatus_SDSPI_NoError !=
+ SDSPI_DRV_SendIfCond(spi, card, 0xAA, response))
+ {
+ likelySdV1 = true;
+ }
+ else if ((response[3] == 0x1) || (response[4] == 0xAA))
+ {
+ acmd41Arg |= SD_OCR_HCS;
+ }
+ else
+ {
+ return kStatus_SDSPI_Failed;
+ }
+
+ startTime = OSA_TimeGetMsec();
+ do
+ {
+ if (kStatus_SDSPI_NoError !=
+ SDSPI_DRV_AppSendOpCond(spi, card, acmd41Arg, acmd41resp))
+ {
+ if (likelySdV1)
+ {
+ likelyMmc = true;
+ break;
+ }
+ return kStatus_SDSPI_Failed;
+ }
+ elapsedTime = OSA_TimeGetMsec() - startTime;
+ if (!acmd41resp[0])
+ {
+ break;
+ }
+ if (elapsedTime > 500)
+ {
+ if (likelySdV1)
+ {
+ likelyMmc = true;
+ break;
+ }
+ }
+ } while(acmd41resp[0] == SDMMC_SPI_R1_IN_IDLE_STATE);
+
+ if (likelyMmc)
+ {
+ card->cardType = kCardTypeMmc;
+ return kStatus_SDSPI_NotSupportYet;
+ }
+ else
+ {
+ card->cardType = kCardTypeSd;
+ }
+
+ if (!likelySdV1)
+ {
+ card->version = kSdCardVersion_2_x;
+ if (kStatus_SDSPI_NoError != SDSPI_DRV_ReadOcr(spi, card))
+ {
+ return kStatus_SDSPI_Failed;
+ }
+ if (card->ocr & SD_OCR_CCS)
+ {
+ card->caps = SDSPI_CAPS_ACCESS_IN_BLOCK;
+ }
+ }
+ else
+ {
+ card->version = kSdCardVersion_1_x;
+ }
+
+ /* Force to use 512-byte length block, no matter which version */
+ if (kStatus_SDSPI_NoError != SDSPI_DRV_SetBlockSize(spi, 512))
+ {
+ return kStatus_SDSPI_Failed;
+ }
+
+ if (kStatus_SDSPI_NoError != SDSPI_DRV_InitSd(spi, card))
+ {
+ return kStatus_SDSPI_Failed;
+ }
+
+ return kStatus_SDSPI_NoError;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDSPI_DRV_StopTransmission
+ * Description: Send stop transmission command to card to stop ongoing
+ * data transferring.
+ *
+ *END*********************************************************************/
+static sdspi_status_t SDSPI_DRV_StopTransmission(sdspi_spi_t *spi)
+{
+ sdspi_request_t *req = 0;
+
+ req = (sdspi_request_t *)OSA_MemAllocZero(sizeof(sdspi_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDSPI_OutOfMemory;
+ }
+
+ req->cmdIndex = kStopTransmission;
+ req->respType = kSdSpiRespTypeR1b;
+ if (kStatus_SDSPI_NoError != SDSPI_DRV_SendCommand(spi, req, SDSPI_TIMEOUT))
+ {
+ OSA_MemFree(req);
+ return kStatus_SDSPI_Failed;
+ }
+
+ OSA_MemFree(req);
+ return kStatus_SDSPI_NoError;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDSPI_DRV_ReadBlocks
+ * Description: read blocks from card
+ *
+ *END*********************************************************************/
+sdspi_status_t SDSPI_DRV_ReadBlocks(sdspi_spi_t *spi, sdspi_card_t *card, uint8_t *buffer,
+ uint32_t startBlock, uint32_t blockCount)
+{
+ uint32_t offset, i;
+ sdspi_request_t *req;
+ assert(spi);
+ assert(card);
+ assert(buffer);
+ assert(blockCount);
+
+ req = (sdspi_request_t *)OSA_MemAllocZero(sizeof(sdspi_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDSPI_OutOfMemory;
+ }
+
+ offset = startBlock;
+ if (!IS_BLOCK_ACCESS(card))
+ {
+ offset *= card->blockSize;
+ }
+
+ req->argument = offset;
+ req->respType = kSdSpiRespTypeR1;
+ if (blockCount == 1)
+ {
+ req->cmdIndex = kReadSingleBlock;
+
+ if (kStatus_SDSPI_NoError != SDSPI_DRV_SendCommand(spi, req, SDSPI_TIMEOUT))
+ {
+ OSA_MemFree(req);
+ return kStatus_SDSPI_Failed;
+ }
+ OSA_MemFree(req);
+
+ if (SDSPI_DRV_Read(spi, buffer, card->blockSize) != card->blockSize)
+ {
+ return kStatus_SDSPI_Failed;
+ }
+ }
+ else
+ {
+ req->cmdIndex = kReadMultipleBlock;
+
+ if (kStatus_SDSPI_NoError != SDSPI_DRV_SendCommand(spi, req, SDSPI_TIMEOUT))
+ {
+ OSA_MemFree(req);
+ return kStatus_SDSPI_Failed;
+ }
+ OSA_MemFree(req);
+
+ for (i = 0; i < blockCount; i++)
+ {
+ if (SDSPI_DRV_Read(spi, buffer, card->blockSize) != card->blockSize)
+ {
+ return kStatus_SDSPI_Failed;
+ }
+ buffer += card->blockSize;
+ }
+ SDSPI_DRV_StopTransmission(spi);
+ }
+
+ return kStatus_SDSPI_NoError;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDSPI_DRV_WriteBlocks
+ * Description: write blocks to card
+ *
+ *END*********************************************************************/
+sdspi_status_t SDSPI_DRV_WriteBlocks(sdspi_spi_t *spi, sdspi_card_t *card, uint8_t *buffer,
+ uint32_t startBlock, uint32_t blockCount)
+{
+ uint32_t offset, i, startTime, elapsedTime;
+ uint8_t response;
+ sdspi_request_t *req;
+ assert(spi);
+ assert(card);
+ assert(buffer);
+ assert(blockCount);
+
+ if (card->state & SDSPI_STATE_WRITE_PROTECTED)
+ {
+ return kStatus_SDSPI_WriteProtected;
+ }
+
+ req = (sdspi_request_t *)OSA_MemAllocZero(sizeof(sdspi_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDSPI_OutOfMemory;
+ }
+
+ offset = startBlock;
+ if (!IS_BLOCK_ACCESS(card))
+ {
+ offset *= card->blockSize;
+ }
+
+ if (blockCount == 1)
+ {
+ req->cmdIndex = kWriteBlock;
+ req->argument = offset;
+ req->respType = kSdSpiRespTypeR1;
+ if (kStatus_SDSPI_NoError != SDSPI_DRV_SendCommand(spi, req, SDSPI_TIMEOUT))
+ {
+ OSA_MemFree(req);
+ return kStatus_SDSPI_Failed;
+ }
+ if (req->response[0])
+ {
+ OSA_MemFree(req);
+ return kStatus_SDSPI_Failed;
+ }
+
+ OSA_MemFree(req);
+ if (SDSPI_DRV_Write(spi, buffer, card->blockSize, SDMMC_SPI_DT_START_SINGLE_BLK) != card->blockSize)
+ {
+ return kStatus_SDSPI_Failed;
+ }
+ }
+ else
+ {
+#if defined FSL_SDSPI_ENABLE_PRE_ERASE_ON_WRITE
+ if (IS_SD_CARD(card))
+ {
+ /* Pre-erase before writing data */
+ if (kStatus_SDSPI_NoError != SDSPI_DRV_SendApplicationCmd(spi))
+ {
+ OSA_MemFree(req);
+ return kStatus_SDSPI_Failed;
+ }
+ req->cmdIndex = kSdAppSetWrBlkEraseCount;
+ req->argument = blockCount;
+ req->respType = kSdSpiRespTypeR1;
+ if (kStatus_SDSPI_NoError != SDSPI_DRV_SendCommand(spi, req, SDSPI_TIMEOUT))
+ {
+ OSA_MemFree(req);
+ return kStatus_SDSPI_Failed;
+ }
+ if (req->response[0])
+ {
+ OSA_MemFree(req);
+ return kStatus_SDSPI_Failed;
+ }
+ }
+#endif
+
+ memset(req, 0, sizeof(sdspi_request_t));
+ req->cmdIndex = kWriteMultipleBlock;
+ req->argument = offset;
+ req->respType = kSdSpiRespTypeR1;
+
+ if (kStatus_SDSPI_NoError != SDSPI_DRV_SendCommand(spi, req, SDSPI_TIMEOUT))
+ {
+ OSA_MemFree(req);
+ return kStatus_SDSPI_Failed;
+ }
+ if (req->response[0])
+ {
+ OSA_MemFree(req);
+ return kStatus_SDSPI_Failed;
+ }
+ OSA_MemFree(req);
+
+ for (i = 0; i < blockCount; i++)
+ {
+ if (SDSPI_DRV_Write(spi, buffer, card->blockSize, SDMMC_SPI_DT_START_MULTI_BLK) != card->blockSize)
+ {
+ return kStatus_SDSPI_Failed;
+ }
+ buffer += card->blockSize;
+ }
+
+ SDSPI_DRV_Write(spi, 0, 0, SDMMC_SPI_DT_STOP_TRANSFER);
+
+ startTime = OSA_TimeGetMsec();
+ do
+ {
+ response = spi->ops->sendWord(spi, 0xFF);
+ elapsedTime = OSA_TimeGetMsec() - startTime;
+ } while ((response != 0xFF) && (elapsedTime < 100));
+ }
+
+ return kStatus_SDSPI_NoError;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDSPI_DRV_CheckReadOnly
+ * Description: check if card is read only
+ *
+ *END*********************************************************************/
+bool SDSPI_DRV_CheckReadOnly(sdspi_spi_t* spi, sdspi_card_t *card)
+{
+ assert(card);
+
+ card->state &= ~SDSPI_STATE_WRITE_PROTECTED;
+ if (card->cardType != kCardTypeSd)
+ {
+ return false;
+ }
+
+ if (SD_CSD_PERM_WRITEPROTECT(card->rawCsd)
+ || SD_CSD_TEMP_WRITEPROTECT(card->rawCsd))
+ {
+ card->state |= SDSPI_STATE_WRITE_PROTECTED;
+ return true;
+ }
+
+ return false;
+}
+
+void SDSPI_DRV_Shutdown(sdspi_spi_t *spi, sdspi_card_t *card)
+{
+ assert(spi);
+ assert(card);
+
+ memset(card, 0, sizeof(sdspi_card_t));
+ return;
+}
diff --git a/KSDK_1.2.0/platform/composite/src/sdcard/fsl_sdhc_card.c b/KSDK_1.2.0/platform/composite/src/sdcard/fsl_sdhc_card.c
new file mode 100755
index 0000000..884c549
--- /dev/null
+++ b/KSDK_1.2.0/platform/composite/src/sdcard/fsl_sdhc_card.c
@@ -0,0 +1,1576 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include "fsl_os_abstraction.h"
+#include "fsl_sdhc_card.h"
+#include "fsl_sdmmc_card.h"
+
+#if defined(FSL_SDHC_USING_BIG_ENDIAN)
+#define swap_be32(x) (x)
+#else
+#define swap_be32(x) (__REV(x))
+#endif
+
+#define FSL_SDCARD_REQUEST_TIMEOUT 1000
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_DelayMsec
+ * Description: blocking delay msecond
+ *
+ *END*********************************************************************/
+static void SDCARD_DRV_DelayMsec(uint32_t msec)
+{
+ uint32_t startTime, elapsedTime;
+ assert(msec);
+
+ startTime = OSA_TimeGetMsec();
+ do
+ {
+ elapsedTime = OSA_TimeGetMsec() - startTime;
+ } while(elapsedTime < msec);
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_DecodeCsd
+ * Description: decode csd register
+ *
+ *END*********************************************************************/
+static void SDCARD_DRV_DecodeCsd(uint32_t *rawCsd, sdhc_card_t *card)
+{
+ sdcard_csd_t *csd;
+ assert(rawCsd);
+ assert(card);
+ csd = &(card->csd);
+ csd->csdStructure = (uint8_t)((rawCsd[3] & 0xC0000000U) >> 30);
+ csd->taac = (uint8_t)((rawCsd[3] & 0xFF0000) >> 16);
+ csd->nsac = (uint8_t)((rawCsd[3] & 0xFF00) >> 8);
+ csd->tranSpeed = (uint8_t)(rawCsd[3] & 0xFF);
+ csd->ccc = (uint16_t)((rawCsd[2] & 0xFFF00000U) >> 20);
+ csd->readBlkLen = (uint8_t)((rawCsd[2] & 0xF0000) >> 16);
+ if (rawCsd[2] & 0x8000)
+ {
+ csd->flags |= SDCARD_CSD_READ_BL_PARTIAL;
+ }
+ if (rawCsd[2] & 0x4000)
+ {
+ csd->flags |= SDCARD_CSD_WRITE_BLK_MISALIGN;
+ }
+ if (rawCsd[2] & 0x2000)
+ {
+ csd->flags |= SDCARD_CSD_READ_BLK_MISALIGN;
+ }
+ if (rawCsd[2] & 0x1000)
+ {
+ csd->flags |= SDCARD_CSD_DSR_IMP;
+ }
+ if (csd->csdStructure == 0)
+ {
+ csd->cSize = (uint32_t)((rawCsd[2] & 0x3FF) << 2);
+ csd->cSize |= (uint32_t)((rawCsd[1] & 0xC0000000U) >> 30);
+ csd->vddRCurrMin = (uint8_t)((rawCsd[1] & 0x38000000) >> 27);
+ csd->vddRCurrMax = (uint8_t)((rawCsd[1] & 0x7000000) >> 24);
+ csd->vddWCurrMin = (uint8_t)((rawCsd[1] & 0xE00000) >> 20);
+ csd->vddWCurrMax = (uint8_t)((rawCsd[1] & 0x1C0000) >> 18);
+ csd->cSizeMult = (uint8_t)((rawCsd[1] & 0x38000) >> 15);
+ card->blockCount = (csd->cSize + 1) << (csd->cSizeMult + 2);
+ card->blockSize = CARD_BLOCK_LEN(csd->readBlkLen);
+ if (card->blockSize != FSL_SDHC_CARD_DEFAULT_BLOCK_SIZE)
+ {
+ card->blockCount = card->blockCount * card->blockSize;
+ card->blockSize = FSL_SDHC_CARD_DEFAULT_BLOCK_SIZE;
+ card->blockCount = card->blockCount / card->blockSize;
+ }
+ }
+ else if (csd->csdStructure == 1)
+ {
+ card->blockSize = FSL_SDHC_CARD_DEFAULT_BLOCK_SIZE;
+ csd->cSize = (uint32_t)((rawCsd[2] & 0x3F) << 16);
+ csd->cSize |= (uint32_t)((rawCsd[1] & 0xFFFF0000U) >> 16);
+ if (csd->cSize >= 0xFFFF)
+ {
+ card->caps |= SDMMC_CARD_CAPS_SDXC;
+ }
+ card->blockCount = (csd->cSize + 1) * 1024;
+ }
+
+ if ((uint8_t)((rawCsd[1] & 0x4000) >> 14))
+ {
+ csd->flags |= SDCARD_CSD_ERASE_BLK_ENABLED;
+ }
+
+ csd->sectorSize = (uint8_t)((rawCsd[1] & 0x3F80) >> 7);
+ csd->wpGrpSize = (uint8_t)(rawCsd[1] & 0x7F);
+ if ((uint8_t)(rawCsd[0] & 0x80000000U))
+ {
+ csd->flags |= SDCARD_CSD_WP_GRP_ENABLED;
+ }
+ csd->r2wFactor = (uint8_t)((rawCsd[0] & 0x1C000000) >> 26);
+ csd->writeBlkLen = (uint8_t)((rawCsd[0] & 0x3C00000) >> 22);
+ if ((uint8_t)((rawCsd[0] & 0x200000) >> 21))
+ {
+ csd->flags |= SDCARD_CSD_WRITE_BL_PARTIAL;
+ }
+ if ((uint8_t)((rawCsd[0] & 0x8000) >> 15))
+ {
+ csd->flags |= SDCARD_CSD_FILE_FORMAT_GROUP;
+ }
+ if ((uint8_t)((rawCsd[0] & 0x4000) >> 14))
+ {
+ csd->flags |= SDCARD_CSD_COPY;
+ }
+ if ((uint8_t)((rawCsd[0] & 0x2000) >> 13))
+ {
+ csd->flags |= SDCARD_CSD_PERM_WRITE_PROTECT;
+ }
+ if ((uint8_t)((rawCsd[0] & 0x1000) >> 12))
+ {
+ csd->flags |= SDCARD_CSD_TMP_WRITE_PROTECT;
+ }
+ csd->fileFormat = (uint8_t)((rawCsd[0] & 0xC00) >> 10);
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_DecodeCid
+ * Description: decode cid register
+ *
+ *END*********************************************************************/
+static void SDCARD_DRV_DecodeCid(uint32_t *rawCid, sdhc_card_t *card)
+{
+ sdcard_cid_t *cid;
+ assert(rawCid);
+ assert(card);
+ cid = &(card->cid);
+
+ cid->mid = (uint8_t)((rawCid[3] & 0xFF000000) >> 24);
+
+ cid->oid = (uint16_t)((rawCid[3] & 0xFFFF00) >> 8);
+
+ cid->pnm[0] = (uint8_t)((rawCid[3] & 0xFF));
+ cid->pnm[1] = (uint8_t)((rawCid[2] & 0xFF000000U) >> 24);
+ cid->pnm[2] = (uint8_t)((rawCid[2] & 0xFF0000) >> 16);
+ cid->pnm[3] = (uint8_t)((rawCid[2] & 0xFF00) >> 8);
+ cid->pnm[4] = (uint8_t)((rawCid[2] & 0xFF));
+
+ cid->prv = (uint8_t)((rawCid[1] & 0xFF000000U) >> 24);
+
+ cid->psn = (uint32_t)((rawCid[1] & 0xFFFFFF) << 8);
+ cid->psn |= (uint32_t)((rawCid[0] & 0xFF000000U) >> 24);
+
+ cid->mdt = (uint16_t)((rawCid[0] & 0xFFF00) >> 8);
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_SendApplicationCmd
+ * Description: send application command to card
+ *
+ *END*********************************************************************/
+static sdhc_status_t SDCARD_DRV_SendApplicationCmd(sdhc_card_t *card)
+{
+ sdhc_request_t *req = 0;
+ sdhc_status_t ret = kStatus_SDHC_NoError;
+#if ! defined BSP_FSL_SDHC_USING_DYNALLOC
+ sdhc_request_t request = {0};
+ req = &request;
+#endif
+ assert(card);
+
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ req = (sdhc_request_t *)OSA_MemAllocZero(sizeof(sdhc_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDHC_OutOfMemory;
+ }
+#endif
+ req->cmdIndex = kAppCmd;
+ req->argument = 0;
+ if (card->cardType != kCardTypeUnknown)
+ {
+ req->argument = card->rca << 16;
+ }
+ req->respType = kSdhcRespTypeR1;
+
+ if (kStatus_SDHC_NoError !=
+ SDHC_DRV_IssueRequestBlocking(card->hostInstance,
+ req,
+ FSL_SDCARD_REQUEST_TIMEOUT))
+ {
+ if (req->error & FSL_SDHC_REQ_ERR_CMD_TIMEOUT)
+ {
+ ret = kStatus_SDHC_TimeoutError;
+ }
+ else
+ {
+ ret = kStatus_SDHC_RequestFailed;
+ }
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return ret;
+ }
+
+ if (!(req->response[0] & SDMMC_R1_APP_CMD))
+ {
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_CardNotSupport;
+ }
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_NoError;
+}
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_AllSendCid
+ * Description: send all_send_cid command
+ *
+ *END*********************************************************************/
+static sdhc_status_t SDCARD_DRV_AllSendCid(sdhc_card_t *card)
+{
+ sdhc_request_t *req = 0;
+#if ! defined BSP_FSL_SDHC_USING_DYNALLOC
+ sdhc_request_t request = {0};
+ req = &request;
+#endif
+ assert(card);
+
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ req = (sdhc_request_t *)OSA_MemAllocZero(sizeof(sdhc_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDHC_OutOfMemory;
+ }
+#endif
+ req->cmdIndex = kAllSendCid;
+ req->argument = 0;
+ req->respType = kSdhcRespTypeR2;
+ if (kStatus_SDHC_NoError ==
+ SDHC_DRV_IssueRequestBlocking(card->hostInstance,
+ req,
+ FSL_SDCARD_REQUEST_TIMEOUT))
+ {
+ memcpy(card->rawCid, req->response, sizeof(card->rawCid));
+ SDCARD_DRV_DecodeCid(req->response, card);
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_NoError;
+ }
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_RequestFailed;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_SendRca
+ * Description: send rca command to card to get relative card address
+ *
+ *END*********************************************************************/
+static sdhc_status_t SDCARD_DRV_SendRca(sdhc_card_t *card)
+{
+ sdhc_request_t *req = 0;
+#if ! defined BSP_FSL_SDHC_USING_DYNALLOC
+ sdhc_request_t request = {0};
+ req = &request;
+#endif
+ assert(card);
+
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ req = (sdhc_request_t *)OSA_MemAllocZero(sizeof(sdhc_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDHC_OutOfMemory;
+ }
+#endif
+ req->cmdIndex = kSdSendRelativeAddr;
+ req->argument = 0;
+ req->respType = kSdhcRespTypeR6;
+ if (kStatus_SDHC_NoError ==
+ SDHC_DRV_IssueRequestBlocking(card->hostInstance,
+ req,
+ FSL_SDCARD_REQUEST_TIMEOUT))
+ {
+ card->rca = req->response[0] >> 16;
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_NoError;
+ }
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_RequestFailed;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_SendCsd
+ * Description: get csd from card
+ *
+ *END*********************************************************************/
+static sdhc_status_t SDCARD_DRV_SendCsd(sdhc_card_t *card)
+{
+ sdhc_request_t *req = 0;
+#if ! defined BSP_FSL_SDHC_USING_DYNALLOC
+ sdhc_request_t request = {0};
+ req = &request;
+#endif
+ assert(card);
+
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ req = (sdhc_request_t *)OSA_MemAllocZero(sizeof(sdhc_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDHC_OutOfMemory;
+ }
+#endif
+ req->cmdIndex = kSendCsd;
+ req->argument = card->rca << 16;
+ req->respType = kSdhcRespTypeR2;
+ if (kStatus_SDHC_NoError ==
+ SDHC_DRV_IssueRequestBlocking(card->hostInstance,
+ req,
+ FSL_SDCARD_REQUEST_TIMEOUT))
+ {
+ memcpy(card->rawCsd, req->response, sizeof(card->rawCsd));
+ SDCARD_DRV_DecodeCsd(req->response, card);
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_NoError;
+ }
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_RequestFailed;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_SelectCard
+ * Description: select or deselect card
+ *
+ *END*********************************************************************/
+static sdhc_status_t SDCARD_DRV_SelectCard(sdhc_card_t *card, bool isSelected)
+{
+ sdhc_request_t *req = 0;
+#if ! defined BSP_FSL_SDHC_USING_DYNALLOC
+ sdhc_request_t request = {0};
+ req = &request;
+#endif
+ assert(card);
+
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ req = (sdhc_request_t *)OSA_MemAllocZero(sizeof(sdhc_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDHC_OutOfMemory;
+ }
+#endif
+ req->cmdIndex = kSelectCard;
+ if (isSelected)
+ {
+ req->argument = card->rca << 16;
+ req->respType = kSdhcRespTypeR1;
+ }
+ else
+ {
+ req->argument = 0;
+ req->respType = kSdhcRespTypeNone;
+ }
+ if (kStatus_SDHC_NoError !=
+ SDHC_DRV_IssueRequestBlocking(card->hostInstance,
+ req,
+ FSL_SDCARD_REQUEST_TIMEOUT))
+ {
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_RequestFailed;
+ }
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_NoError;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_SetBlockSize
+ * Description: Set the block length in bytes for SDSC cards. For SDHC cards,
+ * it does not affect memory read or write commands, always 512 bytes fixed
+ * block length is used.
+ *
+ *END*********************************************************************/
+static sdhc_status_t SDCARD_DRV_SetBlockSize(sdhc_card_t *card, uint32_t blockSize)
+{
+ sdhc_request_t *req = 0;
+#if ! defined BSP_FSL_SDHC_USING_DYNALLOC
+ sdhc_request_t request = {0};
+ req = &request;
+#endif
+ assert(card);
+
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ req = (sdhc_request_t *)OSA_MemAllocZero(sizeof(sdhc_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDHC_OutOfMemory;
+ }
+#endif
+ req->cmdIndex = kSetBlockLen;
+ req->argument = blockSize;
+ req->respType = kSdhcRespTypeR1;
+
+ if (kStatus_SDHC_NoError !=
+ SDHC_DRV_IssueRequestBlocking(card->hostInstance,
+ req,
+ FSL_SDCARD_REQUEST_TIMEOUT))
+ {
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_RequestFailed;
+ }
+
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_NoError;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_Switch
+ * Description: send switch command to card
+ *
+ *END*********************************************************************/
+static sdhc_status_t SDCARD_DRV_Switch(sdhc_card_t *card,
+ uint32_t mode,
+ uint32_t group,
+ uint32_t value,
+ uint32_t *resp)
+{
+ sdhc_request_t *req = 0;
+ sdhc_data_t data = {0};
+#if ! defined BSP_FSL_SDHC_USING_DYNALLOC
+ sdhc_request_t request = {0};
+ req = &request;
+#endif
+ assert(card);
+
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ req = (sdhc_request_t *)OSA_MemAllocZero(sizeof(sdhc_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDHC_OutOfMemory;
+ }
+#endif
+ req->data = &data;
+
+ req->cmdIndex = kSdSwitch;
+ req->argument = mode << 31 | 0x00FFFFFF;
+ req->argument &= ~((uint32_t)(0xF) << (group * 4));
+ req->argument |= value << (group * 4);
+ req->flags = FSL_SDHC_REQ_FLAGS_DATA_READ;
+ req->respType = kSdhcRespTypeR1;
+
+
+ data.blockSize = 64;
+ data.blockCount = 1;
+ data.buffer = resp;
+ data.req = req;
+
+ if (kStatus_SDHC_NoError != SDCARD_DRV_SetBlockSize(card, data.blockSize))
+ {
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_SetCardBlockSizeFailed;
+ }
+
+ if (kStatus_SDHC_NoError !=
+ SDHC_DRV_IssueRequestBlocking(card->hostInstance,
+ req,
+ FSL_SDCARD_REQUEST_TIMEOUT))
+ {
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_RequestFailed;
+ }
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_NoError;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_DecodeScr
+ * Description: decode scr register
+ *
+ *END*********************************************************************/
+static void SDCARD_DRV_DecodeScr(uint32_t *rawScr, sdhc_card_t *card)
+{
+ sdcard_scr_t *scr;
+ assert(rawScr);
+ assert(card);
+
+ scr = &(card->scr);
+ scr->scrStructure = (uint8_t)((rawScr[0] & 0xF0000000U) >> 28);
+ scr->sdSpec = (uint8_t)((rawScr[0] & 0xF000000) >> 24);
+ if ((uint8_t)((rawScr[0] & 0x800000) >> 23))
+ {
+ scr->flags |= SDCARD_SCR_DATA_STAT_AFTER_ERASE;
+ }
+ scr->sdSecurity = (uint8_t)((rawScr[0] & 0x700000) >> 20);
+ scr->sdBusWidths = (uint8_t)((rawScr[0] & 0xF0000) >> 16);
+ if ((uint8_t)((rawScr[0] & 0x8000) >> 15))
+ {
+ scr->flags |= SDCARD_SCR_SD_SPEC3;
+ }
+ scr->exSecurity = (uint8_t)((rawScr[0] & 0x7800) >> 10);
+ scr->cmdSupport = (uint8_t)(rawScr[0] & 0x3);
+ scr->reservedForMan = rawScr[1];
+
+ switch(scr->sdSpec)
+ {
+ case 0:
+ card->version = SDMMC_SD_VERSION_1_0;
+ break;
+ case 1:
+ card->version = SDMMC_SD_VERSION_1_1;
+ break;
+ case 2:
+ card->version = SDMMC_SD_VERSION_2_0;
+ if (card->scr.flags & SDCARD_SCR_SD_SPEC3)
+ {
+ card->version = SDMMC_SD_VERSION_3_0;
+ }
+ break;
+ default:
+ break;
+ }
+ if (card->scr.sdBusWidths & SD_SCR_BUS_WIDTHS_4BIT)
+ {
+ card->caps |= SDMMC_CARD_CAPS_BUSWIDTH_4BITS;
+ }
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_SendScr
+ * Description: fetch scr register from card
+ *
+ *END*********************************************************************/
+static sdhc_status_t SDCARD_DRV_SendScr(sdhc_card_t *card)
+{
+ sdhc_request_t *req = 0;
+ sdhc_data_t data = {0};
+ sdhc_status_t err = kStatus_SDHC_NoError;
+ uint32_t rawScr[2] = {0};
+#if ! defined BSP_FSL_SDHC_USING_DYNALLOC
+ sdhc_request_t request = {0};
+ req = &request;
+#endif
+ assert(card);
+
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ req = (sdhc_request_t *)OSA_MemAllocZero(sizeof(sdhc_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDHC_OutOfMemory;
+ }
+#endif
+ err = SDCARD_DRV_SendApplicationCmd(card);
+ if (err)
+ {
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return err;
+ }
+
+ req->data = &data;
+ req->cmdIndex = kSdAppSendScr;
+ req->flags = FSL_SDHC_REQ_FLAGS_DATA_READ;
+ req->respType = kSdhcRespTypeR1;
+ req->argument = 0;
+
+ data.blockSize = 8;
+ data.blockCount = 1;
+ data.buffer = rawScr;
+ data.req = req;
+
+ if (kStatus_SDHC_NoError !=
+ SDHC_DRV_IssueRequestBlocking(card->hostInstance,
+ req,
+ FSL_SDCARD_REQUEST_TIMEOUT))
+ {
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_RequestFailed;
+ }
+ rawScr[0] = swap_be32(rawScr[0]);
+ rawScr[1] = swap_be32(rawScr[1]);
+ memcpy(card->rawScr, rawScr, sizeof(card->rawScr));
+ SDCARD_DRV_DecodeScr(rawScr, card);
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_NoError;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_SwitchHighspeed
+ * Description: switch high speed mode of the specific card
+ *
+ *END*********************************************************************/
+static sdhc_status_t SDCARD_DRV_SwitchHighspeed(sdhc_card_t *card)
+{
+ uint32_t response[16] = {0};
+ sdhc_status_t err = kStatus_SDHC_NoError;
+ assert(card);
+
+ if ((card->version < SDMMC_SD_VERSION_1_1)
+ || (!(card->csd.ccc & SD_CCC_SWITCH)))
+ {
+ return kStatus_SDHC_CardNotSupport;
+ }
+
+ err = SDCARD_DRV_Switch(card, kSdSwitchCheck, 0, 1, response);
+ if (err)
+ {
+ return err;
+ }
+
+ if ((!(swap_be32(response[3]) & 0x10000)) ||
+ ((swap_be32(response[4]) & 0x0f000000) == 0x0F000000))
+ {
+ return kStatus_SDHC_CardNotSupport;
+ }
+
+ err = SDCARD_DRV_Switch(card, kSdSwitchSet, 0, 1, response);
+ if (err)
+ {
+ return err;
+ }
+
+ if ((swap_be32(response[4]) & 0x0f000000) != 0x01000000)
+ {
+ err = kStatus_SDHC_SwitchFailed;
+ }
+
+ return err;
+
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_SetBusWidth
+ * Description: set desired buswidth
+ *
+ *END*********************************************************************/
+static uint32_t SDCARD_DRV_SetBusWidth(sdhc_card_t *card,
+ sd_buswidth_t busWidth)
+{
+ sdhc_request_t *req = 0;
+ sdhc_status_t err = kStatus_SDHC_NoError;
+#if ! defined BSP_FSL_SDHC_USING_DYNALLOC
+ sdhc_request_t request = {0};
+ req = &request;
+#endif
+ assert(card);
+
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ req = (sdhc_request_t *)OSA_MemAllocZero(sizeof(sdhc_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDHC_OutOfMemory;
+ }
+#endif
+ err = SDCARD_DRV_SendApplicationCmd(card);
+ if (err != kStatus_SDHC_NoError)
+ {
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return err;
+ }
+
+ req->cmdIndex = kSdAppSetBusWdith;
+ req->respType = kSdhcRespTypeR1;
+ req->argument = busWidth;
+
+ if (kStatus_SDHC_NoError !=
+ SDHC_DRV_IssueRequestBlocking(card->hostInstance,
+ req,
+ FSL_SDCARD_REQUEST_TIMEOUT))
+ {
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_RequestFailed;
+ }
+
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return err;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_InitSd
+ * Description: initialize SD memory card
+ *
+ *END*********************************************************************/
+static sdhc_status_t SDCARD_DRV_InitSd(sdhc_card_t *card)
+{
+ assert(card);
+ sdhc_status_t err = kStatus_SDHC_NoError;
+ card->cardType = kCardTypeSd;
+
+ if (kStatus_SDHC_NoError != SDCARD_DRV_AllSendCid(card))
+ {
+ return kStatus_SDHC_AllSendCidFailed;
+ }
+
+ if (kStatus_SDHC_NoError != SDCARD_DRV_SendRca(card))
+ {
+ return kStatus_SDHC_SendRcaFailed;
+ }
+
+ if (kStatus_SDHC_NoError != SDCARD_DRV_SendCsd(card))
+ {
+ return kStatus_SDHC_SendCsdFailed;
+ }
+
+ if (kStatus_SDHC_NoError != SDCARD_DRV_SelectCard(card, true))
+ {
+ return kStatus_SDHC_SelectCardFailed;
+ }
+
+ if (kStatus_SDHC_NoError != SDCARD_DRV_SendScr(card))
+ {
+ return kStatus_SDHC_SendScrFailed;
+ }
+
+ if (kStatus_SDHC_NoError !=
+ SDHC_DRV_ConfigClock(card->hostInstance, SDMMC_CLK_25MHZ))
+ {
+ return kStatus_SDHC_SetClockFailed;
+ }
+
+ if (DOES_HOST_SUPPORT_4BITS(card->host) && DOES_CARD_SUPPORT_4BITS(card))
+ {
+ if (kStatus_SDHC_NoError != SDCARD_DRV_SetBusWidth(card, kSdBusWidth4Bit))
+ {
+ return kStatus_SDHC_SetCardWideBusFailed;
+ }
+ if (kStatus_SDHC_NoError !=
+ SDHC_DRV_SetBusWidth(card->hostInstance, kSdhcBusWidth4Bit))
+ {
+ return kStatus_SDHC_SetBusWidthFailed;
+ }
+ }
+
+ if (DOES_HOST_SUPPORT_HIGHSPEED(card->host))
+ {
+ err = SDCARD_DRV_SwitchHighspeed(card);
+ if ((err != kStatus_SDHC_NoError) && (kStatus_SDHC_CardNotSupport != err))
+ {
+ return kStatus_SDHC_SwitchHighSpeedFailed;
+ }
+ else if (err == kStatus_SDHC_NoError)
+ {
+ if (kStatus_SDHC_NoError !=
+ SDHC_DRV_ConfigClock(card->hostInstance, SDMMC_CLK_50MHZ))
+ {
+ return kStatus_SDHC_SetClockFailed;
+ }
+ }
+ else
+ {
+ err = kStatus_SDHC_NoError;
+ }
+ }
+
+ if (SDCARD_DRV_SetBlockSize(card, FSL_SDHC_CARD_DEFAULT_BLOCK_SIZE))
+ {
+ err = kStatus_SDHC_SetCardBlockSizeFailed;
+ }
+ return err;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_AppSendOpCond
+ * Description: Send host capacity support information and asks the accessed
+ * card to send its operating condition register content.
+ *
+ *END*********************************************************************/
+static sdhc_status_t SDCARD_DRV_AppSendOpCond(sdhc_card_t *card,
+ uint32_t acmd41Arg)
+{
+ sdhc_request_t *req = 0;
+ sdhc_status_t err;
+ uint32_t i = FSL_SDHC_CARD_MAX_VOLT_RETRIES;
+#if ! defined BSP_FSL_SDHC_USING_DYNALLOC
+ sdhc_request_t request = {0};
+ req = &request;
+#endif
+ assert(card);
+
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ req = (sdhc_request_t *)OSA_MemAllocZero(sizeof(sdhc_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDHC_OutOfMemory;
+ }
+#endif
+ req->cmdIndex = kSdAppSendOpCond;
+ req->argument = acmd41Arg;
+ req->respType = kSdhcRespTypeR3;
+
+ while (i--)
+ {
+ err = SDCARD_DRV_SendApplicationCmd(card);
+ if (err != kStatus_SDHC_NoError)
+ {
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return err;
+ }
+
+ if (kStatus_SDHC_NoError !=
+ SDHC_DRV_IssueRequestBlocking(card->hostInstance,
+ req,
+ FSL_SDCARD_REQUEST_TIMEOUT))
+ {
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return err;
+ }
+
+ if (req->response[0] & SDMMC_CARD_BUSY)
+ {
+ if (req->response[0] & SD_OCR_CCS)
+ {
+ card->caps |= SDMMC_CARD_CAPS_HIGHCAPACITY;
+ }
+ err = kStatus_SDHC_NoError;
+ card->ocr = req->response[0];
+ break;
+ }
+ err = kStatus_SDHC_TimeoutError;
+
+ SDCARD_DRV_DelayMsec(1);
+ }
+
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return err;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_GoIdle
+ * Description: reset all cards to idle state
+ *
+ *END*********************************************************************/
+static sdhc_status_t SDCARD_DRV_GoIdle(sdhc_card_t *card)
+{
+ sdhc_request_t *req = 0;
+ sdhc_status_t err;
+#if ! defined BSP_FSL_SDHC_USING_DYNALLOC
+ sdhc_request_t request = {0};
+ req = &request;
+#endif
+ assert(card);
+
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ req = (sdhc_request_t *)OSA_MemAllocZero(sizeof(sdhc_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDHC_OutOfMemory;
+ }
+#endif
+ req->cmdIndex = kGoIdleState;
+ err = SDHC_DRV_IssueRequestBlocking(card->hostInstance,
+ req,
+ FSL_SDCARD_REQUEST_TIMEOUT);
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return err;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_CheckReadOnly
+ * Description: Check if the card is ready only
+ *
+ *END*********************************************************************/
+bool SDCARD_DRV_CheckReadOnly(sdhc_card_t *card)
+{
+ assert(card);
+
+ return ((card->csd.flags & SDCARD_CSD_PERM_WRITE_PROTECT) ||
+ (card->csd.flags & SDCARD_CSD_TMP_WRITE_PROTECT));
+}
+
+
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_SendIfCond
+ * Description: check card interface condition, which includes host supply
+ * voltage information and asks the card whether card supports voltage.
+ *
+ *END*********************************************************************/
+static sdhc_status_t SDCARD_DRV_SendIfCond(sdhc_card_t *card)
+{
+ sdhc_request_t *req = 0;
+ sdhc_status_t err = kStatus_SDHC_NoError;
+#if ! defined BSP_FSL_SDHC_USING_DYNALLOC
+ sdhc_request_t request = {0};
+ req = &request;
+#endif
+ assert(card);
+
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ req = (sdhc_request_t *)OSA_MemAllocZero(sizeof(sdhc_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDHC_OutOfMemory;
+ }
+#endif
+ req->cmdIndex = kSdSendIfCond;
+ req->argument = 0x1AA;
+ req->respType = kSdhcRespTypeR7;
+ if (kStatus_SDHC_NoError !=
+ SDHC_DRV_IssueRequestBlocking(card->hostInstance,
+ req,
+ FSL_SDCARD_REQUEST_TIMEOUT))
+ {
+ err = kStatus_SDHC_RequestFailed;
+ }
+ else if ((req->response[0] & 0xFF) != 0xAA)
+ {
+ err = kStatus_SDHC_CardNotSupport;
+ }
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return err;
+}
+
+#if ! defined BSP_FSL_SDHC_ENABLE_AUTOCMD12
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_StopTransmission
+ * Description: Send stop transmission command to card to stop ongoing
+ * data transferring.
+ *
+ *END*********************************************************************/
+static sdhc_status_t SDCARD_DRV_StopTransmission(sdhc_card_t *card)
+{
+ sdhc_request_t *req = 0;
+ sdhc_status_t err = kStatus_SDHC_NoError;
+#if ! defined BSP_FSL_SDHC_USING_DYNALLOC
+ sdhc_request_t request = {0};
+ req = &request;
+#endif
+ assert(card);
+
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ req = (sdhc_request_t *)OSA_MemAllocZero(sizeof(sdhc_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDHC_OutOfMemory;
+ }
+#endif
+
+ req->cmdIndex = kStopTransmission;
+ req->flags |= FSL_SDHC_REQ_FLAGS_STOP_TRANS;
+ req->argument = 0;
+ req->respType = kSdhcRespTypeR1b;
+ req->data = 0;
+ if (kStatus_SDHC_NoError !=
+ SDHC_DRV_IssueRequestBlocking(card->hostInstance,
+ req,
+ FSL_SDCARD_REQUEST_TIMEOUT))
+ {
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_RequestFailed;
+ }
+
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return err;
+}
+#endif
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_Read
+ * Description: read data from specific card
+ *
+ *END*********************************************************************/
+static sdhc_status_t SDCARD_DRV_Read(sdhc_card_t *card,
+ uint8_t *buffer,
+ uint32_t startBlock,
+ uint32_t blockSize,
+ uint32_t blockCount)
+{
+ sdhc_request_t *req = 0;
+ sdhc_data_t data = {0};
+#if ! defined BSP_FSL_SDHC_USING_DYNALLOC
+ sdhc_request_t request = {0};
+ req = &request;
+#endif
+
+ assert(card);
+ assert(buffer);
+ assert(blockCount);
+ assert(blockSize);
+ assert(blockSize == FSL_SDHC_CARD_DEFAULT_BLOCK_SIZE);
+
+ if ((IS_HIGHCAPACITY_CARD(card) && (blockSize != 512))
+ || (blockSize > card->blockSize)
+ || (blockSize > card->host->maxBlockSize)
+ || (blockSize % 4))
+ {
+ return kStatus_SDHC_BlockSizeNotSupportError;
+ }
+
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ req = (sdhc_request_t *)OSA_MemAllocZero(sizeof(sdhc_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDHC_OutOfMemory;
+ }
+#endif
+
+ data.blockSize = blockSize;
+ data.blockCount = blockCount;
+ data.buffer = (uint32_t *)buffer;
+
+ req->data = &data;
+ req->cmdIndex = kReadMultipleBlock;
+ if (data.blockCount == 1)
+ {
+ req->cmdIndex = kReadSingleBlock;
+ }
+
+ req->argument = startBlock;
+ if (!IS_HIGHCAPACITY_CARD(card))
+ {
+ req->argument *= data.blockSize;
+ }
+ req->flags = FSL_SDHC_REQ_FLAGS_DATA_READ;
+ req->respType = kSdhcRespTypeR1;
+
+ data.req = req;
+ if (kStatus_SDHC_NoError !=
+ SDHC_DRV_IssueRequestBlocking(card->hostInstance,
+ req,
+ FSL_SDCARD_REQUEST_TIMEOUT))
+ {
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_RequestFailed;
+ }
+
+#if ! defined BSP_FSL_SDHC_ENABLE_AUTOCMD12
+ if (data.blockCount > 1)
+ {
+ if (kStatus_SDHC_NoError != SDCARD_DRV_StopTransmission(card))
+ {
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_StopTransmissionFailed;
+ }
+ }
+#endif
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_NoError;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_Write
+ * Description: write data from specific card
+ *
+ *END*********************************************************************/
+static sdhc_status_t SDCARD_DRV_Write(sdhc_card_t *card,
+ uint8_t *buffer,
+ uint32_t startBlock,
+ uint32_t blockSize,
+ uint32_t blockCount)
+{
+ sdhc_request_t *req = 0;
+ sdhc_data_t data = {0};
+#if ! defined BSP_FSL_SDHC_USING_DYNALLOC
+ sdhc_request_t request = {0};
+ req = &request;
+#endif
+ assert(card);
+ assert(buffer);
+ assert(blockCount);
+ assert(blockSize);
+ assert(blockSize == FSL_SDHC_CARD_DEFAULT_BLOCK_SIZE);
+
+ if ((IS_HIGHCAPACITY_CARD(card) && (blockSize != 512))
+ || (blockSize > card->blockSize)
+ || (blockSize > card->host->maxBlockSize)
+ || (blockSize % 4))
+ {
+ return kStatus_SDHC_BlockSizeNotSupportError;
+ }
+
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ req = (sdhc_request_t *)OSA_MemAllocZero(sizeof(sdhc_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDHC_OutOfMemory;
+ }
+#endif
+
+ data.blockSize = blockSize;
+ data.blockCount = blockCount;
+ data.buffer = (uint32_t *)buffer;
+
+ req->data = &data;
+ req->cmdIndex = kWriteMultipleBlock;
+ if (data.blockCount == 1)
+ {
+ req->cmdIndex = kWriteBlock;
+ }
+
+ req->argument = startBlock;
+ if (!IS_HIGHCAPACITY_CARD(card))
+ {
+ req->argument *= data.blockSize;
+ }
+ req->respType = kSdhcRespTypeR1;
+ data.req = req;
+ if (kStatus_SDHC_NoError !=
+ SDHC_DRV_IssueRequestBlocking(card->hostInstance,
+ req,
+ FSL_SDCARD_REQUEST_TIMEOUT))
+ {
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_RequestFailed;
+ }
+
+ if (data.blockCount > 1)
+ {
+#if ! defined BSP_FSL_SDHC_ENABLE_AUTOCMD12
+ if (kStatus_SDHC_NoError != SDCARD_DRV_StopTransmission(card))
+ {
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_StopTransmissionFailed;
+ }
+#endif
+ }
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_NoError;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_Erase
+ * Description: erase data for the given block range
+ *
+ *END*********************************************************************/
+static sdhc_status_t SDCARD_DRV_Erase(sdhc_card_t *card,
+ uint32_t startBlock,
+ uint32_t blockCount)
+{
+ uint32_t s, e;
+ sdhc_request_t *req = 0;
+#if ! defined BSP_FSL_SDHC_USING_DYNALLOC
+ sdhc_request_t request = {0};
+ req = &request;
+#endif
+ assert(card);
+ assert(blockCount);
+
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ req = (sdhc_request_t *)OSA_MemAllocZero(sizeof(sdhc_request_t));
+ if (req == NULL)
+ {
+ return kStatus_SDHC_OutOfMemory;
+ }
+#endif
+ s = startBlock;
+ e = s + blockCount - 1;
+ if (!IS_HIGHCAPACITY_CARD(card))
+ {
+ s = s * FSL_SDHC_CARD_DEFAULT_BLOCK_SIZE;
+ e = e * FSL_SDHC_CARD_DEFAULT_BLOCK_SIZE;
+ }
+
+ req->cmdIndex = kSdEraseWrBlkStart;
+ req->argument = s;
+ req->respType = kSdhcRespTypeR1;
+ if (kStatus_SDHC_NoError !=
+ SDHC_DRV_IssueRequestBlocking(card->hostInstance,
+ req,
+ FSL_SDCARD_REQUEST_TIMEOUT))
+ {
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_RequestFailed;
+ }
+ req->cmdIndex = kSdEraseWrBlkEnd;
+ req->argument = e;
+ if (kStatus_SDHC_NoError !=
+ SDHC_DRV_IssueRequestBlocking(card->hostInstance,
+ req,
+ FSL_SDCARD_REQUEST_TIMEOUT))
+ {
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_RequestFailed;
+ }
+ req->cmdIndex = kErase;
+ req->argument = 0;
+ req->respType = kSdhcRespTypeR1b;
+ if (kStatus_SDHC_NoError !=
+ SDHC_DRV_IssueRequestBlocking(card->hostInstance,
+ req,
+ FSL_SDCARD_REQUEST_TIMEOUT))
+ {
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_RequestFailed;
+ }
+
+#if defined BSP_FSL_SDHC_USING_DYNALLOC
+ OSA_MemFree(req);
+#endif
+ req = NULL;
+ return kStatus_SDHC_NoError;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_Shutdown
+ * Description: destory initialized card and shutdown the corresponding
+ * host controller
+ *
+ *END*********************************************************************/
+void SDCARD_DRV_Shutdown(sdhc_card_t *card)
+{
+ assert(card);
+ SDCARD_DRV_SelectCard(card, false);
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_Init
+ * Description: initialize card on the given host controller
+ *
+ *END*********************************************************************/
+sdhc_status_t SDCARD_DRV_Init(sdhc_host_t *host, sdhc_card_t *card)
+{
+ sdhc_status_t err = kStatus_SDHC_NoError;
+ uint32_t acmd41Arg;
+ assert(card);
+ assert(host);
+
+ card->cardType = kCardTypeUnknown;
+ card->host = host;
+ card->hostInstance = host->instance;
+
+ if (SDHC_DRV_ConfigClock(card->hostInstance, SDMMC_CLK_400KHZ))
+ {
+ return kStatus_SDHC_SetClockFailed;
+ }
+
+ err = SDCARD_DRV_GoIdle(card);
+ if (err)
+ {
+ return kStatus_SDHC_SetCardToIdle;
+ }
+ acmd41Arg = card->host->ocrSupported;
+
+ err = SDCARD_DRV_SendIfCond(card);
+ if (err == kStatus_SDHC_NoError)
+ {
+ /* SDHC or SDXC card */
+ acmd41Arg |= SD_OCR_HCS;
+ card->caps |= SDMMC_CARD_CAPS_SDHC;
+ }
+ else
+ {
+ /* SDSC card */
+ err = SDCARD_DRV_GoIdle(card);
+ if (err)
+ {
+ return kStatus_SDHC_SetCardToIdle;
+ }
+ }
+
+ err = SDCARD_DRV_AppSendOpCond(card, acmd41Arg);
+ if (kStatus_SDHC_TimeoutError == err)
+ {
+ /* MMC card */
+ return kStatus_SDHC_NotSupportYet;
+ }
+ else if (err)
+ {
+ return kStatus_SDHC_SendAppOpCondFailed;
+ }
+
+ return SDCARD_DRV_InitSd(card);
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_WriteBlocks
+ * Description: write blocks to card with default block size
+ *
+ *END*********************************************************************/
+sdhc_status_t SDCARD_DRV_WriteBlocks(sdhc_card_t *card,
+ uint8_t *buffer,
+ uint32_t startBlock,
+ uint32_t blockCount)
+{
+ uint32_t blkCnt, blkLeft, blkDone;
+ sdhc_status_t err = kStatus_SDHC_NoError;
+
+ assert(card);
+ assert(buffer);
+ assert(blockCount);
+
+ blkLeft = blockCount;
+ blkDone = 0;
+
+ if ((blockCount + startBlock) > card->blockCount)
+ {
+ return kStatus_SDHC_InvalidIORange;
+ }
+
+ while(blkLeft)
+ {
+ if (blkLeft > card->host->maxBlockCount)
+ {
+ blkLeft = blkLeft - card->host->maxBlockCount;
+ blkCnt = card->host->maxBlockCount;
+ }
+ else
+ {
+ blkCnt = blkLeft;
+ blkLeft = 0;
+ }
+
+ err = SDCARD_DRV_Write(card,
+ buffer + blkDone * FSL_SDHC_CARD_DEFAULT_BLOCK_SIZE,
+ startBlock + blkDone,
+ FSL_SDHC_CARD_DEFAULT_BLOCK_SIZE,
+ blkCnt);
+ if (err != kStatus_SDHC_NoError)
+ {
+ return err;
+ }
+ blkDone += blkCnt;
+ }
+
+ return err;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_ReadBlocks
+ * Description: read blocks from card with default block size
+ *
+ *END*********************************************************************/
+sdhc_status_t SDCARD_DRV_ReadBlocks(sdhc_card_t *card,
+ uint8_t *buffer,
+ uint32_t startBlock,
+ uint32_t blockCount)
+{
+ uint32_t blkCnt, blkLeft, blkDone;
+ sdhc_status_t err = kStatus_SDHC_NoError;
+
+ assert(card);
+ assert(buffer);
+ assert(blockCount);
+
+ blkLeft = blockCount;
+ blkDone = 0;
+
+ if ((blockCount + startBlock) > card->blockCount)
+ {
+ return kStatus_SDHC_InvalidIORange;
+ }
+
+ while(blkLeft)
+ {
+ if (blkLeft > card->host->maxBlockCount)
+ {
+ blkLeft = blkLeft - card->host->maxBlockCount;
+ blkCnt = card->host->maxBlockCount;
+ }
+ else
+ {
+ blkCnt = blkLeft;
+ blkLeft = 0;
+ }
+
+ err = SDCARD_DRV_Read(card,
+ buffer + blkDone * FSL_SDHC_CARD_DEFAULT_BLOCK_SIZE,
+ startBlock + blkDone,
+ FSL_SDHC_CARD_DEFAULT_BLOCK_SIZE,
+ blkCnt);
+ if (err != kStatus_SDHC_NoError)
+ {
+ return err;
+ }
+ blkDone += blkCnt;
+ }
+
+ return err;
+}
+
+/*FUNCTION****************************************************************
+ *
+ * Function Name: SDCARD_DRV_EraseBlocks
+ * Description: erase block range from card with default block size
+ *
+ *END*********************************************************************/
+sdhc_status_t SDCARD_DRV_EraseBlocks(sdhc_card_t *card,
+ uint32_t startBlock,
+ uint32_t blockCount)
+{
+ uint32_t blkDone = 0, blkLeft, blkCnt;
+
+ assert(card);
+ assert(blockCount);
+
+ blkLeft = blockCount;
+ while(blkLeft)
+ {
+ if (blkLeft > (card->csd.sectorSize + 1))
+ {
+ blkCnt = card->csd.sectorSize + 1;
+ blkLeft = blkLeft - blkCnt;
+ }
+ else
+ {
+ blkCnt = blkLeft;
+ blkLeft = 0;
+ }
+
+ if (kStatus_SDHC_NoError != SDCARD_DRV_Erase(card,
+ startBlock + blkDone,
+ blkCnt))
+ {
+ return kStatus_SDHC_CardEraseBlocksFailed;
+ }
+
+ blkDone += blkCnt;
+ }
+ return kStatus_SDHC_NoError;
+}
diff --git a/KSDK_1.2.0/platform/composite/src/soundcard/fsl_soundcard.c b/KSDK_1.2.0/platform/composite/src/soundcard/fsl_soundcard.c
new file mode 100755
index 0000000..8edeeb9
--- /dev/null
+++ b/KSDK_1.2.0/platform/composite/src/soundcard/fsl_soundcard.c
@@ -0,0 +1,612 @@
+/*
+ * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "fsl_soundcard.h"
+#include <assert.h>
+#include <string.h>
+#include "fsl_os_abstraction.h"
+
+/*******************************************************************************
+ *Definitation
+ ******************************************************************************/
+#if SOUNDCARD_USE_STATIC_MEM
+#if defined( __ICCCF__ ) || defined( __ICCARM__ )
+#pragma segment="SAI_BDT_Z"
+#pragma data_alignment=4
+__no_init static uint8_t s_tx_buffer[AUDIO_CONTROLLER_NUM][AUDIO_BUFFER_SIZE] @ "SAI_BDT_Z";
+__no_init static uint8_t s_rx_buffer[AUDIO_CONTROLLER_NUM][AUDIO_BUFFER_SIZE] @ "SAI_BDT_Z";
+#elif defined(__GNUC__)
+__attribute__((aligned(4))) static uint8_t s_tx_buffer[AUDIO_CONTROLLER_NUM][AUDIO_BUFFER_SIZE];
+__attribute__((aligned(4))) static uint8_t s_rx_buffer[AUDIO_CONTROLLER_NUM][AUDIO_BUFFER_SIZE];
+#elif defined (__CC_ARM)
+__align(4) static uint8_t s_tx_buffer[AUDIO_CONTROLLER_NUM][AUDIO_BUFFER_SIZE];
+__align(4) static uint8_t s_rx_buffer[AUDIO_CONTROLLER_NUM][AUDIO_BUFFER_SIZE];
+#endif
+#endif
+
+#if USEDMA
+void SND_TxDmaCallback(void *param, edma_chn_status_t status);
+void SND_RxDmaCallback(void *param, edma_chn_status_t status);
+#else
+void SND_TxCallback(void *param);
+void SND_RxCallback(void *param);
+#endif
+
+/* The instance for sai operation structure. */
+audio_ctrl_operation_t g_sai_ops =
+{
+ SAI_DRV_TxInit,
+ SAI_DRV_RxInit,
+ SAI_DRV_TxDeinit,
+ SAI_DRV_RxDeinit,
+ SAI_DRV_TxConfigDataFormat,
+ SAI_DRV_RxConfigDataFormat,
+ SAI_DRV_TxStartModule,
+ SAI_DRV_RxStartModule,
+ SAI_DRV_TxStopModule,
+ SAI_DRV_RxStopModule,
+ SAI_DRV_TxRegisterCallback,
+ SAI_DRV_RxRegisterCallback,
+ SAI_DRV_TxSetIntCmd,
+ SAI_DRV_RxSetIntCmd,
+ SAI_DRV_TxSetDmaCmd,
+ SAI_DRV_RxSetDmaCmd,
+ SAI_DRV_TxGetWatermark,
+ SAI_DRV_RxGetWatermark,
+ SAI_DRV_TxGetFifoAddr,
+ SAI_DRV_RxGetFifoAddr,
+ SAI_DRV_SendDataInt,
+ SAI_DRV_ReceiveDataInt
+};
+
+/* Instance of codec operation for sgtl5000. */
+audio_codec_operation_t g_sgtl_ops =
+{
+ SGTL_Init,
+ SGTL_Deinit,
+ SGTL_ConfigDataFormat,
+ SGTL_SetDACMute,
+ SGTL_SetDACVoulme,
+ SGTL_GetDACVolume
+};
+
+/*******************************************************************************
+ *Code
+ ******************************************************************************/
+
+/*FUNCTION**********************************************************************
+*
+* Function Name : SND_TxInit
+* Description : Initialize the soundcard.
+* The soundcard includes a controller and a codec.
+*END**************************************************************************/
+snd_status_t SND_TxInit(
+ sound_card_t * card, void * ctrl_config, void * codec_config, ctrl_state_t *state)
+{
+ audio_controller_t *ctrl = &card->controller;
+ audio_codec_t *codec = &card->codec;
+ /* Allocate space for buffer */
+ audio_buffer_t *buffer = &card->buffer;
+ /* Buffer size and block settings */
+ if ((buffer->blocks == 0) || (buffer->size == 0))
+ {
+ buffer->blocks = AUDIO_BUFFER_BLOCK;
+ buffer->size = AUDIO_BUFFER_BLOCK_SIZE;
+ }
+#if SOUNDCARD_USE_STATIC_MEM
+ buffer->buff = &s_tx_buffer[ctrl->instance][0];
+#else
+ buffer->buff = (uint8_t *)OSA_MemAllocZero(buffer->size * buffer->blocks);
+ if(!buffer->buff)
+ {
+ return kStatus_SND_BufferAllocateFail;
+ }
+#endif
+ buffer->input_curbuff = buffer->buff;
+ buffer->output_curbuff = buffer->buff;
+ /* Initialize the status structure */
+ buffer->empty_block = buffer->blocks;
+ buffer->full_block = 0;
+ OSA_SemaCreate(&buffer->sem, buffer->blocks);
+ /* Initialize audio controller and codec */
+ ctrl->ops->Ctrl_TxInit(ctrl->instance, ctrl_config, state);
+ codec->ops->Codec_Init((void *)codec->handler, codec_config);
+#if USEDMA
+ EDMA_DRV_RequestChannel(kEDMAAnyChannel, ctrl->dma_source, &ctrl->dma_channel);
+ EDMA_DRV_InstallCallback(&ctrl->dma_channel, SND_TxDmaCallback, (void *)card);
+#else
+ ctrl->ops->Ctrl_TxRegisterCallback(ctrl->instance, SND_TxCallback, card);
+#endif
+ return kStatus_SND_Success;
+}
+
+/*FUNCTION**********************************************************************
+*
+* Function Name : SND_RxInit
+* Description : Initialize the Rx soundcard.
+* The soundcard includes a controller and a codec.
+*END**************************************************************************/
+snd_status_t SND_RxInit(
+sound_card_t * card, void * ctrl_config, void * codec_config, ctrl_state_t *state)
+{
+ audio_controller_t *ctrl = &card->controller;
+ audio_codec_t *codec = &card->codec;
+ /* Allocate space for buffer */
+ audio_buffer_t *buffer = &card->buffer;
+ /* Buffer size and block settings */
+ if ((buffer->blocks == 0) || (buffer->size == 0))
+ {
+ buffer->blocks = AUDIO_BUFFER_BLOCK;
+ buffer->size = AUDIO_BUFFER_BLOCK_SIZE;
+ }
+#if SOUNDCARD_USE_STATIC_MEM
+ buffer->buff = &s_rx_buffer[ctrl->instance][0];
+#else
+ buffer->buff = (uint8_t *)OSA_MemAllocZero(buffer->size * buffer->blocks);
+ if(!buffer->buff)
+ {
+ return kStatus_SND_BufferAllocateFail;
+ }
+#endif
+ buffer->input_curbuff = buffer->buff;
+ buffer->output_curbuff = buffer->buff;
+ /* Initialize the status structure */
+ buffer->empty_block = buffer->blocks;
+ buffer->full_block = 0;
+ OSA_SemaCreate(&buffer->sem, 0);
+ /* Initialize audio controller and codec */
+ ctrl->ops->Ctrl_RxInit(ctrl->instance, ctrl_config,state);
+ codec->ops->Codec_Init((void *)codec->handler, codec_config);
+#if USEDMA
+ EDMA_DRV_RequestChannel(kEDMAAnyChannel, ctrl->dma_source, &ctrl->dma_channel);
+ EDMA_DRV_InstallCallback(&ctrl->dma_channel, SND_RxDmaCallback, (void *)card);
+#else
+ ctrl->ops->Ctrl_RxRegisterCallback(ctrl->instance, SND_RxCallback, card);
+#endif
+ return kStatus_SND_Success;
+}
+
+/*FUNCTION*********************************************************************
+*
+* Function Name : SND_TxDeinit
+* Description : Deinit the tx soundcard.
+* The soundcard includes a controller and a codec.
+*END**************************************************************************/
+snd_status_t SND_TxDeinit(sound_card_t *card)
+{
+ audio_controller_t *ctrl = &card->controller;
+ audio_codec_t *codec = &card->codec;
+ audio_buffer_t *buffer = &card->buffer;
+ /* Call the deinit function of the ctrl and codec. */
+ ctrl->ops->Ctrl_TxDeinit(ctrl->instance);
+ codec->ops->Codec_Deinit((void *)codec->handler);
+#if USEDMA
+ /* Deinit the dma resource */
+ EDMA_DRV_StopChannel(&ctrl->dma_channel);
+ EDMA_DRV_ReleaseChannel(&ctrl->dma_channel);
+#endif
+ OSA_SemaDestroy(&buffer->sem);
+#if !SOUNDCARD_USE_STATIC_MEM
+ /* Free the tx and rx buffer. */
+ OSA_MemFree(buffer->buff);
+#endif
+ return kStatus_SND_Success;
+}
+
+/*FUNCTION*********************************************************************
+*
+* Function Name : SND_RxDeinit
+* Description : Deinit the rx soundcard.
+* The soundcard includes a controller and a codec.
+*END**************************************************************************/
+snd_status_t SND_RxDeinit(sound_card_t *card)
+{
+ audio_controller_t *ctrl = &card->controller;
+ audio_codec_t *codec = &card->codec;
+ audio_buffer_t *buffer = &card->buffer;
+ /* Call the deinit function of the ctrl and codec. */
+ ctrl->ops->Ctrl_RxDeinit(ctrl->instance);
+ codec->ops->Codec_Deinit((void *)codec->handler);
+#if USEDMA
+ /* Deinit the dma resource */
+ EDMA_DRV_StopChannel(&ctrl->dma_channel);
+ EDMA_DRV_ReleaseChannel(&ctrl->dma_channel);
+#endif
+ OSA_SemaDestroy(&buffer->sem);
+#if !SOUNDCARD_USE_STATIC_MEM
+ /* Free the tx and rx buffer. */
+ OSA_MemFree(buffer->buff);
+#endif
+ return kStatus_SND_Success;
+}
+
+/*FUNCTION**********************************************************************
+*
+* Function Name : SND_TxConfigDataFormat
+* Description : Configure the audio file format in tx soundcard.
+* The soundcard includes a controller and a codec. The audio format includes
+* sample rate, bit length and so on.
+*END**************************************************************************/
+snd_status_t SND_TxConfigDataFormat(sound_card_t *card, ctrl_data_format_t *format)
+{
+ audio_controller_t *ctrl = &card->controller;
+ audio_codec_t *codec = &card->codec;
+
+ ctrl->ops->Ctrl_TxConfigDataFormat(ctrl->instance, format);
+ codec->ops->Codec_ConfigDataFormat(codec->handler, format->mclk, format->sample_rate,
+ format->bits);
+ /* Configure dma */
+#if USEDMA
+ audio_buffer_t *buffer = &card->buffer;
+ uint32_t watermark = ctrl->ops->Ctrl_TxGetWatermark(ctrl->instance);
+ uint8_t sample_size = format->bits/8;
+ if((sample_size == 3) || (format->bits & 0x7))
+ {
+ sample_size = 4;
+ }
+ uint32_t desAddr = ctrl->ops->Ctrl_TxGetFifoAddr(ctrl->instance, ctrl->fifo_channel);
+ EDMA_DRV_ConfigLoopTransfer(
+ &ctrl->dma_channel, ctrl->stcd, kEDMAMemoryToPeripheral,
+ (uint32_t)buffer->buff, (uint32_t)desAddr, sample_size,
+ sample_size * (AUDIO_FIFO_LEN -watermark) , AUDIO_BUFFER_SIZE, AUDIO_BUFFER_BLOCK);
+ EDMA_DRV_StartChannel(&ctrl->dma_channel);
+#endif
+ return kStatus_SND_Success;
+}
+
+/*FUNCTION**********************************************************************
+*
+* Function Name : SND_RxConfigDataFormat
+* Description : Configure the audio file format in rx soundcard.
+* The soundcard includes a controller and a codec. The audio format includes
+* sample rate, bit length and so on.
+*END**************************************************************************/
+snd_status_t SND_RxConfigDataFormat(sound_card_t *card, ctrl_data_format_t *format)
+{
+ audio_controller_t *ctrl = &card->controller;
+ audio_codec_t *codec = &card->codec;
+
+ ctrl->ops->Ctrl_RxConfigDataFormat(ctrl->instance, format);
+ codec->ops->Codec_ConfigDataFormat(codec->handler, format->mclk, format->sample_rate,
+ format->bits);
+ /* Configure dma */
+#if USEDMA
+ audio_buffer_t *buffer = &card->buffer;
+ uint8_t sample_size = format->bits/8;
+ uint32_t watermark = ctrl->ops->Ctrl_RxGetWatermark(ctrl->instance);
+ if((sample_size == 3) || (format->bits & 0x7))
+ {
+ sample_size = 4;
+ }
+ uint32_t desAddr = ctrl->ops->Ctrl_RxGetFifoAddr(ctrl->instance,ctrl->fifo_channel);
+ EDMA_DRV_ConfigLoopTransfer(
+ &ctrl->dma_channel, ctrl->stcd, kEDMAPeripheralToMemory,
+ (uint32_t)desAddr, (uint32_t)buffer->buff, sample_size,
+ sample_size * watermark, AUDIO_BUFFER_SIZE, AUDIO_BUFFER_BLOCK);
+ EDMA_DRV_StartChannel(&ctrl->dma_channel);
+#endif
+ return kStatus_SND_Success;
+}
+
+/*FUNCTION**********************************************************************
+*
+* Function Name : SND_TxUpdateStatus
+* Description : Update the status of tx soundcard internal logic
+* The function would tell tx soundcard how many data applications have written
+* to the ring buffer.
+*END**************************************************************************/
+uint32_t SND_TxUpdateStatus(sound_card_t * card, uint32_t len)
+{
+ audio_buffer_t * buffer = &card->buffer;
+ uint32_t blocks = len/buffer->size;
+ /* Update the buffer information */
+ buffer->requested += len;
+ buffer->queued += len;
+
+ if(buffer->input_index + blocks < buffer->blocks)
+ {
+ buffer->input_index += blocks;
+ }
+ else
+ {
+ buffer->input_index = blocks - (buffer->blocks - 1 - buffer->input_index) - 1;
+ }
+ buffer->input_curbuff = buffer->buff + buffer->input_index * buffer->size;
+ buffer->empty_block -= blocks;
+ buffer->full_block += blocks;
+ /* If sai is not enable, enable the sai */
+ if (buffer->first_io)
+ {
+ buffer->first_io = false;
+ SND_TxStart(card);
+ }
+ return len;
+}
+
+/*FUNCTION**********************************************************************
+*
+* Function Name : SND_RxUpdateStatus
+* Description : Update the status of rx soundcard internal logic
+* The function would tell rx soundcard how many data applications have received
+* from the ring buffer.
+*END**************************************************************************/
+uint32_t SND_RxUpdateStatus(sound_card_t * card, uint32_t len)
+{
+ audio_buffer_t * buffer = &card->buffer;
+ uint32_t blocks = len/buffer->size;
+ /* Update inner information */
+ buffer->requested += len;
+ buffer->processed += len;
+ buffer->queued -= len;
+ /* Switch the buffer */
+ if(buffer->output_index + blocks < buffer->blocks)
+ {
+ buffer->output_index += blocks;
+ }
+ else
+ {
+ buffer->output_index = blocks - (buffer->blocks - 1 - buffer->output_index) - 1;
+ }
+ buffer->output_curbuff = buffer->buff + buffer->output_index * buffer->size;
+ buffer->full_block -= blocks;
+ buffer->empty_block += blocks;
+ /* If sai is not enable, enable the sai */
+ if (buffer->first_io)
+ {
+ buffer->first_io = false;
+ SND_RxStart(card);
+ }
+ return len;
+}
+
+/*FUNCTION**********************************************************************
+*
+* Function Name : SND_TxCallback
+* Description : Callback function to tell that audio controller have finished
+* a period data.
+* The function would update the buffer status information.
+*END**************************************************************************/
+void SND_TxCallback(void *param)
+{
+ sound_card_t *card = (sound_card_t *)param;
+ audio_buffer_t *buffer = &card->buffer;
+ if(buffer->queued == 0)
+ {
+ return;
+ }
+ buffer->processed += buffer->size;
+ buffer->queued -= buffer->size;
+
+ /* Change the current buffer */
+ if (buffer->output_index == buffer->blocks - 1)
+ {
+ buffer->output_curbuff = buffer->buff;
+ buffer->output_index = 0;
+ }
+ else
+ {
+ buffer->output_index ++;
+ buffer->output_curbuff += buffer->size;
+ }
+ /* Update the status */
+ buffer->empty_block += 1;
+ buffer->full_block -= 1;
+ /* Judge if need to close the SAI transfer. */
+ if (buffer->input_index == buffer->output_index)
+ {
+ SND_TxStop(card);
+ buffer->buffer_error ++;
+ buffer->first_io = true;
+ }
+ else
+ {
+#if !USEDMA
+ audio_controller_t * ctrl = &card->controller;
+ ctrl->ops->Ctrl_SendData(ctrl->instance, buffer->output_curbuff, buffer->size);
+#endif
+ }
+ /* post the sync */
+ OSA_SemaPost(&buffer->sem);
+}
+
+/*FUNCTION**********************************************************************
+*
+* Function Name : SND_RxCallback
+* Description : Callback function to tell that audio controller have finished
+* a period data.
+* The function would update the buffer status information.
+*END**************************************************************************/
+void SND_RxCallback(void *param)
+{
+ sound_card_t *card = (sound_card_t *)param;
+ audio_buffer_t *buffer = &card->buffer;
+ buffer->queued += buffer->size;
+ /* Change the current buffer. */
+ if (buffer->input_index == buffer->blocks - 1)
+ {
+ buffer->input_curbuff = buffer->buff;
+ buffer->input_index = 0;
+ }
+ else
+ {
+ buffer->input_index ++;
+ buffer->input_curbuff += buffer->size;
+ }
+ buffer->empty_block -= 1;
+ buffer->full_block += 1;
+ /* Judge if need to close the SAI transfer, while the buffer is full,
+ * we need to close the SAI */
+ if (buffer->input_index == buffer->output_index)
+ {
+ SND_RxStop(card);
+ buffer->buffer_error ++;
+ buffer->first_io = true;
+ }
+ else
+ {
+#if !USEDMA
+ audio_controller_t *ctrl = &card->controller;
+ ctrl->ops->Ctrl_ReceiveData(ctrl->instance, buffer->input_curbuff, buffer->size);
+#endif
+ }
+ OSA_SemaPost(&buffer->sem);
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : SND_GetStatus
+ * Description : Get the status of audio buffer, the status includes the empty
+ * blocks, full blocks and the starting address.
+ *END**************************************************************************/
+ void SND_GetStatus(sound_card_t *card, snd_state_t *status)
+{
+ audio_buffer_t *buffer = &card->buffer;
+ status->size = buffer->size;
+ status->empty_block = buffer->empty_block;
+ status->full_block = buffer->full_block;
+ status->input_address = buffer->input_curbuff;
+ status->output_address = buffer->output_curbuff;
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : SND_WaitEvent
+ * Description : This function is used for appliaction to wait for the semaphore
+ * to copy data in/out the sai buffer.
+ *END**************************************************************************/
+void SND_WaitEvent(sound_card_t *card)
+{
+ osa_status_t syncStatus;
+ audio_buffer_t *buffer = &card->buffer;
+ do
+ {
+ syncStatus = OSA_SemaWait(&buffer->sem, OSA_WAIT_FOREVER);
+ }while(syncStatus == kStatus_OSA_Idle);
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : SND_TxStart
+ * Description : This function is used to start tx transfer.
+ *END**************************************************************************/
+void SND_TxStart(sound_card_t *card)
+{
+ audio_controller_t *ctrl = &card->controller;
+#if !USEDMA
+ audio_buffer_t *buffer = &card->buffer;
+ ctrl->ops->Ctrl_SendData(ctrl->instance, buffer->output_curbuff, buffer->size);
+ ctrl->ops->Ctrl_TxSetIntCmd(ctrl->instance, true);
+#else
+ ctrl->ops->Ctrl_TxSetDmaCmd(ctrl->instance,true);
+ EDMA_DRV_StartChannel(&card->controller.dma_channel);
+#endif
+ ctrl->ops->Ctrl_TxStart(ctrl->instance);
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : SND_RxStart
+ * Description : This function is used to start rx receive.
+ *END**************************************************************************/
+void SND_RxStart(sound_card_t *card)
+{
+ audio_controller_t *ctrl = &card->controller;
+#if !USEDMA
+ audio_buffer_t *buffer = &card->buffer;
+ ctrl->ops->Ctrl_ReceiveData(ctrl->instance, buffer->input_curbuff, buffer->size);
+ ctrl->ops->Ctrl_RxSetIntCmd(ctrl->instance, true);
+#else
+ ctrl->ops->Ctrl_RxSetDmaCmd(ctrl->instance,true);
+ EDMA_DRV_StartChannel(&card->controller.dma_channel);
+#endif
+ ctrl->ops->Ctrl_RxStart(ctrl->instance);
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : SND_SetMuteCmd
+ * Description : This function is used to mute or unmute the soundcard.
+ *END**************************************************************************/
+snd_status_t SND_SetMuteCmd(sound_card_t * card,bool enable)
+{
+ audio_codec_t *codec = &card->codec;
+ codec->ops->Codec_SetMuteCmd(codec->handler, enable);
+ return kStatus_SND_Success;
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : SND_SetVolume
+ * Description : This function is used to set the volume of soundcard.
+ *END**************************************************************************/
+snd_status_t SND_SetVolume(sound_card_t * card,uint32_t volume)
+{
+ audio_codec_t *codec = &card->codec;
+ codec->ops->Codec_SetMuteCmd(codec->handler, false);
+ codec->ops->Codec_SetVolume(codec->handler,volume);
+ return kStatus_SND_Success;
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : SND_GetVolume
+ * Description : This function is used to get the volume of soundcard.
+ *END**************************************************************************/
+uint32_t SND_GetVolume(sound_card_t * card)
+{
+ audio_codec_t *codec = &card->codec;
+ return codec->ops->Codec_GetVolume(codec->handler);
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : SND_TxDmaCallback
+ * Description : This function is as the tx callback function registered to dma module.
+ *END**************************************************************************/
+void SND_TxDmaCallback(void *param, edma_chn_status_t status)
+{
+ SND_TxCallback(param);
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : SND_RxDmaCallback
+ * Description : This function is as the rx callback function registered to dma module.
+ *END**************************************************************************/
+void SND_RxDmaCallback(void *param, edma_chn_status_t status)
+{
+ SND_RxCallback(param);
+}
+
+/*******************************************************************************
+ *EOF
+ ******************************************************************************/
+