Homebrew DSi Reverse Engineering: SD/MMC/SDIO Registers

nocash123

Well-Known Member
OP
Member
Joined
Aug 4, 2015
Messages
133
Trophies
0
XP
900
Country
Afghanistan
Tested the SOFT_RESET register. Clearing bit0 does force following settings (while - and as long as - Bit0=0):
Code:
  SD_STOP_INTERNAL_ACTION   = 0000h
  SD_RESPONSE0-7            = zerofilled
  SD_IRQ_STATUS0-1          = all IRQs flags acknowledged
  SD_CARD_CLK_CTL           = bit 8 and 10 cleared
  SD_CARD_OPTION            = 40EEh
  SD_CARD_INTERRUPT_CONTROL = 0000h
All other registers seem to be left unaffected (including the the extra IRQ flags in 4004900h); though there may be some further hidden effects (like
aborting transfers or resetting internal registers).
The other bits in SOFT_RESET seem to be unused/fixed/read-only: bit3-15 always cleared, and bit1-2 always set. Although, confusingly, the DSi firmware does issue reset by toggling both bit0 and bit1, although (trying to) clear bit1 bit doesn't seem to have any effect at all.

And, tested inserting/removing an EMPTY microSD adaptor (without a microSD card in it). IRQ_STATUS bit3,4,5 are behaving the same way as when inserting/removing a normal SD card. So those status bits must be soley relying on the card-detect switch (without checking any voltages on the SD Card pins).
Well, not too spectacular news - one might have more or less expected that anyways. Only the name "SIGSTATE" for bit5 was quite confusing (some signal? a signature? what?). But now it's confirmed to be just meaning the current state of the card-detect switch.
 

nocash123

Well-Known Member
OP
Member
Joined
Aug 4, 2015
Messages
133
Trophies
0
XP
900
Country
Afghanistan
Tested writing FFFFh to the lower & upper 16 bits of the IRQ_STATUS register: Nothing happened. There isn't any undocumented bit in that register that would clear all other status bits when writing "1" to it (at least not on DSi, the 3DS might work somehow differently).

Also tested writing FFFFh to lower & upper 16bits of the IRQ_MASK register (also tried repeatedly toggling them between 0000h and FFFFh). Toshiba datasheets claimed that setting MASK bits would clear STATUS bits (which wouldn't really be a desired effect). But, nothing happened there, too. The status bits stayed intact. Either the old Toshiba datasheets are wrong, or the DSi uses a newer (better) interrupt scheme.

I've been trying to trigger the "sdio" interrupt by GNDing the SD slot pins. But couldn't find anything. None of the 4004800h..40049FFh registers seem to have changed, and the "async" IF2 bits didn't change either. Also tried to enable the irq by setting/clearing all bits in the 4004800h..40049FFh range (except, without clearing SOFT_RESET, of course). And setting/clearing the unknown registers at 4004C04..4004C05. Nothing :- /
Anyways, the Atheros wifi unit should/does probably use SDIO irq's, so maybe reversing the wifi unit will put some more light on it, someday.

But, while GNDing pins, it turned out that "SIGSTATE_A" is also belonging to the SD Slot (not to the onboard eMMC). It's indicating the state of the Data3 ("card detect") pin. Unlike the card detect switch, that signal would even work when ejecting/inserting microSD cards into microSD adaptors. That is, it would work if it would work. As far as I can see the signal is always 1=High, no matter if a cartridge is inserted or not (unless there would be a way to disable internal pull-ups in the DSi via some 40048xxh port; I couldn't find any such feature though).

Anyways, forcefully GNDing the pin is working, and also triggers the correspondig "insert/eject" irq flags:
Code:
  8   undoc undoc CARD_REMOVE_A (0=No event, 1=High-to-Low occurred)   ;\SD
  9   undoc undoc CARD_INSERT_A (0=No event, 1=Low-to-High óccurred)   ; Slot
  10  undoc 0     SIGSTATE_A    (usually 1=High) ;also as so for SDIO  ;/Data3
That's working even in 4bit data mode, but seems to be disabled during data transfers: During data transfers, the traffic on data3 pin doesn't trigger the insert/remove IRQs in bit8/9. And bit10 should be (ideally/hopefully) kept frozen at its most recent value.
 
Last edited by nocash123,

nocash123

