Has anyone used the Shell_write_test command with an SD card or eMMC? In both cases I see problems when writing a 512 byte buffer. 512 bytes happens to be the sector size. The DLA bit in PRSSTAT is not clearing. I named the command "writetest" in my shell.
shell> writetest test
Test Iteration #8 Passed
Test Iteration #16 Passed
Test Iteration #32 Passed
Test Iteration #64 Passed
Test Iteration #128 Passed
Test Iteration #256 Passed
Test Iteration #512 Error, unable to open file to read
shell>
It seems that you found already known issue.
I suppose that you use append mode.
Unfortunately, append mode is implemented wrongly.
Problem with append mode appears when file size is multiply of cluster size. See also:
https://community.freescale.com/message/441854
As workaround, please use r+/w/w+ modes instead of append mode and seeks manually according your needs.
Next MQX release will contain complete redesigned MFS subsystem which will solve this issue.
I hope it helps you.
Have a great day,
RadekS
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Thanks for the prompt reply.
I took a look at the source code for Shell_write_test and it opens file in "w" mode. The bug may not be only with append mode.
Paul
I have done more investigation on this issue. It looks like the problem is in the sdcard/esdhc drivers. The problem happens on the first write to a new file. The buffer to write is 512 bytes. It is 1 block in the SD card. The driver issues a CMD24. In _esdhc_write() when the buffered CMD24 is finally sent to the device there is an ESDHC_LWEVENT_TRANSFER_ERROR. In the code below from _esdhc_write(), should line 5 be >= ?
if(_lwevent_get_signalled() & ESDHC_LWEVENT_TRANSFER_ERROR)
{
esdhc_ptr->SYSCTL |= SDHC_SYSCTL_RSTD_MASK;
if(esdhc_device_ptr->BUFFERED_CMD.BLOCKS > 1)
{
/* In this case the peripheral doesn't automatically send the CMD12, so MUST be sent manually */
ESDHC_COMMAND_STRUCT command;
command.COMMAND = ESDHC_CREATE_CMD(12, ESDHC_COMMAND_TYPE_NORMAL, ESDHC_COMMAND_RESPONSE_R1b, (ESDHC_COMMAND_NONE_FLAG));
command.ARGUMENT = 0;
command.BLOCKS = 0;
_esdhc_send_command(esdhc_device_ptr, &command, NULL);
/* Don't care about the result because the operation ends always by IO_ERROR. */
}
return IO_ERROR;
}
Paul
Thank you for your bug report.
I could confirm that writetest function has problem with write more than 511 bytes (511 works, 512 and more not work).
It has nothing to do with FAT sector size. The problem is the same even when sector size is 8196bytes.
It must be probably somehow connected to SD card block size.
Strange is that standard write function (Shell_write) doesn’t suffer by this issue. Till now I didn’t found root cause of this issue. I will report it.
Note: Your modification in esdhc.c file didn't help
Hi Radek,
Thank you for doing more investigation. I have new information to report today. I set a breakpoint in the _edshc_isr() function and I'm getting a DMA error when I try to write a single buffer of 512bytes. (See line 12 in code below.) 512 is the sector size of the device. It doesn't matter if the device is microSD or eMMC. (I have a board with microSD and another board with eMMC.) That tells me it's a K70 issue.
/*
DMA Error
Occurs when an Internal DMA transfer has failed. This bit is set to 1, when some error occurs in the data
transfer. This error can be caused by either Simple DMA or ADMA, depending on which DMA is in use.
The value in DMA System Address register is the next fetch address where the error occurs. Since any
error corrupts the whole data block, the host driver shall re-start the transfer from the corrupted block
boundary. The address of the block boundary can be calculated either from the current DSADDR value or
from the remaining number of blocks and the block size.
*/
if((esdhc_ptr->IRQSIGEN & SDHC_IRQSIGEN_DMAEIEN_MASK) && (sdhc_irqstat & SDHC_IRQSTAT_DMAE_MASK))
{
_lwevent_set( &esdhc_device_ptr->LWEVENT, ESDHC_LWEVENT_TRANSFER_ERROR);
}
Thanks,
Paul