FreeRTOS+FAT SL, SD Card, initialization issue

owaisfazal wrote on Monday, September 15, 2014:

Hello Wonjae, Thanks for the response. I am using Atmel SAM4S CortexM. Have you ever worked with these microcontrollers? Can we set up a timing to discuss this matter it would be more convenient for me if we can arrange something like this. Please let me know if it is possible for you. I am now planning to directly go ajead with the FreeRTOS+FAT and integrate the SD card into it. Looking forward to your help.
Regards,
Owais

zealhero wrote on Monday, September 15, 2014:

Hello Owais.

I haven’t used other microcontrollers. But I think it is no problem if you can use SPI communication FreeRTOS and FAT SL on your system.
I agree with your opinion, we can make an appointment. it is no hard.

Write your statement or questions on this post or another new post, I can reply it if I know about it. Then other engineers also help you :slight_smile:

Regards.
Wonjae

owaisfazal wrote on Monday, September 15, 2014:

Hello Wonjae, I am actually using the HSMCI interface on SAM4S. Since I will be using the SPI interface for other purpose. I have already tested FreeRTOS on my system it is running fine. I just need to include the necessary files for the FAT SL inti the FreeRTOS environment and then integrate the SD related components. Can you please tell me where to start from. I have the initialization of SD working fine and I have other functions such as read and write blocks. Where should i put them into FAT SL? Thanks in advance.
Regards,
Owais

zealhero wrote on Monday, September 15, 2014:

Did you tried using window demo project?
It is good for understanding the structure and system of FAT SL. Try it if you didn’t.
It is using ram for storage, its configurations are in ‘ramdrv_f.c’. You can change it to your own codes for SD storage system.
Regards.
Wonjae

owaisfazal wrote on Monday, September 15, 2014:

I am actually looking into it right now. It consists of many files can I open it in Atmel Studio?

zealhero wrote on Monday, September 15, 2014:

It can be opend ‘Visual Studio’. Did you use it before…?
You can see the guide at here.
http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_FAT_SL/Demos/File_System_Win32_Simulator_demo.shtml
You can also open it by Atmel Studio but cannot execute. you can just read the codes. It is maybe enough to understand the system.

owaisfazal wrote on Monday, September 15, 2014:

No I haven’t used it before. I will go through it now. Moreover, I have looked into an example project in Atmel Studio for unit testing the HSMCI interface. Form there I have got the functions related to HSMCI interface for reading and writing blocks to the SD card. I wonder if I can use these in the FreeRTOS+FAT SL somehow, have you done the same? My card is initializing now and I get the card capacity and RCA (Relative Card Address). Next I want to try to initialize the card in FreeRTOS+FAT SL and see if it works the same way as it does without FreeRTOS+FAT SL. Any suggestions in this regard would be helpful.

zealhero wrote on Monday, September 15, 2014:

The answer is maybe in ramdrv_f.c…
It is needed to connect SD functions with FAT SL function.
Make a new F_DRIVER structure and put your SD functions into the structure.

ex) structurename.readsector = SD_read;
structurename is declared F_DRIVER * and it has readsector, writesector…etc. you can find it.
SD_read is your own function already you used for reading SD memory.

owaisfazal wrote on Monday, September 15, 2014:

Okay let me first included the necessary file into my project. I will continue from there on. One more thing, I just have the following functions related to HSMCI read and write can you please look into them and let me know if they would be sufficient for including int the F-DRIVER structure or do I need something else.

uint32_t hsmci_start_read_blocks(void *dest, uint16_t nb_block)
{
uint32_t nb_data;

nb_data = nb_block * hsmci_block_size;

// Handle unaligned memory address
if (((uint32_t)dest & 0x3) || (hsmci_block_size & 0x3))
{
HSMCI->HSMCI_MR |= HSMCI_MR_FBYTE;
}
else
{
HSMCI->HSMCI_MR &= ~HSMCI_MR_FBYTE;
}

// Configure PDC transfer
HSMCI->HSMCI_RPR = (uint32_t)dest;
HSMCI->HSMCI_RCR = (HSMCI->HSMCI_MR & HSMCI_MR_FBYTE) ? nb_data : nb_data / 4;
HSMCI->HSMCI_RNCR = 0;
// Start transfer
HSMCI->HSMCI_PTCR = HSMCI_PTCR_RXTEN;
hsmci_transfert_pos += nb_data;
return OK;
}