Well-Known Member
OP
Member
Joined
Aug 4, 2015
Messages
133
Trophies
0
XP
900
Country
Afghanistan
Got the CARD_CLK_CTL register reversed. The CLK pin is pulsed even when no SD card is attached, so I could do scope tests even without those nasty microSD adaptors around, but it's been a painful process with sudokuhax prompting to remove the test cable and insert an sd card after each and every failed dslink wifi upload.
HCLK is really 33MHz, and clk dividers are /2 through /512 as described in the toshiba datasheet. The weird clock change procedure in the datasheet doesn't seem to be required. The firmware contains some code that simply writes the divider alongsides with bit8=1 for clock enable (looks as if it's done after detecting the supported clk rate via CSD register) (in other cases, eg. for SDIO init, clock is stopped via bit8=0 before/while changing the clk divider, don't know if that's required, but maybe that method is a bit more stable).
The other bits are bit15-11 unused (no hclk divider-disable, unlike as in datasheet), bit10=unknown (doesn't seem to affect the clk), bit9=unknown (seems to freeze the clock, similar as when trying to set more than 1 bit in the divider field at bit7-0), bit8=0 stops the clock and forces.output LOW, this should be done when not accessing SD/MMC (probably for reducing power consumption).

I've been trying an first attempt to make a clean I/O map for the SD/MMC registers (see http://dsibrew.org/wiki/SD/MMC/SDIO_Registers). With the fixed registers from the "sdmmc_fixed_values" list marked as such, it's actually looking quite nice: Turns out that there aren't too many unknown registers (apart from those seemingly fixed values). Of course, there are still plenty of bits with unknown function, even in the "known" registers.

Also updated all register descriptions on the wiki page (reflecting the new findings from past some days).
Plus marking read/write-ability of all bits as (R/W), (R), (W); as far as known, most other bits are probably always zero, though may be a few more (R) or (W) bits hiding here and there.
Plus some cosmetic changes on the chapter headlines, especially dropping separate headlines for SDIO registers as it turned out that they are just identical to the SD/MMC registers (unlike as described in the old datasheets) (exceptions are 4004A02h and 4004AF8h/4004AFAh which do differ an SDIO side).
Stuff that's still missing on the wiki page are the flowcharts for handling IRQ bits in data transfers.
 

nocash123

Well-Known Member
OP
Member
Joined
Aug 4, 2015
Messages
133
Trophies
0
XP
900
Country
Afghanistan
Found a couple of ways to provoke error bits in ERROR_DETAIL_STATUS getting set: Bit8=1 when programming the controller to expect GET_STATUS to return a 136bit response. Bit16=1 when sending GET_CID in "tran" state. Bit20=1 when sending GET_STATUS configured to expect a data/read reply. Bit21=1 when sending GET_STATUS configured to expect a data/write block (and with actually sending a data block to it).

Neither reading nor writing ERROR_DETAIL_STATUS nor IRQ_STATUS does acknowledge error bits. Instead, the error bits are cleared automatically when sending a new command (by writing to SD_CMD register). SOFT_RESET does also acknowledge the error bits. In both cases, the exception is bit13 which is kept "always 1".

Alongsides, I've also rev-engineered the SD_CMD register: Response Type=0 selects "Auto". That is, the controller does automatically pick the correct response type for the written command number (and also the correct data type; ie. bit11-13 are ignored (should be zero) when using "Auto". The DSi firmware seems to be using "Auto" for everything - except SDIO commands. There might be also some subtle differences between some SD and MMC commands, so "Auto" won't work in such cases (unless the controller can be switched into "SD-or-MMC mode" via some configuration bit).
Still don't know what SD_CMD bit14-15 are doing, both are R/W so they should have some function. Bit14 is set for SDIO commands, but no idea what it is doing.
Is there some difference between SD/MMC and SDIO signal transmission protocols?

Timeouts are counted in SDCLK units (the CLK-Pin rate selected in SD_CARD_CLK_CTL register). For Response-Timeouts, the timeout is fixed: Around 290h SDCLK's (preceeded by 30h SDCLK's for sending the command). For Data-Timeouts, the timeout can be selected in SD_CARD_OPTION.bit4-7, which is apparently what toshiba tried to describe as "RTO" bits. Values 0..14 select timeout "2000h SHL 0..14 SDCLK's" and value 15 selects "100h SDCLK's" (that, oddly, resulting in Data-timeout getting triggered before Response-timeout, which is rather nonsense since it's opposite of the actual transfer order).

For data/read, the timeout starts counting after transferring Command+Response. For data/write it starts after transferring Command+Response+DataBlock. The maximum duration for data timeouts (with RTO=14) would be around 8 seconds (at SDCLK=HCLK/2), or up to about 30 minutes (at HCLK/512).
One odd effect is that Response-Timeouts can occur (after 290h SDCLKs, and recursing the selected SDCLK=HCLK/n rate) even if SDCLK is stopped via SD_CARD_CLK_CTL.Bit8 (ie. the selected clock is kept running internally, and only the CLK-Pin output is forced LOW when Bit8=0).

Oh, and when provoking the data-write-timeout, it happened that IRQ_STATUS.bit23 got cleared (spotted after writing the data block). So, whatever happened there, bit23 isn't always set. Don't know if it's also getting cleared in "normal" data-write situations, or if it's happening only in combination with "timeouts" (eg. such like maybe when write fifo is full, without (yet) being able to forward its content to the memory card).
 
Last edited by nocash123,

nocash123

Well-Known Member
OP
Member
Joined
Aug 4, 2015
Messages
133
Trophies
0
XP
900
Country
Afghanistan
Created a list of fixed bits. Allowing to verify supposedly unused/constant values in registers that contain both fixed & variable bits mixed together.
Code:
sdmmc_fixed_bit_list:
 ;---addr // can_be_nonzero, always_set
 dd 40048D8h // dw 01032h, 01010h  ;DATA_CTL
 dd 4004826h // dw 003ffh, 00000h  ;BLOCK_LEN16
 dd 4004904h // dw 003ffh, 00000h  ;BLOCK_LEN32
 dd 400481Ch // dw 007bdh, 00000h  ;IRQ_STATUS_LO
 dd 400481Eh // dw 0ebffh, 00000h  ;IRQ_STATUS_HI
 dd 4004820h // dw 0031dh, 00000h  ;IRQ_MASK_LO
 dd 4004822h // dw 08b7fh, 00000h  ;IRQ_MASK_HI
 dd 4004900h // dw 01b02h, 00000h  ;IRQ32
 dd 400482Ch // dw 02fffh, 02000h  ;ERROR_DETAIL_LO
 dd 400482Eh // dw 00073h, 00000h  ;ERROR_DETAIL_HI
 dd 4004802h // dw 0020fh, 00200h  ;CARD_PORT_SELECT  ;bit8/9 unlike SDIO
 dd 4004828h // dw 0c0ffh, 04000h  ;CARD_OPTION
 dd 4004824h // dw 007ffh, 00000h  ;CARD_CLK_CTL
 dd 4004808h // dw 00101h, 00000h  ;STOP_INTERNAL_ACTION
 dd 40048E0h // dw 00007h, 00006h  ;SOFT_RESET
 dd 40048F6h // dw 00000h, 00000h  ;always 0, but... firmware tests bit0?
 dd 4004836h // dw 00002h, 00000h  ;CARD_INTERRUPT_CONTROL  ;used by SDIO
 dd 4004838h // dw 0c007h, 00000h  ;CLK_AND_WAIT_CTL        ;used by SDIO
 dd 4004834h // dw 00305h, 00000h  ;TRANSACTION_CTL
 dd 40048F2h // dw 00003h, 00000h  ;Can be 0003h
 dd 40048F4h // dw 00770h, 00000h  ;Can be 0770h
 dd 40048FAh // dw 00007h, 00000h  ;Can be 0004h..0007h  ;unlike SDIO
 dd 40048FCh // dw 000ffh, 00024h  ;Can be 0024h..00FFh
 dd 40048FEh // dw 000ffh, 00024h  ;Can be 0024h..00FFh
 ;sdio...
 dd 4004AD8h // dw 01032h, 01010h  ;DATA_CTL
 dd 4004A26h // dw 003ffh, 00000h  ;BLOCK_LEN16
 dd 4004B04h // dw 003ffh, 00000h  ;BLOCK_LEN32
 dd 4004A1Ch // dw 007bdh, 00000h  ;IRQ_STATUS_LO
 dd 4004A1Eh // dw 0ebffh, 00000h  ;IRQ_STATUS_HI
 dd 4004A20h // dw 0031dh, 00000h  ;IRQ_MASK_LO
 dd 4004A22h // dw 08b7fh, 00000h  ;IRQ_MASK_HI
 dd 4004B00h // dw 01b02h, 00000h  ;IRQ32
 dd 4004A2Ch // dw 02fffh, 02000h  ;ERROR_DETAIL_LO
 dd 4004A2Eh // dw 00073h, 00000h  ;ERROR_DETAIL_HI
 dd 4004A02h // dw 0010fh, 00100h  ;CARD_PORT_SELECT  ;bit8/9 unlike SD
 dd 4004A28h // dw 0c0ffh, 04000h  ;CARD_OPTION
 dd 4004A24h // dw 007ffh, 00000h  ;CARD_CLK_CTL
 dd 4004A08h // dw 00101h, 00000h  ;STOP_INTERNAL_ACTION
 dd 4004AE0h // dw 00007h, 00006h  ;SOFT_RESET
 dd 4004AF6h // dw 00000h, 00000h  ;always 0, but... firmware tests bit0?
 dd 4004A36h // dw 00002h, 00000h  ;CARD_INTERRUPT_CONTROL  ;used by SDIO
 dd 4004A38h // dw 0c007h, 00000h  ;CLK_AND_WAIT_CTL        ;used by SDIO
 dd 4004A34h // dw 00305h, 00000h  ;TRANSACTION_CTL
 dd 4004AF2h // dw 00003h, 00000h  ;Can be 0003h
 dd 4004AF4h // dw 00770h, 00000h  ;Can be 0770h
;dd 4004AFAh // dw 00000h, 00000h  ;zero (unlike SD)
 dd 4004AFCh // dw 000ffh, 00024h  ;Can be 0024h..00FFh
 dd 4004AFEh // dw 000ffh, 00024h  ;Can be 0024h..00FFh
 dd 0  ;end of list
Example code for verifying the fixed bits...
Code:
 ldr  r4,=sdmmc_fixed_bit_list          ;\
@@verify_fixbit_lop:                    ;
 ldr  r5,[r4],4  ;address               ;
 ldrh r6,[r4],2  ;can_be_nonzero        ;
 ldrh r7,[r4],2  ;always_nonzero        ; verify fixed bits
 ldrh r8,[r5]    ;[address]             ; (within registers with variable bits)
 bics r0,r8,r6   ;strip can_be_nonzero  ;
 bne  @@verify_fixbit_bad   ;want zero  ;
 and  r0,r8,r7   ;isolate always_nonzero;
 cmp  r0,r7      ;verify always_nonzero ;
 bne  @@verify_fixbit_bad  ;want nonzero;
 b    @@verify_fixbit_inner_okay        ;
@@verify_fixbit_bad:                    ;
 bl   wrcrlf                            ;
 ldr  r1,=txt_fixbit_mismatch           ;
 bl   wrstr                             ;
 mov  r0,r5      ;address               ;
 bl   wrhex32bit                        ;
 bl   wrspc                             ;
 mov  r0,r8      ;value                 ;
 bl   wrhex16bit                        ;
 bl   wrspc                             ;
 bl   wrcrlf                            ;
@@verify_fixbit_inner_okay:             ;
 ldr  r0,[r4]    ;address               ;
 cmp  r0,0       ;end of list           ;
 bne  @@verify_fixbit_lop               ;/
First finding is that 40048FAh.bit2 can be zero (happens somewhere during data/read, spotted somewhere between RESPEND and RXRDY).

I haven't repeated all tests from last week with the new fixed-bit checks. If anybody uses software with SD/MMC access on DSi or 3DS, please add the above fixed-bit verifification (and the older fixed-register verification from http://gbatemp.net/threads/dsi-reverse-engineering-sd-mmc-sdio-registers.395787/#post-5640698) to your sd/mmc code in as many places as possible. That should be very easy to do, and will help to find out if any of the fixed bits/registers are changing in whatever situations.

Btw. does anybody know a "Programming and Reverse Engineering" forum for NDS, and especially for DSi? Or would like to create such a forum if there's none? Posting that kind of stuff in "Emulation and Homebrew" feels a bit like getting nude in front of other people in the wrong place (fortunately, nobody complained yet). It would be just nice to have a place to discuss technical stuff. That kind of forums & communities exist for NES, SNES, CPC, ZX81, PSX and various "retro" systems, but not for newer consoles. Which is a pity because modern consoles like DSi couldn't be possibly programmed or reverse engineered without discussing their hardware and firmware with other people.
 

I pwned U!

I am pleased to beat you!
Member
Joined
Jun 14, 2013
Messages
927
Trophies
3
Age
28
Website
gbatemp.net
XP
680
Country
United States
Btw. does anybody know a "Programming and Reverse Engineering" forum for NDS, and especially for DSi? Or would like to create such a forum if there's none? Posting that kind of stuff in "Emulation and Homebrew" feels a bit like getting nude in front of other people in the wrong place (fortunately, nobody complained yet). It would be just nice to have a place to discuss technical stuff. That kind of forums & communities exist for NES, SNES, CPC, ZX81, PSX and various "retro" systems, but not for newer consoles. Which is a pity because modern consoles like DSi couldn't be possibly programmed or reverse engineered without discussing their hardware and firmware with other people.
Due to these recent DSi developments and differences in hardware from the DS, many users here (myself included) would like a DSi section on GBATemp, but so far, the only member of the GBATemp staff to comment on the matter does not seem too keen on it.

Also, I immensely appreciate all of the DSi reverse engineering that you have accomplished. The revival of the DSi scene would not have been possible with your extremely hard work and incredible determination. You seem to have accomplished more for the DSi scene in one year than other well-known DSi reverse engineers have in the five years prior to your developments!
 

nocash123

Well-Known Member
OP
Member
Joined
Aug 4, 2015
Messages
133
Trophies
0
XP
900
Country
Afghanistan
Thanks for the feedback :- ) and thanks for pointing out that there's a thread about suggesting a Nintendo DSi section. Somebody seems to have just added voting to that thread. If you (don't) a want DSi section: Click here http://gbatemp.net/threads/nintendo-dsi-section.393580/ and vote yes/no.

