I am writing a bare metal uSDHC driver for the iMX6Q based on the SDK version and am having an issue with reading (haven't tried writing yet). I can send commands to the SDHC card and get the proper responses back, so sending commands is not an issue. I believe the code for setting up for the read is also correct including the setup for the adma2. I'm using a CMD17 (read single block) to try to read the MBR (sector 0) of a known good (16GB) SDCARD using a known good OTS board from Boundary Devices. I initialize the read buffer (512 bytes) with the value 0x5a to detect what is read. This is what I get back (buffer starts at 0x104098a0):
The 55 aa at the end is correct and some of the 00 bytes may be as well. Since none of the bytes are 0x5a, 512 bytes were read from somewhere.
Below is what the data should be:
Here are the registers just before sending the command:
Below are the registers after the read (note that INT_STATUS has already been cleared):
In my setup I use three adma2 descriptors. The first one covers from the beginning of the buffer until the start of the first cache line. The read data is read into a separate uncached buffer (in DRAM), then copied into the real buffer. The second one is used to read in the rest of the data down to the last full 32 bytes (last full cache line). This data is read into physical memory, then the virtual memory is invalidated forcing the cache to be re-loaded. The third descriptor is used to read anything left over, and acts like the first one.
The adma2 descriptors are set up (in uncached DRAM) in this example such that, the buffer was started on a cache line so only two of the descriptor are used (third one not needed). There doesn’t appear to be any descriptor errors (AMDA_ERR_STATUS = 0), and the addresses of the 2 descriptors used are 0x184000C0, and 0x184000C8. The ADMA_SYS_ADDR reg shows 0x184000D0 which shows that the 2 descriptors used were executed. No errors are reported in the INT_STATUS reg.
It has the appearance of some kind of timing issue or data not ready, card can send data fast enough (@25MHz). Both CIHB and CDIHB are checked as you can see in the attached code.
Any ideas where to start looking for errors as to why the data is incorrect?
Hi,
I'm working on a bare-metal uSDHC driver (written in rust) for the i.MX8M Nano and seem to be hit a technical snag. I was wondering if you'd be open to sharing your implementation as a quick reference or provide some pointers on what I might be missing.
-Nihal
What problem are you having?
When my uSDHC driver issues an sd-command (anything apart from a CMD0), I get a response but it contains errors and decoding the contents of interrupt status register for details gives me
I have double-checked the implementation (many times) but I cant seem to figure out what I am missing.
A quick overview of my implementation:
Here is the full debug log
-Nihal
My first guess is your clock is too fast. During card identification, the card clock cannot exceed 400KHz. In my case I use 3.3V signaling and stick with cards not exceeding 64 GB. After card ID is done, the clock rate can be boosted to whatever (I use 50 MHz).
Send me a PM and I'll send you my driver.
During uSDHC initialization, I use an identification clock of 400Khz and a 3.3 volts setting. I'm currently testing an 8GB card.
Here is the list of steps in my initialization routine
For pinmux settings - I use the values from the imx8mn nano device-tree, as listed below
with some modifications.
The board I'm using has been in production several years so I think it's solid. I'm using the same pin settings that the company uses in their linux distro:
PAD_CTL_PUS_100K_PU |
PAD_CTL_ODE_DISABLED |
PAD_CTL_SPEED_MED |
PAD_CTL_DSE_38ohm |
PAD_CTL_HYS_ENABLED |
PAD_CTL_SRE_FAST;
I think the problem has to do more with the adma and/or cache issues. In the example above, the first adma descriptor is:
LEN: 32
ATT: 0x21
ADDR: 0x18400080 (uncached DRAM)
The second one is:
LEN: 480
ATTR: 0x23
ADDR: 0x104098C0
I don't flush the descriptors before the read because they are in uncached memory. My system is flat-mapped - virtual address = physical addr.
Right after the read, the 32 bytes in the uncached memory read all zeros (before the read all bytes were 0x5a) so something happened. After the read, the data from uncached memory is copied into the beginning of the data buffer (at 0x104098A0), then a dcache_invalidate is done over the part of the buffer in cached memory (starting at 0x1040_98C0) to update the virtual memory. However the data is already wrong at this point.
Don't know where to look for a solution.
>The board I'm using has been in production several years so I think it's solid.
in such case one can try the same test in verified (working) software : uboot or
linux. For ADMA there is ERR004536 erratum
Chip Errata for the i.MX 6Dual/6Quad and i.MX 6DualPlus/6QuadPlus - IMX6DQCE
Best regards
igor
Hi ogj
>Any ideas where to start looking for errors as to why the data is incorrect?
in general, it may be due to signal integrity issues as described for example on
https://community.nxp.com/t5/i-MX-Processors/eMMC-8GB-to-4GB-crash-on-linux-yocto-boot/m-p/373231
Best regards
igor