uint32_t hsmci_wait_end_of_read_blocks(void)
{
uint32_t sr;
// Wait end of transfer
// Note: no need of timeout, because it is include in HSMCI, see DTOE bit.
do
{
sr = HSMCI->HSMCI_SR;
if (sr & (HSMCI_SR_UNRE | HSMCI_SR_OVRE | HSMCI_SR_DTOE | HSMCI_SR_DCRCE))
{
HSMCI->HSMCI_PTCR = HSMCI_PTCR_RXTDIS | HSMCI_PTCR_TXTDIS;
hsmci_reset();
return FAIL;
}

} while (!(sr & HSMCI_SR_RXBUFF));

if (hsmci_transfert_pos < ((uint32_t)hsmci_block_size * hsmci_nb_block))
{
return OK;
}
// It is the last transfer, then wait command completed
// Note: no need of timeout, because it is include in HSMCI, see DTOE bit.
do
{
sr = HSMCI->HSMCI_SR;
if (sr & (HSMCI_SR_UNRE | HSMCI_SR_OVRE | HSMCI_SR_DTOE | HSMCI_SR_DCRCE))
{
hsmci_reset();
return FAIL;
}
} while (!(sr & HSMCI_SR_XFRDONE));
return OK;
}

uint32_t hsmci_start_write_blocks(const void *src, uint16_t nb_block)
{
uint32_t nb_data;

nb_data = nb_block * hsmci_block_size;

// Handle unaligned memory address
if (((uint32_t)src & 0x3) || (hsmci_block_size & 0x3))
{
HSMCI->HSMCI_MR |= HSMCI_MR_FBYTE;
}
else
{
HSMCI->HSMCI_MR &= ~HSMCI_MR_FBYTE;
}

// Configure PDC transfer
HSMCI->HSMCI_TPR = (uint32_t)src;
HSMCI->HSMCI_TCR = (HSMCI->HSMCI_MR & HSMCI_MR_FBYTE) ? nb_data : nb_data / 4;
HSMCI->HSMCI_TNCR = 0;
// Start transfer
HSMCI->HSMCI_PTCR = HSMCI_PTCR_TXTEN;
hsmci_transfert_pos += nb_data;
return OK;
}

uint32_t hsmci_wait_end_of_write_blocks(void)
{
uint32_t sr;

// Wait end of transfer
// Note: no need of timeout, because it is include in HSMCI, see DTOE bit.
do
{
sr = HSMCI->HSMCI_SR;
if (sr & (HSMCI_SR_UNRE | HSMCI_SR_OVRE | HSMCI_SR_DTOE | HSMCI_SR_DCRCE))
{
hsmci_reset();
HSMCI->HSMCI_PTCR = HSMCI_PTCR_RXTDIS | HSMCI_PTCR_TXTDIS;
return FAIL;
}
} while (!(sr & HSMCI_SR_TXBUFE));

if (hsmci_transfert_pos < ((uint32_t)hsmci_block_size * hsmci_nb_block))
{
return OK;
}
// It is the last transfer, then wait command completed
// Note: no need of timeout, because it is include in HSMCI, see DTOE bit.
do
{
sr = HSMCI->HSMCI_SR;
if (sr & (HSMCI_SR_UNRE | HSMCI_SR_OVRE | HSMCI_SR_DTOE | HSMCI_SR_DCRCE))
{
hsmci_reset();
return FAIL;
}
} while (!(sr & HSMCI_SR_NOTBUSY));
//Assert(HSMCI->HSMCI_SR & HSMCI_SR_FIFOEMPTY);
return OK;
}

These are from the Atmel Studio example of HSMCI interface unit test.

Thanks once again for your support.

owaisfazal wrote on Monday, September 15, 2014:

Hello Wonjae,

I have included all the source and include files from FreeRTOS+FAT SL into my project and it is compiling without any error, but this is without any implementation or initialization yet just the files are included and linked. Now I am looking at the F_DRIVER structure defined in api_mdriver.h I cannot understand where are these functions implemented (F_DRIVERINIT F_WRITESECTOR F_READSECTOR F_GETPHY F_GETSTATUS F_RELEASE) and what should I do to replace them with my functions for example SD initialization etc. This is really very stressful but i hope you understand my situation and could help me further. Thanks for your support.

Regards,
Owais

