-
-
Notifications
You must be signed in to change notification settings - Fork 846
Question - help, porting an EMMC driver over to rust
#134
-
Hi,
Firstly, thank you for putting this repo together. Its been quite useful. I just wanted to check to see if someone's already solved this problem.
Context: I'm working on porting a SD/EMMC driver written in C
, managed to put together an initial implementation but I seem to have hit a roadblock. I assumed the rpi4 would have sufficient documentation but I guess not (at least when it comes to the onboard SD/EMMC controllers). Rpi4 has 3 of them usually referred to as
- SDHOST: this is accessible via GPIO pins but isn't connected to the onboard micro-SD slot.
- EMMC: accessible via GPIO pins but we cant use GPIO to connect to the on-board micro-SD slot. Although, this interface can be routed to the micro-SD slot via dedicated pins.
- EMMC2: is a new piece of IP (available on the rpi4) that doesn't appear on the GPIOs i.e. its the default MMC controller with dedicated pins connecting it to the micro-SD slot.
So, the port works so far in as I can
- get a stable clock, reset the EMMC controller etc.
- but fails when attempting to perform a full initialization
- more specifically, it fails when I issue a
CMD
to an SDcard in the on-board microSD slot. - I get a command timeout and command CRC error almost immediately.
For now I'm relying on print-f style
debugging; as I was hoping to avoid a full debugging workflow (i.e. JTAG and all), assuming this was going to be a straightforward port but it didn't quite turn out that way (I'm quite sure I'm missing something). So, I'm hoping someone here has more insight into the rpi
and its inner workings; if yes, would appreciate it if you provide some pointers on what I'm missing here.
Here's the output you should get when you compile and run the impl on real hardware (i.e. rpi4)
[ 0.001629] EMMC: reset card. [W 0.001984] EMMC_CONTROL1, from emmc_reset2: 0 [ 0.002550] EMMC: setting clock speed to 400000. [ 0.003124] Divisor = 105, Freq Set = 396825 [W 0.003653] EMMC_CONTROL1, from emmc_set_clock1: 944391 [W 0.004291] EMMC_CONTROL1::CLK_STABLE, from emmc_set_clock: 1 [W 0.005007] EMMC_CONTROL1, from emmc_set_clock2: 944391 [W 0.005657] from emmc_set_clock, set_clock_success [W 0.006242] from_emmc_reset_card, interrupt: 0x00000000 [W 0.006881] from_emmc_reset_card, interrupt_en: 0x00000000 [W 0.007552] from_emmc_reset_card, interrupt_mask: 0x00000000 [W 0.008246] from_emmc_reset_card, interrupt_en: 0x37ff7fff [W 0.008918] from_emmc_reset_card, interrupt_mask: 0x37ff7fff [W 0.009611] from_emmc_reset_card, interrupt: 0x00000140 [W 0.010250] from emmc_reset, just before emmc_send_command: [W 0.010933] from_emmc_send_command1, false [W 0.011432] from_emmc_send_command2 [W 0.011854] from emmc_wait_for_command, cmd_inhibit: false [W 0.012525] from emmc_wait_for_command1, interrupt: 0x00000140 [W 0.013239] from emmc_wait_for_command1, int_error_mask: 0x017e8000 [W 0.014009] from emmc_wait_for_command1, interrupt & mask: 0x00000000 [W 0.014800] from emmc_wait_for_command, cmd_inhibit: false [W 0.015471] from emmc_wait_for_command2, interrupt: 0x00000140 [W 0.016186] from emmc_wait_for_command2, int_error_mask: 0x017e8000 [W 0.016955] from emmc_wait_for_command2, interrupt & mask: 0x00000000 [W 0.017746] from_emmc_wait_for_command, td: 0 [ 0.018277] EMMC: Sending command, CMD_NAME: "GO_IDLE_STATE", CMD_CODE: 0x00000000, CMD_ARG: 0x00000000 [W 0.019448] from_emmc_send_command_p, interrupt: 0x00000100 [W 0.020130] from_emmc_send_command_p, before wait_for_interrupt [W 0.020867] from_emmc_wait_for_interrupt, interrupt_en: 0x37ff7fff [W 0.021625] from_emmc_wait_for_interrupt, interrupt_mask: 0x37ff7fff [W 0.022405] from_emmc_wait_for_interrupt, interrupt: 0x00038100 [W 0.023131] from_emmc_wait_for_interrupt, mask: 0x00000001, t_mask: 0x017e8001, int_error_mask: 0x017e8000 [W 0.024322] from_emmc_wait_for_interrupt, interrupt & t_mask: 0x00028000 [W 0.025146] from_emmc_wait_for_interrupt: td: 0 [W 0.025698] from_emmc_wait_for_interrupt, interrupt_en: 0x37ff7fff [W 0.026456] from_emmc_wait_for_interrupt, interrupt_mask: 0x37ff7fff [W 0.027236] from_emmc_wait_for_interrupt, ival: 0x00038100 [W 0.027908] from_emmc_wait_for_interrupt, ival & INT_CMD_TIMEOUT: 0x00010000 [W 0.028775] from_emmc_wait_for_interrupt, ival & INT_DATA_TIMEOUT: 0x00000000 [ 0.029653] EMMC: Wait for interrupt MASK: 0x00000001, STATUS: 0x000f0001, iVAL: 0x00038100, RESP0: 0x00000000 [W 0.030902] from emmc_reset, emmc_send_command resp: EMMC_TIMEOUT [ 0.031646] from emmc_init, emmc_reset_card: EMMC_TIMEOUT [ 0.032307] failed to initialize EMMC2 [ 0.032763] rpi4 version 0.1.0 [ 0.033129] Booting on: Raspberry Pi 4 [ 0.033584] Architectural timer resolution: 18 ns [ 0.034159] Drivers loaded: [ 0.034494] 1. BCM GPIO [ 0.034852] 2. BCM PL011 UART [ 0.035275] Chars written: 3287 [W 0.035656] wait duration smaller than architecturally supported, skipping [ 0.036499] waiting for 1 second [ 1.037147] read 20 blocks: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, .... .... .... 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [ 1.369945] waiting for 1 second
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 1
Replies: 2 comments
-
Forgot to mention, you can compile, build and extract the kernel
binary with a single command -
cargo xtask build rustBoot-only rpi4
which you can then drop onto an SD card.
Beta Was this translation helpful? Give feedback.
All reactions
-
So, I managed to fix it i.e. its working now. I switched to using the EMMC2.
A couple of changes to the original implementation. So basically, the card_reset
routine for the pi4 needed these changes.
- change base clock settings (to 50Mhz) and logic used to compute the clock divider value.
- while enabling interrupts and setting the interrupt mask, disable
CARD_INTERRUPT
(this one was quite important). - lastly, configure CONTROL0 to enable/set SD bus power (or VDD) to 3.3V.
and a few other minor details
Here's the output I get.
[ 0.000026] EMMC: reset card. [ 0.000141] Divisor = 63, Freq Set = 396825 [ 0.000571] EMMC: Sending command, CMD_NAME: "GO_IDLE_STATE", CMD_CODE: 0x00000000, CMD_ARG: 0x00000000 [ 0.001803] EMMC: Sending command, CMD_NAME: "SEND_IF_COND", CMD_CODE: 0x08020000, CMD_ARG: 0x000001aa [ 0.003032] EMMC: Sending command, CMD_NAME: "APP_CMD", CMD_CODE: 0x37000000, CMD_ARG: 0x00000000 [ 0.004078] EMMC: Sending command, CMD_NAME: "APP_SEND_OP_COND", CMD_CODE: 0x29020000, CMD_ARG: 0x50ff8000 [ 0.406173] EMMC: Sending command, CMD_NAME: "APP_CMD", CMD_CODE: 0x37000000, CMD_ARG: 0x00000000 [ 0.407028] EMMC: Sending command, CMD_NAME: "APP_SEND_OP_COND", CMD_CODE: 0x29020000, CMD_ARG: 0x00000000 [ 0.409122] EMMC: Sending command, CMD_NAME: "ALL_SEND_CID", CMD_CODE: 0x02010000, CMD_ARG: 0x00000000 [ 0.410182] EMMC: Sending command, CMD_NAME: "SEND_REL_ADDR", CMD_CODE: 0x03020000, CMD_ARG: 0x00000000 [ 0.411239] EMMC: Sending command, CMD_NAME: "SEND_CSD", CMD_CODE: 0x09010000, CMD_ARG: 0xaaaa0000 [ 0.412445] CSD Contents : 00 40 0e 00 32 5b 59 00 00ed c8 7f 80 0a 40 40 [ 0.413023] cemmc_structure=1, spec_vers=0, taac=0x0E, nsac=0x00, tran_speed=0x32,ccc=0x05B5, read_bl_len=0x09,read_bl_partial=0b, write_blk_misalign=0b,read_blk_misalign=0b, dsr_imp=0b, sector_size =0x7F, erase_blk_en=1b [ 0.415458] CSD 2.0: ver2_c_size = 0xEFFC card capacity: 31914459136 bytes or 31.91GiB [ 0.416433] wp_grp_size=0x0000000b wp_grp_enable=0b default_ecc=00b r2w_factor=010b write_bl_len=0x09write_bl_partial=0b file_format_grp=0 copy=1b perm_write_protect=0b tmp_write_protect=0bfile_format=0b ecc=00b [ 0.418765] Divisor = 1, Freq Set = 25000000 [ 0.419296] EMMC: Sending command, CMD_NAME: "CARD_SELECT", CMD_CODE: 0x07030000, CMD_ARG: 0xaaaa0000 [ 0.420443] EMMC: Sending command, CMD_NAME: "APP_CMD_RCA", CMD_CODE: 0x37020000, CMD_ARG: 0xaaaa0000 [ 0.421579] EMMC: Sending command, CMD_NAME: "SEND_SCR", CMD_CODE: 0x33220010, CMD_ARG: 0x00000000 [ 0.422857] EMMC: Sending command, CMD_NAME: "SET_BLOCKLEN", CMD_CODE: 0x10000000, CMD_ARG: 0x00000200 [ 0.423827] EMMC: SD Card Type 2 HC, 30436Mb, mfr_id: 3, 'SD:SD32G', r8.5, mfr_date: 1/2021, serial: 0x427f3942, RCA: 0xaaaa [ 0.424949] rpi4 version 0.1.0 [ 0.425315] Booting on: Raspberry Pi 4 [ 0.425771] Architectural timer resolution: 18 ns [ 0.426345] Drivers loaded: [ 0.426681] 1. BCM GPIO [ 0.427038] 2. BCM PL011 UART [ 0.427461] Chars written: 2442 [W 0.427842] wait duration smaller than architecturally supported, skipping [ 0.428685] waiting for 1 second [ 1.429077] waiting for 1 second [ 2.429149] waiting for 1 second [ 3.429215] waiting for 1 second
PS: I'm actually a bit surprised. I hope documentation for the raspberry-pi gets better (at least for its core-peripherals).
Beta Was this translation helpful? Give feedback.