I've got a FatFS SDHC driver implemented that works well for single sector reads/writes.
I'm attempting to do multi-sector reads and am experiencing strange SDHC behavior.
As a test, I want to read 1024 bytes from a file -- so FatFS (after all its FAT and Directory reads) - issues a read for two (2) sectors from the wanted file.
My "Read Block" interface issues a CMD18 with a block count of 2 and AutoCMD12 enabled.
After I read 1024 bytes (256 dwords) the SDHC does NOT show TC (Transfer Complete) active. I have to perform another 128 dummy reads of the 512 buffer in order to get TC active.
I can't believe this is correct so I must be doing something wrong.
I need to understand this issue before I try to implement DMA .. since I can't do 128 dummy DMA reads.
I would appreciate any insight you might have on why the SDHC is requiring an additional read of the complete 512 buffer before it issues a TC.
Sorry for the delay. I resolved to using using pointers and not DMA because I can;t always control the destination address unless I want to copy from a good buff .. but that just consumes more time.
I had no issues using DMA for all commands.
The issue was using pointers (cpu gets data based on the use of a pointer), NOT DMA, and could not get the Multi-block read to function.
Since I have no explanation as to why the issue is occurring, I'm using single block read using pointers.
Thanks for replying.
Final post for my findings:
The timing above show a block read of 6 sectors -- or 1024 * 3 bytes == 3072 bytes.
That is a data rate of 3072 / 2.5 msec = 1,228,800 bytes/sec or 9,830,400 bits/sec.
I don't think I'm going to get much faster with a multi-block operation as most of the time is waiting on the SDHC to fill the buffer ... SO -- I going to stick with multi CMD17 commands.
I would still like to understand what is happening with the SDHC during CMD18 (multi-sector Read).
It works using DMA but not using pointer moves.
I can't go strictly with DMA because I can't always depend on FatFS providing a dword aligned buffer as described in his site.
I've not found a single reference to anyone getting this mode of operation to work.
Can anyone from NXP explain please?
Hi Joe Hinkle
Sorry for the late response. How is the status of your problem? Could you share your project (or the part that config SDHC) to check if I can replay your problem?
I made some tests in the KSDK 2.0 example and it works as it should, in my case It is configured with DmaModeNo, read 5 blocks of 512 and the flag TC is set. I attached that project, you could check it and it may help.
Have a great day.
Well - there was one positive coming out of all of this work.
After my last post, I pondered at the timing. I decided to look closer at how I was determining my baud settings.
I found a very big mistake .. all requested baud rates were producing setting of VERY VERY SLOW!!!
I redid my baud rate calculation and the timing is 10 times better now.
The closest I could get to 50Mhz was 40Mhz ... 120/3 is the closest ... wish it was faster.
So here is a SDHC clock at 40MHZ.
NOW -- complete 6 sector read is accomplished in 2.5 msec ... not the 220 msec reported earlier.
Also .. the only SDHC wait loop of any significance is waiting for the buffer to fill. That time is now 383 usec compared to 32 msec reported earlier ...may not even do a task switch for that amount of time.
Thought I'd share my head up my ass finding.
One more timing picture ... Again CPU running at 120Mhz and SDHC running at 50Mhz
When the bottom timing line is LO -- cpu is executing -- when HI -- simply in a wait loop waiting on SDHC
It takes 4 millsec for the SDHC to return from a CMD17 command (read one block).
My watermark is set at 128, so I wait for the SDHC to fill the complete 512 byte buffer. That simple wait loop is taking 32 millisecs.
From this, I can see how to implement task waiting from the RTOS and let other processes use that time. Come back when the SDHC interrupt fires.
Just thought I's share while I trying to figure out the multi-block issue.
I did a timing capture of a 6 sector block read.
Please Note -- SDHC is running at 50Mhz. Watermark is set at 512
The Top pulse shows the start/stop time of a loop of CMD17 commands --- 220 millisecs
The bottom small pulses show the actual time required to move the 512 bytes of data once it is in the SDHC's FIFO.
It also illustrates why the SDHC should be operated in association with a RTOS. 99.99% of the time, the cpu is waiting on the SDHC to finish it's task. Perfect use of a thread waiting on an interrupt event to occur.
It also illustrates WHY I want to resolve this CMD18 (Multi-Block) read issue -- to reduce amount of SDHC processing time.
Thanks for the comments Mark.
My application will be one application reading two files at the same time -- but interweaving the read process - so I don't have to "pause" a multi-block read.
I've spent the last 12 hours debugging multi-block reads -- here's what I found ... maybe someone can clarify.
CMD18 is set for AutoCmd12 and has block count set.
My code bails out of the read loop after I have read the specified number of blocks.
I've gone into a while(1) loop to debug SDHC register values after specific operations to see what is happening.
After acquiring the requested number of data blocks - the SDHC shows:
I am assuming that the SDHC has issued the AutoCMD12 as requested in the CMD18 command.
IRQSTAT - BRR (Buffer Read Ready) -- ok -- expected
PRSSTAT - RTA (Read Transfer Active), DLA (Data Line Active), CDIHB(Cmd Inhibit Data).
The PRSSTAT value suggests the block read is still active and the AutoCMD12 did not execute --- so I inserted my OWN CMD12 command --- results remain the same --- so I guess the AutoCMD12 DID execute and leaving the Card/SDHC in this state.
You are DEAD in this state as far any any more read/write operations go.
Investigating how to resolve this, I found the following:
From the K64 Reference Manual - Register XFERTYP - member CMDTYP:
Abort command (CMD12 or AutoCMD12) --- “After issuing the abort command, the host driver must issue a software reset (abort
Tried searching in the K64 manual for the definition of "software reset" and found none.
Researching the SD Card Interface specifications -- they state that after a CMD12 or AutoCMD12, that the software resets for Data and Cmd lines (found in SDHC Register SYSCTL) need to be activated.
So after I issue my own CMD12, I set the Data/Cmd software bits in SYSCTL.
IRQSTAT goes to 0
PRSSTAT now shows that the following clocks have been turned off as a result of the soft-reset: PEROFF (SDHC Clock), HCKOFF (System Clock), and IPGOFF (Bus Clock).
Still --- any READ attempt (CMD17) --- DEAD -- no IRQSTAT bits being set after the command is issued (IRQSTSTEN still has all the flags set -- so that's not he issue).
I suspected the issue may be that the clocks are off (the clocks are normally turned off depending on the state of the card/SDHC).
So I tested that theory ... I set flags PEREN, HCKEN, and IPGEN in register SYSCTL. This prevents the clocks from going off when the soft reset is applied.
Clocks are now ON -- Still DEAD on CMD17 read.
Tested clearing the flags PEREN, HCKEN, and IPGEN in register SYSCTL after the soft reset -- which puts me back where PRSSTAT shows clocks have been turned off again PEROFF (SDHC Clock), HCKOFF (System Clock), and IPGOFF (Bus Clock).
After all of this, the SD Card specifications suggest asking the card it's current state .. so I implemented CMD13.
CMD returns with the current state of the SD card as "tran" which is the "Tranfer State" -- so the card should be able to process my CMD17 command.
Again --- I issue a CMD17 and wait for IRQSTAT to show "Command Complete" or an error -- BUT -- IRQSTAT is always ZERO!!!!
There's the long and short of my investigation.
Can anyone share any insight as to why the SDHC will NOT set any IRQSTAT based on receiving CMD17 after I performed a soft reset as described above?
Thanks in advance for any HELP.
I've tried watermark of 1 and no change in timing.
These transfer numbers are terrible!!!!
There has got to be a way of getting CMD18 (multi-sector read) to generate a TC when the sectors have completed being read NOT using DMA.
If THAT could occur, the read performance would increase significantly. As it stands now ... I can issue a CMD18 and specify the number of sectors to read -- actually read all of the sectors -- but then I enter a wait looking for a TC that never occurs.
Any suggestions from anyone?
It is quite some time that I used multiple block transfers with the SDHC but my conclusion was that it is not reliable so I gave up on it in preference of 1-bit SPI for highest speed transfers based on on multiple-block operations.
I my case the issue was mainly that transfers could not be interrupted (imperative for systems with multiple SD card users - such as multiple HTTP and FTP servers needing to work at the same time with the card) which meant that it was not usable in real applications.
I figured I would post some test results. They surprised me!!
Micro - K64F running at 120mhz
SDHC - 4 bit mode at 25mhz
Sector size 512
Watermark -- both read and write set at 128 -- full SDHC FIFO.
Test were for processing 6 continuous sectors or (1024*3) bytes
T1. Read Buffer dword aligned (use SDHC DMA) - .2393 seconds for a read rate of 12,837 bytes/sec.
T2. Read Buffer dword mis-aligned (use dword *p to move data) - .2196 seconds for a read rate of 14,163 bytes/sec.
Note - for write test .. sectors already contained data.
T3. WriteBuffer dword aligned (use SDHC DMA) - .2436 seconds for a read rate of 12,610 bytes/sec.
T2. WriteBuffer dword mis-aligned (use dword *p to move data) - .2505 seconds for a read rate of 12,258 bytes/sec.
The read test were the same times obtained running multiple tests. The write tests had different times (I suspect do to card erasing time).
The interesting thing is that for read operations -- you get better results issuing multiple CMD17 commands and reading withe a C pointer compared to a single DMA read using CMD18. THAT WAS A SURPRISE!!!!
The tests were run with the system running FreeRtos -- but I made the test thread the highest priority to eliminate any RTOS related delays.
Again - these times were based on watermark lest of 128 which means no data was moved until the SDHC had completely processed the complete sector.
I'll have to look into smaller watermark levels to see if that impacts the timing.
Not finding an answer, I decided to test DMA.
DMA works great for multi-sector reads.
I look at the buffer address - check to make sure it is aligned on a 4 byte boundary. If it is, I use DMA. If NOT, I use data moves via a pointer.
It was the pointer moves in multi-sector operations where my issue occurs.
It looks like I will have to implement individual CMD17 (single sector reads) when I can't use DMA when asked to do a multi-sector operation. I hate that because it will kill performance.
Any comments appreciated.