SD card and FreeRTOS

owaisfazal wrote on Thursday, September 11, 2014:

Hello everyone,
I am a beginner in using SD cards. I am working with SAM4SD32C in Atmel Studio. So far I have managed to initialize the HSMCI interface and SD card is also initialized by sending the corresponding commands given in SD simplified specifications. Now i would like to test read and write operation for the SD card to make sure everything is working properly. After this my intention is to use the SD card as a storage device in FreeRTOS+FATSL. I have gone through the examples given in Atmel Studio and I have the following functions which are used to write and read to and from the SD card. I am stuck at this point as I am not sure what to give in the parameters of these functions to initiate a write or read operation. The functions are as follows, The read block and write block function calls the adtc command and the read block init and write block init send CMD13 to check the data ready status from the card. Please also suggest how I could integrate these function into FreeRTOS+FATSL to be able to use the SD card as a storage device with FreeRTOS.

Regards,
Owais

    uint32_t sd_mmc_init_read_blocks(uint8_t slot, uint32_t start,
    uint16_t nb_block)         
    {
uint32_t cmd, arg, resp;

// Wait for data ready status
if (!sd_mmc_cmd13())
{
	printf("CMD13 data ready error\n\r");
	return FAIL;
}

if (nb_block > 1)
{
	cmd = SDMMC_CMD18_READ_MULTIPLE_BLOCK;
}
else
{
	cmd = SDMMC_CMD17_READ_SINGLE_BLOCK;
}
/*
* SDSC Card (CCS=0) uses byte unit address,
* SDHC and SDXCCards(CCS=1)use blockunitaddress(512Bytes unit).
 */
arg = start;

if (!hsmci_adtc_start(cmd, arg, SD_MMC_BLOCK_SIZE, nb_block,1))
{
	printf("adtc start error\n\r");
	return FAIL;
}
// Check response
resp = hsmci_get_response();
if (resp & CARD_STATUS_ERR_RD_WR)
{
	return FAIL;
}
sd_mmc_nb_block_remaining = nb_block;
sd_mmc_nb_block_to_tranfer = nb_block;
printf("Read blocks initialization done\n\r");
return OK;
    }

    uint32_t sd_mmc_start_read_blocks(void *dest, uint16_t
    nb_block)
    {
if (!(sd_mmc_nb_block_remaining >= nb_block))
{
	printf("No. of blocks remaining is >= start read
            block\n\r"); 
	return FAIL;		
}

if (!hsmci_start_read_blocks(dest, nb_block))
{
	printf("Start read blocks failed\n\r");
	sd_mmc_nb_block_remaining = 0;
	return FAIL;
}
sd_mmc_nb_block_remaining -= nb_block;
return OK;
    }

    uint32_t sd_mmc_wait_end_of_read_blocks(int abort)
    {
if (!hsmci_wait_end_of_read_blocks())
{
	printf("HSMCI wait end of read blocks failed\n\r");
	return FAIL;
}
if (abort)
{
	sd_mmc_nb_block_remaining = 0;
}
else if (sd_mmc_nb_block_remaining)
{
	return OK;
}

// All blocks are transfered then stop read operation
if (sd_mmc_nb_block_to_tranfer == 1)
{
	// Single block transfer, then nothing to do
	printf("All blocks transferred\n\r");
	return OK;
}

if (!hsmci_adtc_stop(SDMMC_CMD12_STOP_TRANSMISSION, 0))
{
	hsmci_adtc_stop(SDMMC_CMD12_STOP_TRANSMISSION, 0);
}
return OK;
    }

    uint32_t sd_mmc_init_write_blocks(uint8_t slot, uint32_t start,
    uint16_t nb_block)	 
    {
uint32_t cmd, arg, resp;

if (nb_block > 1)
{
	cmd = SDMMC_CMD25_WRITE_MULTIPLE_BLOCK;
}
else
{
	cmd = SDMMC_CMD24_WRITE_BLOCK;
}
/*
 * SDSC Card (CCS=0) uses byte unit address,
 * SDHC and SDXCCards(CCS=1)useblockunitaddress(512Bytes unit).
 */
arg = start;

if (!hsmci_adtc_start(cmd, arg, SD_MMC_BLOCK_SIZE, nb_block,1))
{
	printf("adtc start error\n\r");
	return FAIL;
}
// Check response
resp = hsmci_get_response();
if (resp & CARD_STATUS_ERR_RD_WR)
{
	return FAIL;
}
sd_mmc_nb_block_remaining = nb_block;
sd_mmc_nb_block_to_tranfer = nb_block;
printf("Write blocks initialization done\n\r");
return OK;
    }

    uint32_t sd_mmc_start_write_blocks(const void *src, uint16_t
    nb_block)
    {
if(!(sd_mmc_nb_block_remaining >= nb_block))
{
    printf("No. of blocks remaining is >= to start write
    block\n\r");
	return FAIL;
}
if (!hsmci_start_write_blocks(src, nb_block))
{
	printf("Start write blocks failed\n\r");
	sd_mmc_nb_block_remaining = 0;
	return FAIL;
}
sd_mmc_nb_block_remaining -= nb_block;
return OK;
    }

    uint32_t sd_mmc_wait_end_of_write_blocks(int abort)
    {
if (!hsmci_wait_end_of_write_blocks())
{
	printf("HSMCI wait end of write blocks failed\n\r");
	return FAIL;
}
if (abort)
{
	sd_mmc_nb_block_remaining = 0;
}
else if (sd_mmc_nb_block_remaining)
{
	return OK;
}

// All blocks are transfered then stop write operation
if (sd_mmc_nb_block_to_tranfer == 1)
{
	// Single block transfer, then nothing to do
	printf("All blocks written\n\r");
	return OK;
}

// Note: SPI multiblock writes terminate using a special
// token, not a STOP_TRANSMISSION request.
if (!hsmci_adtc_stop(SDMMC_CMD12_STOP_TRANSMISSION, 0))
{		
	return FAIL;
}
else
{
	printf("adtc stop command executed\n\r");
}
return OK;
    }

    uint32_t hsmci_adtc_start(uint32_t cmd, uint32_t arg, uint16_t
    block_size, uint16_t nb_block, uint32_t access_block)      
    {
uint32_t cmdr;

    #ifdef HSMCI_MR_PDCMODE
if (access_block)
{
	// Enable PDC for HSMCI
	HSMCI->HSMCI_MR |= HSMCI_MR_PDCMODE;
}
else
{
	// Disable PDC for HSMCI
	HSMCI->HSMCI_MR &= ~HSMCI_MR_PDCMODE;
}
    #endif

// Enabling Read/Write Proof allows to stop the HSMCI Clock 
// during read/write  access if the internal FIFO is full.
// This will guarantee data integrity, not bandwidth.
HSMCI->HSMCI_MR |= HSMCI_MR_WRPROOF | HSMCI_MR_RDPROOF;
// Force byte transfer if needed
if (block_size & 0x3)
{
	HSMCI->HSMCI_MR |= HSMCI_MR_FBYTE;
}
else
{
	HSMCI->HSMCI_MR &= ~HSMCI_MR_FBYTE;
}

if (cmd & SDMMC_CMD_WRITE)
{
cmdr = HSMCI_CMDR_TRCMD_START_DATA | HSMCI_CMDR_TRDIR_WRITE;
}
else
{
cmdr = HSMCI_CMDR_TRCMD_START_DATA | HSMCI_CMDR_TRDIR_READ;
}

if (cmd & SDMMC_CMD_SDIO_BYTE)
{
cmdr |= HSMCI_CMDR_TRTYP_BYTE;
// Value 0 corresponds to a 512-byte transfer
HSMCI->HSMCI_BLKR = ((block_size % 512) <<HSMCI_BLKR_BCNT_Pos);
}
else
{
HSMCI->HSMCI_BLKR = (block_size << HSMCI_BLKR_BLKLEN_Pos) |
    (nb_block << HSMCI_BLKR_BCNT_Pos);
	if (cmd & SDMMC_CMD_SDIO_BLOCK)
	{
		cmdr |= HSMCI_CMDR_TRTYP_BLOCK;
	}
	else if (cmd & SDMMC_CMD_STREAM)
	{
		cmdr |= HSMCI_CMDR_TRTYP_STREAM;
	}
	else if (cmd & SDMMC_CMD_SINGLE_BLOCK)
	{
		cmdr |= HSMCI_CMDR_TRTYP_SINGLE;
	}
	else if (cmd & SDMMC_CMD_MULTI_BLOCK)
	{
		cmdr |= HSMCI_CMDR_TRTYP_MULTIPLE;
	}
	else
	{
		//Assert(FAIL); // Incorrect flags
		printf("Incorrect flags in adtc command\n\r");
	}
}
hsmci_transfert_pos = 0;
hsmci_block_size = block_size;
hsmci_nb_block = nb_block;

return hsmci_send_cmd_execute(cmdr, cmd, arg);
    }

    uint32_t hsmci_adtc_stop(uint32_t cmd, uint32_t arg)
    {
return hsmci_send_cmd_execute(HSMCI_CMDR_TRCMD_STOP_DATA, cmd,
    arg);    
    }

    uint32_t sd_mmc_cmd13(void)
    {
uint32_t nec_timeout;

/* Wait for data ready status.
 * Nec timing: 0 to unlimited
 * However a timeout is used.
 * 200 000 * 8 cycles
 */
nec_timeout = 200000;
do
{
if (!hsmci_send_cmd(SDMMC_MCI_CMD13_SEND_STATUS, rca << 16))
	{
		return FAIL;
	}
	// Check busy flag
	if (hsmci_get_response() & CARD_STATUS_READY_FOR_DATA)
	{
		break;
	}
	if (nec_timeout-- == 0)
	{
		printf("%s: CMD13 Busy timeout\n\r", __func__);
		return FAIL;
	}
} while (1);

return OK;
    }

davedoors wrote on Thursday, September 11, 2014:

So there are ASF functions and nothing to do with FreeRTOS? Have you tried the ASF documentation?

owaisfazal wrote on Thursday, September 11, 2014:

I was very reluctant to post this right now since everything is related to ASF but this is where I have to start in order to use SD card with FreeRTOS+FATSL. I have searched a lot but in vain. ASF documentation explains the functions and their variables but not exactly how to read and write and I cannot find any application notes related to HSMCI. Please give me some references where I could get help in this regard.

owaisfazal wrote on Thursday, September 11, 2014:

Is there anyone who has implemented the FreeRTOS+FAT for an SD card before. If so please do share your experience. I am stuck at this point and cannot proceed.

Regrads,
Owais

woops_ wrote on Thursday, September 11, 2014:

Help? http://www.freertos.org/FreeRTOS_Support_Forum_Archive/June_2014/freertos_FreeRTOS_FAT_SL_SD_Card_initialization_issue_c35711ecj.html

owaisfazal wrote on Thursday, September 11, 2014:

Thanks woops_ I have seen this thread before. It seems as if it has gone idle since a while now. I wonder what is the progress now.