zealhero wrote on Tuesday, September 16, 2014:

Hello Owais.

  1. I can’t check your codes because I haven’t used HSMCI. but you know it already if you tested it without the file system.

  2. I can understand your streessful situation… I was same with you.
    F_DRIVER what you found is important.
    Make a new initialization function like ram_initfunc() in ‘ramdrv_f.c’. Refer the codes in the file. Try it. It is almost finished. Good luck.

Regards.
Wonjae

owaisfazal wrote on Tuesday, September 16, 2014:

Hello Wonjae and thank you very much for your continuous support, I have initialized a new function in of type F_DRIVER and also I have declared the same in API_mdriver.h as follows:

F_DRIVER * sd_init ( unsigned long driver_param );

and the sd_init function is implemented inside ramdrv_f.c as follows :

F_DRIVER * sd_init ( unsigned long driver_param )
{
( void ) driver_param;

if( in_use )
return NULL;
	
s_driver.readsector = sd_mmc_start_read_blocks;
s_driver.writesector = sd_mmc_start_write_blocks;
s_driver.getphy = sd_getphy;
s_driver.release = sd_release;

//SD card version 2
uint8_t v2 = 0;

// Card need of 74 cycles clock minimum to start
hsmci_send_clock();

// CMD0 - Reset all cards to idle state.
if (!hsmci_send_cmd(SDMMC_MCI_CMD0_GO_IDLE_STATE, 0))
{
	printf("CMD0 failed\n\r");
	return FAIL;
}

// Test SD card for voltage compatibility
if (!sd_cmd8(&v2))
{
	//return FAIL;
	printf("CMD8 failed\n\r");
}

// Try to get the SD card's operating condition
if (!sd_mci_op_cond(v2))
{
	//It is not a SD card
	//return FAIL;
	printf("Not a valid SD card\n\r");
}

// SD MEMORY, Put the Card in Identify Mode
// Note: The CID is not used in this stack
if (!hsmci_send_cmd(SDMMC_CMD2_ALL_SEND_CID, 0))
{
	printf("CMD2 failed\n\r");
	return FAIL;
}
// Ask the card to publish a new relative address (RCA).
if (!hsmci_send_cmd(SD_CMD3_SEND_RELATIVE_ADDR, 0))
{
	printf("CMD3 failed\n\r");
	return FAIL;
}
rca = ((hsmci_get_response() >> 16) & 0xFFFF);
printf("Card relative address is : %d\n\r", rca);

// SD MEMORY, Get the Card-Specific Data
if (!hsmci_send_cmd(SDMMC_MCI_CMD9_SEND_CSD, rca << 16))
{
	printf("CMD9 failed\n\r");
	return FAIL;
}
hsmci_get_response_128(csd);
sd_decode_csd();

// Select the SD card and put it into Transfer Mode
if (!hsmci_send_cmd(SDMMC_CMD7_SELECT_CARD_CMD, rca << 16))
{
	printf("Failed to execute CMD7\n\r");
	return FAIL;
}

// SD MEMORY, Read the SCR to get card version
if (!sd_acmd51())
{
	//return FAIL;
	printf("ACMD51 failed\n\r");
}

// TRY to enable High-Speed Mode
if (!sd_cm6_set_high_speed())
{
	//return FAIL;
	printf("High Speed not set\n\r");
}
else
{
	hsmci_select_device(0, clock, 4, high_speed);
	// Set power saving to maximum value
	//HSMCI->HSMCI_MR = HSMCI_MR_PWSDIV(0x07);
	//HSMCI->HSMCI_CR = HSMCI_CR_PWSEN;
	printf("Card switched to HS mode\n\r");
}

// SD MEMORY, Set default block size
    if(!hsmci_send_cmd(SDMMC_CMD16_SET_BLOCKLEN,SD_MMC_BLOCK_SIZE))
{
	//return FAIL;
	printf("CMD16 failed\n\r");
}
printf("Card relative address is : %d\n\r", rca);

in_use = 1;

return &s_driver;
}

Does this look somewhat correct? I realize there are some flags like F_ERR_NOTFORMATTED and F_NO_ERROR do i need to included these in the sd_init function? Secondly when I run the vCreateAndVerifySampleFiles() it tries to read from the sd card even though I have commented out the f_write, f_read, f_putc and f_getc functions. Am I missing something here? Please advise. Thanks in advance.

Regards,
Owais