Current news: Tested writing some kilobytes of data to the sd/mmc DATA16 and DATA32 registers (without actually sending any commands, so the data just stays in the fifo without transfer to sd/mmc card). Turned out that there actually several fifos in the console:
- DATA16 has two FIFOs, each with a capacity of 200h bytes
- DATA32 has at least one FIFO, with a capacity of 200h bytes

The two DATA16 fifos are apparently swapped after each transfer, so the CPU can access one FIFO, simultaneously with the sd/mmc card accessing the other FIFO.
Writing some kbytes to DATA16 resulted in the first 200h bytes being stored in the first FIFO (let's call it FIFO_A), and the last 200h bytes being stored in the other FIFO (FIFO_B), ie. once when FIFO_A was filled, all further writes seem to have been written (and overwritten) to FIFO_B.
After filling the FIFO's, reading returned the content of FIFO_B, reading beyond end of FIFO_B wrapped to FIFO_A (and stayed wrapping within FIFO_A on further reads).
SOFT_RESET is also having some effect on the DATA16 fifos: It's resetting the read pointer to 'First halfword of FIFO_A'. And, during softreset, reading from the FIFO is disabled (trying to read from it does just return 0000h, even if the two FIFO's do contain only nonzero values) (softreset doesn't change or zerofill the FIFO content though; the old content is getting accessible again once when releasing softreset).

The DATA32 can FIFO can hold another 200h bytes, this seems to be some patchwork for supporting 32bit DMA's an a chip that was originally designed to support only 16bit access (it would have been more elegant to add 32bit support to the existing two FIFOs, instead of coming up with the extra DATA32 FIFO). During actual memory card transfers, the 32bit FIFO is probably copied to/from one of the 16bit FIFOs (if so, then the FIFO32 data should be visible in FIFO16; but that's still to be tested).
Writing some kbytes to FIFO32 results in the first 200h bytes being stored in the 32bit FIFO (the remaining written bytes seem to be lost; unless there's a second 32bit FIFO state, but I haven't found anything hinting in that direction, and a second FIFO wouldn't be too useful in this place). After doing writing: Reading returns those first 200h bytes, and further reads are then stuck on returning the last word (ie. byte number 1FCh..1FFh). I've tried softreset and some other potention "fifo-clear" bits, but haven't yet found anything that would release the 32bit FIFO from being "stuck on last word".

The capacity for the 16bit & 32bit FIFOs depends on the corresponding BLK_LEN registers. Default size (and maximum size) would be 200h bytes, but when using smaller BLK_LEN settings, then the FIFOs are getting smaller accordingly (ie. switching from FIFO_A to FIFO_B occurs after writing less than 200h bytes, and reading from 32bit FIFO gets stuck after less than 200h bytes). The BLK_LEN registers are a bit complicated (when writing 'invalid' values to them):
DATA16_BLK_LEN can be set to 0..200h (trying to write 201h..3FFh will be automatically changed to 200h, ie. when reading BLK_LEN you'll see 200h instead of the written value). Of that possible settings, values 1..200h are working as planned (and for 16bit access, they are rounded-up to multiples of two bytes, although the for the serial bus, the hardware should use the actual length without rounding). The special case is 0, which seems to act same as 200h (at least concerning reading/writing the FIFO register; don't know what happens on the serial bus when using BLK_LEN=0).
DATA32_BLK_LEN can be set to 0..3FFh (reading BLK_LEN returns that values unchanged). But internally, the values are saturated to min 1 word, and max 80h words (ie. 4..200h bytes, or maybe 1..200h bytes) (for 32bit access, the values are rounded-up to multiples of 4 bytes, but don't know if that rounding is also applied to the serial transfer length; it shouldn't be rounded, but maybe they didn't care if FIFO32 was intended only for bigger data blocks).

And, one more thing about DATA32 mode: The firmware seems to be writing the first data block to the 32bit FIFO before even sending the WRITE_MULTIPLE command via SD_CMD register. Don't know why the firmware is doing that though, it would be more efficient to send the data after the SD_CMD write (so the FIFO could be filled while the command & response are being transferred via serial bus). Normmatt seems to have gotten data writes working without that data-before-command ordering.
The only case where data-before-command might be useful & efficient would be sending the data before the previous WRITE_MULTIPLE (and GET_STATUS) commands have finished. That would allow to write multiple clusters without losing speed at cluster boundaries. Only, error handling might be a nightmare: Sensing possible write errors at a time when there's already data for the next write in the FIFO - such a thing should be implemented only if you know what you are doing (and ideally, also have a way to test errors, using worn out memory cards, or some special hardware that can automatically generate errors for testing).
 
Last edited by nocash123,

nocash123

Well-Known Member
OP
Member
Joined
Aug 4, 2015
Messages
133
Trophies
0
XP
900
Country
Afghanistan
#ifdef DATA32_SUPPORT
if(!(ctl32 & 0x200))
Ehm... starting the transfer when the IRQ flag is not set? That would be a funny design decision, if it's really supposed to be handled that way.
You are right, you are right, 4004900h.Bit9 is actually 0=IRQ (unlike 4004900h.Bit8 and unlike the IRQ_STATUS bits in 400481Ch). So, DATA32_IRQ should look like so:
Code:
4004900h/4004B00h - SD_DATA32_IRQ
  15-13  Unknown/unused (appears to be always zero)
  12     DATA32_TX32RQ IRQ Enable   (0=Disable, 1=Enable)                  (R/W)
  11     DATA32_RX32RDY IRQ Enable  (0=Disable, 1=Enable)                  (R/W)
  10     DATA32 Abort/Flush FIFO? (0=No change, 1=Clear Bit8,9)            (W)
  9      DATA32_TX32RQ IRQ Flag     (0=IRQ, 1=No) (0=TX FIFO Empty)        (R)
  8      DATA32_RX32RDY IRQ Flag    (0=No, 1=IRQ) (1=RX FIFO Full)         (R)
  7-2    Unknown/unused (appears to be always zero)
  1      Select 16bit/32bit Data Mode (0=DATA16, 1=DATA32, see 40048D8h)   (R/W)
  0      Unknown/unused (appears to be always zero)

One nasty "feature" for both IRQ_STATUS and DATA32_IRQ is that the interrupts are edge-triggered (IF2.bit8 gets set only on No-IRQ-to-IRQ transitions) (IF2 can be acknowledged even if IRQ(s) are still requested, which would mean that those IRQ(s) would get lost). Workaround would be:
- first acknowledge IF2.bit8 (must be done before next step)
- then check for pending IRQs in IRQ_STATUS and DATA32_IRQ, and process all of them
Ie. if you would process only a single IRQ, then any other IRQs would get lost.

For IRQ_STATUS you could also force unprocessed IRQs to re-trigger IF2 by temporarily disabling IRQ_MASK bits (disable-to-enable for pending IRQs is also edge-triggering IF2). That trick works for IRQ_STATUS only, not for DATA32_IRQ.

Also observe that TX32RQ is set any time when FIFO32 is empty, ie. TX32RQ gets set even after sending the last block (in that case TX32RQ shouldn't be treated as transfer request; ie. when using TX32RQ you must keep track if you've already transferred all blocks) (unlike as in data16 mode, where TXRQ doesn't get set after last block).

Also checked if the 16bit FIFO content after doing a data-write via 32bit FIFO. The result is that the 32bit FIFO data showed up in 16bit FIFO after the transfer. FIFO block diagram should be thus looking as so:
Code:
                  .--------.
               o--| FIFO_A |--o             o---------------- 4004830h CPU
  serial          '--------'   \
  SD/MMC  ---o                  o---------o
  bus         \   .--------.               \    .--------.
               o--| FIFO_B |--o             o---| FIFO32 |--- 400490Ch CPU/NDMA
                  '--------'                    '--------'
Another small detail: I've spotted a case when IRQ_STATUS.bit30 (CMDBUSY) got cleared shortly before IRQ_STATUS.bit29 (CMDREADY) got set. So that bits aren't always the exact inverse of each other.
 

duke_srg

Well-Known Member
Member
Joined
Mar 1, 2011
Messages
1,862
Trophies
0
Age
44
Location
Moscow
XP
807
Country
Serbia, Republic of
Refactoring Normmatt's driver for 3DS, which was rewritted by 173210 before to support IRQ.
Noticed that original driver (used by most 3DS CFW's now) are using CLK/4 devider. And tried with CLK/2, for sure got almost twice speed boost. But with several cads under several conditions fails with underrun error. And I'm actually can't find how to reset the card itself (well, the SD card specification have excluded underrun flag comparing to the MMC specification). Even reinitializing controller and SD card (and NAND eMMC too) works fine in normal conditions, in hangs after read operation fails with underrun.
 

nocash123

Well-Known Member
OP
Member
Joined
Aug 4, 2015
Messages
133
Trophies
0
XP
900
Country
Afghanistan
The official way should be something like this: Start with some slow CLK, read CSD register and check the TRAN_SPEED bits, and then set the CLK to the highest possible/supported value.

I am not all that sure if/when/why that's required - according to SD card specs it's "mandatory" for all SD cards to support 25MHz, and the DSi supports max 16MHz, so there should be no problem at all (or is 3DS different?). Well, or maybe I am misreading the specs (they are saying 25MHz is "mandatory maximum", whatever that means: either all cards must support at least 25MHz... or cards are never allowed to support more than 25MHz...?).

But as you said you get "underrun" errors, that sounds more like some software problem... like not feeding data to TXFIFO fast enough? I think normally you should store the whole data (for a 512 byte sector) in the DATA32 FIFO before issuing the write command.
 

duke_srg

Well-Known Member
Member
Joined
Mar 1, 2011
Messages
1,862
Trophies
0
Age
44
Location
Moscow
XP
807
Country
Serbia, Republic of
SD specs said TANS_SPEED must be either 32h for 25MHz (or higher for HIGH SPEED 50MHz mode). MMC specs have definition to calculate the optimal clock for the card based on TRANS_SPEED and NSAC, TAAC, R2W_FACTOR and also there is a note in MMC specification that is up to the application to choose the higher frequency or lower underrun probability, so it is implied that underruns must be handled anyway. SD spec have no underrun flag defined (its bit is marked reservd) and even optimal clock calculation is not really applicable since looks like NSAS is always zero.
And CLK/2 looks like very similar to DSi maximum clocking, since my own card works with a bit below 7mbs total transfer.

The actual error is identified by TXUNDERRUN and RCRCE both set. So it is a read CRC error caused by internal sdcard underrun IMO.
Yes, I tried to make the whole reintialization routine including downclocking, but did not help.
Unfortunately I personally dont have such card, my works with no issues, but this is not an excuse and not a reason to abandon the highest possible speed.
 

nocash123

Well-Known Member
OP
Member
Joined
Aug 4, 2015
Messages
133
Trophies
0
XP
900
Country
Afghanistan
Do you know the CID and CSD values for the non-working SD card? Or better: Ask somebody to donate one of that cards to you, maybe you are lucky, since even new SD cards are dirt cheap (and old SD cards are probably even cheaper... but harder to find).

I think for the CLK, only TRAN_SPEED should be relevant (as far as I understand, the NSAC/TAAC and R2W_FACTOR values seem to define only extra delays that can occur before/after reading/writing the data blocks; for such delays it might be required to configure the timeout settings).

Did you disable the pull-up via SET_CLR_CARD_DETECT? Maybe not doing so could cause problems at higher transfer speeds.

Yeah, RCRCE sounds like some hardware/timing/configuration problem. For TXUNDERRUN, I don't really know what it means, the TX sounds like writing, but I think it does actually meant to occur upon reading problems. Btw. when getting errors, are you reading or writing the SD card? Or both?
 

duke_srg

Well-Known Member
Member
Joined
Mar 1, 2011
Messages
1,862
Trophies
0
Age
44
Location
Moscow
XP
807
Country
Serbia, Republic of
Do you know the CID and CSD values for the non-working SD card? Or better: Ask somebody to donate one of that cards to you, maybe you are lucky, since even new SD cards are dirt cheap (and old SD cards are probably even cheaper... but harder to find).

I think for the CLK, only TRAN_SPEED should be relevant (as far as I understand, the NSAC/TAAC and R2W_FACTOR values seem to define only extra delays that can occur before/after reading/writing the data blocks; for such delays it might be required to configure the timeout settings).

Did you disable the pull-up via SET_CLR_CARD_DETECT? Maybe not doing so could cause problems at higher transfer speeds.

Yeah, RCRCE sounds like some hardware/timing/configuration problem. For TXUNDERRUN, I don't really know what it means, the TX sounds like writing, but I think it does actually meant to occur upon reading problems. Btw. when getting errors, are you reading or writing the SD card? Or both?

According to dsibrew, TXUNDERRUN is for the host tried to read empty data from the card. Yes, error occurs on read operation, but actually there are three working threads - EmuNAND read from SD, write it to SD FAT partition and background image file read from SD FAT partition. And it happens after several hundreds MB already transferred.
I'll try to use SET_CLR_CARD_DETECT. If this won't help, dump CID/CSD if this card, which is claimed to be Sandisk U1.
 

duke_srg

Well-Known Member
Member
Joined
Mar 1, 2011
Messages
1,862
Trophies
0
Age
44
Location
Moscow
XP
807
Country
Serbia, Republic of
Checked with CD pull-up disabled. Looks better, but still could have underrun errors.
Dumped CID&CSD looks legit, the only differences with my own is higher min/max read and write VDD current ratings.
Also checked 16Mhz clocking with another two cards with no issues.
 

nocash123

Well-Known Member
OP
Member
Joined
Aug 4, 2015
Messages
133
Trophies
0
XP
900
Country
Afghanistan
get in touch with the makers of bootstrap.nds, as they have SD read and write access, and could possibly give your wiki page more information.
Everybody can read & write SD cards... or is that bootstrap tool using any of the still undocumented I/O ports for SD/MMC access?

Checked with CD pull-up disabled. Looks better, but still could have underrun errors.
Dumped CID&CSD looks legit, the only differences with my own is higher min/max read and write VDD current ratings.
Also checked 16Mhz clocking with another two cards with no issues.
Can you post the CID/CSD values for the working & non-working cards? If you want to, erase the serial number in CID for privacy.
I could test those values in no$gba, to see how official Nintendo software is dealing with them... ie. seeing how the console's I/O ports get initialized, and log what kind of initialization commands are sent to the SD card.
If it's current (and/or voltage) related, maybe changing the IF_COND and OP_COND settings might help. Or if needs too much current, maybe the card is exceeding the console's limits... does the card work with official Nintendo software?
 
Last edited by nocash123,

duke_srg

Well-Known Member
Member
Joined
Mar 1, 2011
Messages
1,862
Trophies
0
Age
44
Location
Moscow
XP
807
Country
Serbia, Republic of
Everybody can read & write SD cards... or is that bootstrap tool using any of the still undocumented I/O ports for SD/MMC access?


Can you post the CID/CSD values for the working & non-working cards? If you want to, erase the serial number in CID for privacy.
I could test those values in no$gba, to see how official Nintendo software is dealing with them... ie. seeing how the console's I/O ports get initialized, and log what kind of initialization commands are sent to the SD card.
If it's current (and/or voltage) related, maybe changing the IF_COND and OP_COND settings might help. Or if needs too much current, maybe the card is exceeding the console's limits... does the card work with official Nintendo software?

Yes, the card is claimed to work fine except of that issue with 16MHz operations.
Working fine:
CID 00744A45 55534420 20106100 19D700B6
CSD 00400E00 325B5900 00778D7F 800A4000
Failing:
CID 00035344 534C3634 47800360 AC3000EA
CSD 00400E00 325B5900 01DBD37F 800A4000
just responses, so actually no CRC in LSB

BTW high speed mode tested on 5 cards now, only one fails time to time.
 
Last edited by duke_srg,

nocash123

Well-Known Member
OP
Member
Joined
Aug 4, 2015
Messages
133
Trophies
0
XP
900
Country
Afghanistan
The upper 2bits (in the upper byte with value 40h) are indicated the CSD structure version, for the working & failing card, that's set to the "new" CSD version (for SDHC/SDXC cards).
And, in that "new" version, the C_SIZE field occupies 22bits, and the current specs do no longer exist in CSD (actually, they don't seem to exist at all, at least I can't find any current specs in any other registers like SCR).
Anyways, from what I can see, the two CSD registers differ only by the C_SIZE entries (with value 1DBD3h vs 0778Dh, aka 62GB vs 15GB). Maybe dumping SCR and SSR would reveal further differences.

Or another idea: Are you switching between SD and eMMC access? Maybe it's required to wait for current operations to "finish" before doing that switching.

EDIT: And, if the failing card is 62GB, then it should be SDXC (not SDHC), and by default it would be formatted as EXFAT (not FAT32, unless it was reformatted), oh, and SDXC has one extra current bit in SD_SEND_OP_COND command, maybe that bit must be set/cleared or whatever.
For testing the CSD's in no$gba, I think that won't work out (as far as I know, official DSi software supports max 32GB cards).
 
Last edited by nocash123,

duke_srg

Well-Known Member
Member
Joined
Mar 1, 2011
Messages
1,862
Trophies
0
Age
44
Location
Moscow
XP
807
Country
Serbia, Republic of
The upper 2bits (in the upper byte with value 40h) are indicated the CSD structure version, for the working & failing card, that's set to the "new" CSD version (for SDHC/SDXC cards).
And, in that "new" version, the C_SIZE field occupies 22bits, and the current specs do no longer exist in CSD (actually, they don't seem to exist at all, at least I can't find any current specs in any other registers like SCR).
Anyways, from what I can see, the two CSD registers differ only by the C_SIZE entries (with value 1DBD3h vs 0778Dh, aka 62GB vs 15GB). Maybe dumping SCR and SSR would reveal further differences.

Or another idea: Are you switching between SD and eMMC access? Maybe it's required to wait for current operations to "finish" before doing that switching.

EDIT: And, if the failing card is 62GB, then it should be SDXC (not SDHC), and by default it would be formatted as EXFAT (not FAT32, unless it was reformatted), oh, and SDXC has one extra current bit in SD_SEND_OP_COND command, maybe that bit must be set/cleared or whatever.
For testing the CSD's in no$gba, I think that won't work out (as far as I know, official DSi software supports max 32GB cards).
I have tested another brand 64gb SDXC card with no issues. The operations is accessing only SD on a failure (EmuNAND to SD dump)
SDXC is not optimized for FAT, but it should work anyway. Will check SD_SEND_OP_COND bit set.
 

Valery0p

Well-Known Member
Member
Joined
Jan 16, 2017
Messages
560
Trophies
0
XP
1,644
Country
Italy
Everybody can read & write SD cards... or is that bootstrap tool using any of the still undocumented I/O ports for SD/MMC access?
But they found the way to do that in NTR mode :) , and they are trying to emulate flashcard capabilities via software...
Sorry if this is unrelated to your research...
 

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
  • K3Nv2 @ K3Nv2:
    $12 large any style pizza deal
  • K3Nv2 @ K3Nv2:
    Each bite is a $1 well spent
  • SylverReZ @ SylverReZ:
    @ZeroT21, Agreed. I hate oven pizza, only from pizza place.
    +1
  • K3Nv2 @ K3Nv2:
    Nah I can still go for totinos
  • RedColoredStars @ RedColoredStars:
    i like totinos party pizzas. lol.
  • RedColoredStars @ RedColoredStars:
    the cracker-like crust is great on those
  • RedColoredStars @ RedColoredStars:
    My neighbor and I are going to make this next month....
  • SylverReZ @ SylverReZ:
    Tiger crust is great.
  • K3Nv2 @ K3Nv2:
    I'm beefing with a neighbor currently each time I ask him for help with something he makes bs excuses then ignores my calls text but seems to randomly speak when I'm done with the project after doing things to help him
  • RedColoredStars @ RedColoredStars:
    DiGiorno Crispy Pan Pizza tasted pretty dang close to Pizza hut pan pizza, but Im not sure if theyve been discontinued or not. Havent seen them locally for a couple of months now.
  • RedColoredStars @ RedColoredStars:
    The croissant crust is still available though, but not quite as good imo.
  • RedColoredStars @ RedColoredStars:
    @SylverReZ Never heard of tiger crust. What is it?
  • SylverReZ @ SylverReZ:
    @RedColoredStars, Its known as tiger bread, also known as dutch crust.
  • Maximumbeans @ Maximumbeans:
    It's fuggin gooooood
    +1
  • RedColoredStars @ RedColoredStars:
    I mean. Whats different about it?
  • RedColoredStars @ RedColoredStars:
    Never even seen a tiger crust pizza in any stores around here. Walmart, Cub, or otherwise.
  • RedColoredStars @ RedColoredStars:
    Must be a regional thing.
  • RedColoredStars @ RedColoredStars:
    Gonna smoke this bowl then go get kitties ashes. <3
  • RedColoredStars @ RedColoredStars:
    Last thing I told her is how much I love her, and that Im not leaving her there forever and I promise to come back and take her back home with me.
  • Bunjolio @ Bunjolio:
    halllo
  • Black_Manta_8bit @ Black_Manta_8bit:
    hello, anyone is able to create cheat patches for cemu? i have a simple request if anyone can help
  • SylverReZ @ SylverReZ:
    @RedColoredStars, Rest in piece. Hope she rests well, she'll always love you too. :sad:
    SylverReZ @ SylverReZ: @RedColoredStars, Rest in piece. Hope she rests well, she'll always love you too. :sad: