eugene-tarassov / vivado-risc-v

Xilinx Vivado block designs for FPGA RISC-V SoC running Debian Linux distro
778 stars 180 forks source link

Issues related to SDC on the 512Bits AXI bus #202

Closed Ryan45758 closed 5 months ago

Ryan45758 commented 5 months ago

Hi, I want to apply your open source SD card controller to my homemade RISCV CPU.

My CPU specifications are as follows: Frequency: 60MHz CPU bus: AXI (512 bits) Memory: DDR4 2GB (AXI 512 bits, 300MHz)

In order to connect the SDC to the bus with a width of 512 bits, I added a datawidth downsizer 512 to 32 bits to the Slave, and a datawidth upsizer 32 to 512 bits to the Master.

Before burning Bitstream I used this SD card 1.0 simulation model to do a simple simulation. I connect it to the CPU, and the CPU initializes the SD card through C language (send CMD 0, 8, 55 41, 2, 3, 7, 55 6), and finally sends CMD24 and CMD17 to determine the written value and the read value, and the final result is correct.

However, the actual results are different from the simulated results. When I executed Bootrom.c in my homemade CPU, the error message "CANNOT MOUNT SD: NOT A VALID FAT VOLUME" will appear, and if I try to mount the SD on the Linux side The card will display "mmc0: unrecognised SCR structure version 10, error -22 whilst initializing SD card"

After actual testing on the FPGA, I found that the SD card controller can send commands to the SD card normally through the sd_cmd interface, and can also receive responses normally. However, the sd_dat interface seems to be unable to receive/send data normally. I printed out AXI m_axi_wdata and the result was 0. , I used ILA to analyze the sd_dat signal, and the value is also all 1 or all 0.

I would like to ask what the possible reasons are? Is it possible that the frequency of DDR4 and SD card controller is different? Or is it caused by improper setting of the clock divider value?

eugene-tarassov commented 5 months ago

Is it possible that the frequency of DDR4 and SD card controller is different?

SD card controller clock must be 100MHz. It is different from DDR 300MHz. Vivado is supposed to report error or critical warning if the clock is not 100MHz.

Ryan45758 commented 5 months ago

Is it possible that the frequency of DDR4 and SD card controller is different?

SD card controller clock must be 100MHz. It is different from DDR 300MHz. Vivado is supposed to report error or critical warning if the clock is not 100MHz.

So SD card controller 60MHz may cause the SD card to work abnormally? Can this be adjusted by setting the clock divider register?

eugene-tarassov commented 5 months ago

Theoretically, 60MHz should work, with reduced performance. 300MHz will not work.

Can this be adjusted by setting the clock divider register?

Max SD HS clock is 50MHz (100 / 2), you cannot get get 50 by dividing 60. But 60 / 2 = 30 should be OK, just not as fast.

Ryan45758 commented 5 months ago

Max SD HS clock is 50MHz (100 / 2), you cannot get get 50 by dividing 60. But 60 / 2 = 30 should be OK, just not as fast.

Thank you for your reply. My SD card controller has always been 60MHz instead of 300MHz, but it still doesn't work.

I found a problem. The problem is that my project currently does not set any Timing contraint for the SD card controller, and I saw that your project has set it. I would like to ask if not setting the Timing constraint may cause the communication with the SD card to fail?

eugene-tarassov commented 5 months ago

Yes, missing timing constraints almost always cause a design to fail.

Ryan45758 commented 5 months ago

Hello, I tried adding Constraint but it still doesn't work.

In addition, I want to try adding ACMD51 command in Bootrom.c to print out the SD scr register information, but the result will be this error CANNOT ACCESS SD: DATA CRC ERROR? (Before sending ACMD51, I have to send CMD55 first)

And I used a logic analyzer to see it, and it also showed CRC errors.

Here are the results received by my logic analyzer Send ACMD51: messageImage_1705666095163

Data response: messageImage_1705666141053

The following is the program I added in bootrom.c:

static int send_data_cmd(unsigned cmd, unsigned arg, void * buf, unsigned blocks) {
 ...
 switch (cmd) {
    ...
    case ACMD51:
        // R3
        command |= 1; // 48 bits
        command |= 1 << 3; // resp CRC
        break;
    ...
    }
if(cmd == ACMD51){
      if (blocks) {
            command |= 1 << 5;
            if ((intptr_t)buf & 3) {
                errno = ERR_BUF_ALIGNMENT;
                return -1;
            }
            regs->dma_addres = (uint64_t)(intptr_t)buf;
            regs->block_size = 8;
            regs->block_count = blocks - 1;
            regs->data_timeout = 0xFFFFFF;
        }

    }else{
      if (blocks) {
            command |= 1 << 5;
            if ((intptr_t)buf & 3) {
                errno = ERR_BUF_ALIGNMENT;
                return -1;
            }
            regs->dma_addres = (uint64_t)(intptr_t)buf;
            if(cmd == 17)
                printf("dma_address: %lx %lx\r\n", regs->dma_addres, (uint64_t)(intptr_t)buf);
            regs->block_size = 511;
            regs->block_count = blocks - 1;
            regs->data_timeout = 0xFFFFFF;
    }
...
}
eugene-tarassov commented 5 months ago

There is something wrong with the logic analyzer. In the data response, it shows single 64-bit message on SDIO_DAT, which is correct. But it interprets it as 2 16-bit messages, which is wrong. Because of this, it is hard say what is going on.

Ryan45758 commented 5 months ago

Hi, thank you very much for your help. The hardware part has been confirmed and there are no problems.

Then my Linux can successfully read the SD card after commenting out the C code that caused the error (reading the SCR register).

But I found a few strange problems, that is;

  1. Only can mount the SD card once. If unmount and then mount it again, an error will be reported.(The error message is as follows)
~ # [   92.938527] mmc0: host does not support reading read-only switch, assuming write-enable
[   92.985944] mmc0: new SDHC card at address b368
[   93.008678] mmcblk0: mmc0:b368 SMI   3.70 GiB
[   93.038144]  mmcblk0: p1

~ # mount /dev/mmcblk0p1 /mnt/

~ # umount /mnt/

~ # mount /dev/mmcblk0p1 /mnt/
[  118.125869] FAT-fs (mmcblk0p1): Volume was not properly unmounted. Some data may be corrupt. Please run fsck.

~ # mount /dev/mmcblk0p1 /mnt/
mount: mounting /dev/mmcblk0p1 on /mnt/ failed: Device or resource busy

~ # mount /dev/mmcblk0p1 /mnt
mount: mounting /dev/mmcblk0p1 on /mnt failed: No such device or address

Can you give me some debugging directions? Thanks.

eugene-tarassov commented 5 months ago

I don't know. It works fine for me:

root@debian:~# umount /dev/mmcblk0p1
root@debian:~# mount /dev/mmcblk0p1 /mnt/
root@debian:~# umount /mnt/
root@debian:~# mount /dev/mmcblk0p1 /mnt/
root@debian:~# umount /mnt/
root@debian:~#
Ryan45758 commented 5 months ago

Thank you. I'll give it a try on my own.

eugene-tarassov commented 5 months ago

Just a guess: in your implementation DMA bus is not cache-coherent. If so, you need to modify SD driver to flush/invalidate caches explicitly.

Ryan45758 commented 5 months ago

Just a guess: in your implementation DMA bus is not cache-coherent. If so, you need to modify SD driver to flush/invalidate caches explicitly.

The reason Bootrom.c cannot be mounted is indeed due to mapping to a non-coherent address base, but it is not the cause for the issue in Linux. I have specifically addressed this problem.

I noticed the "umount /dev/mmcblk0p1" in your log, and I suspect the issue might be because I only entered "umount /mnt" without specifying "umount /dev/mmcblk0p1," leading to filesystem corruption.

If I need to unmount the SD card, is it necessary to use "umount /dev/mmcblk0p1"?

eugene-tarassov commented 5 months ago

I did umount /dev/mmcblk0p1 because it was already mounted as /boot. Running umount /boot would do the same.