owaisfazal wrote on Tuesday, September 16, 2014:

Okay so now the initialization is done and I get the same result as I was getting when I ran the sd_init independently. I have the same RCA and the capacity of the card is also correct. Now I am having trouble with

f_format( F_FAT32_MEDIA );

It returns F_ERR_ONDRIVE I cannot understand why is it so. Any suggestion in this regard? Although the card that I have inserted is already formatted with FAT32 FS do I need to go through the format procedure again or can I skip this and proceed to creating files? At this point I have taken a lot of code from AS example and placed it in the sd_mmc_read_block function which is equivalent to ram_readsector. I am not sure what is wrong. Also my function returns OK=1 at the end of execution could this create problems in the FreeRTOS+FAT SL? Please guide me how to proceed further.

Regards,
Owais

owaisfazal wrote on Tuesday, September 16, 2014:

turns out that the F_ERR_ONDRIVE was caused due to the reason that my sd_getphy function was returning OK=1 whereas in FreeRTOS+FAT SL it is expected to be

    MDRIVER_RAM_NO_ERROR=0

I changed my function according so now there is a new error

    F_ERR_MEDIATOOSMALL

I ran the debug and found out that it is coming from

    return _f_postformat( &phy, fattype );

Any suggestion in this regard.

Regards,
Owais

owaisfazal wrote on Tuesday, September 16, 2014:

okay now I have figured out why I was getting the following error

F_ERR_MEDIATOOSMALL

It turns out that the getphy function also returns the following

MDRIVER_RAM_NO_ERROR

I have changed it now and it doesn’t return the above error anymore. Now the situation is that since at some point in the following functions

f_initvolume(sd_init) 
f_format(F_FAT32_MEDIA)

The program runs the following functions

ram_readsector()
ram_writesector()

I have replaced these functions with my own functions specific for SD card. The read operation seem to be working fine as it does not generate any error whereas the write operation is making huge number of errors. I am not sure if this is a problem of my function or if the FreeRTOS+FAT SL is looking for something that I haven’t done. Any suggestions in this regard?

Regards,
Owais

zealhero wrote on Wednesday, September 17, 2014:

Hello Owais.
Your progress is similar to me.

  1. The Format problem
    It is same in my system. I fromatted my SD card on PC, but FAT SL say it is not formatted. It works well on the board if I format again using FAT SL. But it cannot read in PC. They are same FAT32 format… So I checked MBR, but I don’t know still what is reason. Please let me know if you find it. I posted it on this thread at 2014-07-11.

  2. It seems your reading function is working well. The errors occured from writing function are build error?

I think that your development way is correct… Actually my system is still not perfect, so I don’t know my idea is accurate. Please give me your opinion.

Regards.
Wonjae

owaisfazal wrote on Wednesday, September 17, 2014:

Hello Wonjae,

I have gone through your posts and read about the format problem but unfortunately I am far from there since I can only read the card at the moment but I am not sure how to make sure if the read function is working without any fault. I have just included some printfs in the read function to indicate any error but it seems to be working okay without any problem but i will be more sure once I can read something meaningful and display it somewhere. About the write function the problems are not related to build in fact they are related to actual transfer of data seems there are some errors while I read the Status Register I am not sure what the problem is. I am still looking into it maybe the write function that you have can help me in this regard can you please share your write function. It would be very helpful. Thanks.

Regards,
Owais

zealhero wrote on Wednesday, September 17, 2014:

Hello Owais,

I can’t guess what is reason of your writing fuction error. Is it works without file system?
My reading function and writing fucntions are same… the only difference is connecting to the own ‘reading’ or ‘writing’ fucntion…

Test your writing fucntion independently.

Regards.
Wonjae

owaisfazal wrote on Wednesday, September 17, 2014:

Hello Wonjae,

I am not sure either since I have used the same function as I am using for reading and just changed the command to Write single block and accordingly made adjustment in mode registers of the interface but still it is not clear where the problem is. Moreover I am thinking whether it is this simple to get it running, I mean if I add the write function that works will it ensure that everything else starts running smoothly like making a file and writing something into it and then reading it back again?

Thank you for your support so far it has helped me a lot.

Regards,
Owais

zealhero wrote on Wednesday, September 17, 2014:

In my opinion, it will be operated well automatically if you make a perfect initialization function. so check your functions independently first…

Regards,
Wonjae