MCUXpresso_LPC55S69/boards/lpcxpresso55s69/sdmmc_examples/sdcard_polling/cm33_core0/sdcard_polling.c

298 lines
9.3 KiB
C

/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include "fsl_debug_console.h"
#include "pin_mux.h"
#include "board.h"
#include "fsl_sd.h"
#include "sdmmc_config.h"
#include <stdbool.h>
#include "fsl_iocon.h"
#include "fsl_power.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Data block count accessed in card */
#define DATA_BLOCK_COUNT (5U)
/*! @brief Start data block number accessed in card */
#define DATA_BLOCK_START (2U)
/*! @brief Data buffer size. */
#define DATA_BUFFER_SIZE (FSL_SDMMC_DEFAULT_BLOCK_SIZE * DATA_BLOCK_COUNT)
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief printf the card information log.
*
* @param card Card descriptor.
*/
static void CardInformationLog(sd_card_t *card);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Card descriptor. */
sd_card_t g_sd;
/* @brief decription about the read/write buffer
* The size of the read/write buffer should be a multiple of 512, since SDHC/SDXC card uses 512-byte fixed
* block length and this driver example is enabled with a SDHC/SDXC card.If you are using a SDSC card, you
* can define the block length by yourself if the card supports partial access.
* The address of the read/write buffer should align to the specific DMA data buffer address align value if
* DMA transfer is used, otherwise the buffer address is not important.
* At the same time buffer address/size should be aligned to the cache line size if cache is supported.
*/
/*! @brief Data written to the card */
SDK_ALIGN(uint8_t g_dataWrite[DATA_BUFFER_SIZE], BOARD_SDMMC_DATA_BUFFER_ALIGN_SIZE);
/*! @brief Data read from the card */
SDK_ALIGN(uint8_t g_dataRead[DATA_BUFFER_SIZE], BOARD_SDMMC_DATA_BUFFER_ALIGN_SIZE);
/*******************************************************************************
* Code
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
static status_t AccessCard(sd_card_t *card, bool isReadOnly)
{
if (isReadOnly)
{
PRINTF("\r\nRead one data block......\r\n");
if (kStatus_Success != SD_ReadBlocks(card, g_dataRead, DATA_BLOCK_START, 1U))
{
PRINTF("Read one data block failed.\r\n");
return kStatus_Fail;
}
PRINTF("Read multiple data blocks......\r\n");
if (kStatus_Success != SD_ReadBlocks(card, g_dataRead, DATA_BLOCK_START, DATA_BLOCK_COUNT))
{
PRINTF("Read multiple data blocks failed.\r\n");
return kStatus_Fail;
}
}
else
{
memset(g_dataWrite, 0x67U, sizeof(g_dataWrite));
PRINTF("\r\nWrite/read one data block......\r\n");
if (kStatus_Success != SD_WriteBlocks(card, g_dataWrite, DATA_BLOCK_START, 1U))
{
PRINTF("Write one data block failed.\r\n");
return kStatus_Fail;
}
memset(g_dataRead, 0U, sizeof(g_dataRead));
if (kStatus_Success != SD_ReadBlocks(card, g_dataRead, DATA_BLOCK_START, 1U))
{
PRINTF("Read one data block failed.\r\n");
return kStatus_Fail;
}
PRINTF("Compare the read/write content......\r\n");
if (memcmp(g_dataRead, g_dataWrite, FSL_SDMMC_DEFAULT_BLOCK_SIZE))
{
PRINTF("The read/write content isn't consistent.\r\n");
return kStatus_Fail;
}
PRINTF("The read/write content is consistent.\r\n");
PRINTF("Write/read multiple data blocks......\r\n");
if (kStatus_Success != SD_WriteBlocks(card, g_dataWrite, DATA_BLOCK_START, DATA_BLOCK_COUNT))
{
PRINTF("Write multiple data blocks failed.\r\n");
return kStatus_Fail;
}
memset(g_dataRead, 0U, sizeof(g_dataRead));
if (kStatus_Success != SD_ReadBlocks(card, g_dataRead, DATA_BLOCK_START, DATA_BLOCK_COUNT))
{
PRINTF("Read multiple data blocks failed.\r\n");
return kStatus_Fail;
}
PRINTF("Compare the read/write content......\r\n");
if (memcmp(g_dataRead, g_dataWrite, FSL_SDMMC_DEFAULT_BLOCK_SIZE))
{
PRINTF("The read/write content isn't consistent.\r\n");
return kStatus_Fail;
}
PRINTF("The read/write content is consistent.\r\n");
PRINTF("Erase multiple data blocks......\r\n");
if (kStatus_Success != SD_EraseBlocks(card, DATA_BLOCK_START, DATA_BLOCK_COUNT))
{
PRINTF("Erase multiple data blocks failed.\r\n");
return kStatus_Fail;
}
}
return kStatus_Success;
}
/*!
* @brief Main function
*/
int main(void)
{
sd_card_t *card = &g_sd;
char ch = '0';
bool isReadOnly;
/* set BOD VBAT level to 1.65V */
POWER_SetBodVbatLevel(kPOWER_BodVbatLevel1650mv, kPOWER_BodHystLevel50mv, false);
CLOCK_EnableClock(kCLOCK_InputMux);
/* attach 12 MHz clock to FLEXCOMM0 (debug console) */
CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);
BOARD_InitPins();
BOARD_BootClockPLL150M();
BOARD_InitDebugConsole();
BOARD_SD_Config(card, NULL, BOARD_SDMMC_SD_HOST_IRQ_PRIORITY, NULL);
PRINTF("\r\nSDCARD polling example.\r\n");
/* SD host init function */
if (SD_HostInit(card) != kStatus_Success)
{
PRINTF("\r\nSD host init fail\r\n");
return -1;
}
while (ch != 'q')
{
PRINTF("\r\nPlease insert a card into board.\r\n");
/* wait card insert */
SD_PollingCardInsert(card, kSD_Inserted);
/* power off card */
SD_SetCardPower(card, false);
/* power on the card */
SD_SetCardPower(card, true);
PRINTF("\r\nCard inserted.\r\n");
/* Init card. */
if (SD_CardInit(card))
{
PRINTF("\r\nSD card init failed.\r\n");
return -1;
}
/* card information log */
CardInformationLog(card);
/* Check if card is readonly. */
isReadOnly = SD_CheckReadOnly(card);
PRINTF("\r\nRead/Write/Erase the card continuously until encounter error......\r\n");
for (;;)
{
if (kStatus_Success != AccessCard(card, isReadOnly))
{
/* access card fail, due to card remove. */
if (SD_IsCardPresent(card) == false)
{
SD_HostDoReset(card);
PRINTF("\r\nCard removed\r\n");
PRINTF(
"\r\nInput 'q' to quit read/write/erase process.\
\r\nInput other char to wait card re-insert.\r\n");
ch = GETCHAR();
PUTCHAR(ch);
}
/* access card fail, due to transfer error */
else
{
ch = 'q';
}
break;
}
else
{
PRINTF(
"\r\nInput 'q' to quit read/write/erase process.\
\r\nInput other char to read/write/erase data blocks again.\r\n");
ch = GETCHAR();
PUTCHAR(ch);
if (ch == 'q')
{
break;
}
}
}
}
PRINTF("\r\nThe example will not read/write data blocks again.\r\n");
SD_Deinit(card);
while (true)
{
}
}
static void CardInformationLog(sd_card_t *card)
{
assert(card);
PRINTF("\r\nCard size %d * %d bytes\r\n", card->blockCount, card->blockSize);
PRINTF("\r\nWorking condition:\r\n");
if (card->operationVoltage == kSDMMC_OperationVoltage330V)
{
PRINTF("\r\n Voltage : 3.3V\r\n");
}
else if (card->operationVoltage == kSDMMC_OperationVoltage180V)
{
PRINTF("\r\n Voltage : 1.8V\r\n");
}
if (card->currentTiming == kSD_TimingSDR12DefaultMode)
{
if (card->operationVoltage == kSDMMC_OperationVoltage330V)
{
PRINTF("\r\n Timing mode: Default mode\r\n");
}
else if (card->operationVoltage == kSDMMC_OperationVoltage180V)
{
PRINTF("\r\n Timing mode: SDR12 mode\r\n");
}
}
else if (card->currentTiming == kSD_TimingSDR25HighSpeedMode)
{
if (card->operationVoltage == kSDMMC_OperationVoltage180V)
{
PRINTF("\r\n Timing mode: SDR25\r\n");
}
else
{
PRINTF("\r\n Timing mode: High Speed\r\n");
}
}
else if (card->currentTiming == kSD_TimingSDR50Mode)
{
PRINTF("\r\n Timing mode: SDR50\r\n");
}
else if (card->currentTiming == kSD_TimingSDR104Mode)
{
PRINTF("\r\n Timing mode: SDR104\r\n");
}
else if (card->currentTiming == kSD_TimingDDR50Mode)
{
PRINTF("\r\n Timing mode: DDR50\r\n");
}
PRINTF("\r\n Freq : %d HZ\r\n", card->busClock_Hz);
}