Homebrew DSi Reverse Engineering: SD/MMC/SDIO Registers

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
and SDXC has one extra current bit in SD_SEND_OP_COND command, maybe that bit must be set/cleared or whatever.
Do you mean SDXC Power Control bit (XPC?) Yes it was unaffected, I fixed that and now waiting for the test result. There is one more problem with this bit - it should not be set for SDHC and I can able to detect SDHC after reading C_SIZE from CSD. The problem is it is initialized now in the following order:

SD_SEND_IF_COND
SD_APP_OP_COND
MMC_ALL_SEND_CID
MMC_SET_RELATIVE_ADDR
MMC_SEND_CSD

And I'm not sure if SD_APP_OP_COND could be moved SD_APP_OP_COND, which sets voltage, and at the same time XPC change requires reinitialization.

Upd: Nope, still freezes on error 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
Yeah, that XPC bit. But the official specs are really unclear about if/when/why/how one would be supposed or allowed to set that bit. Anyways, it should be needed only for some faster speed mode, so, for 16MHz, you can just keep it set to zero (unless the test result tells that it's working with that bit set).

If it helps, here's the DSi Camera's SD card init flow, recorded via no$gba TTY log window (this is for the small SD-card-image bundled with no$gba, ie. some bits should be slightly different for SDHC/SDXC cards):
Code:
SD: CMD00(0000)(00000000) GO_IDLE_STATE
SD: CMD08(0408)(000001AA) SET_IF_COND
SD: CMD55(0037)(00000000) (app_cmd)
SD: ACMD41(0069)(40100000) SEND_OP_COND
SD: CMD02(0002)(00000000) ALL_GET_CID
SD: CMD03(0003)(00000000) GET_RELATIVE_ADDR
SD: CMD09(0009)(00050000) GET_CSD
SD: CMD07(0007)(00050000) SELECT_DESELECT_CARD
SD: CMD16(0010)(00000200) SET_BLOCKLEN
SD: CMD55(0037)(00050000) (app_cmd)
SD: ACMD42(006A)(00000000) SET_CLR_CARD_DETECT
SD: CMD55(0037)(00050000) (app_cmd)
SD: ACMD06(0046)(00000000) SET_BUS_WIDTH
SD: CMD55(0037)(00050000) (app_cmd)
SD: ACMD51(0073)(00000000) GET_SCR
SD: CMD55(0037)(00050000) (app_cmd)
SD: ACMD06(0046)(00000002) SET_BUS_WIDTH
SD: CMD55(0037)(00050000) (app_cmd)
SD: ACMD13(004D)(00000000) SD_STATUS
SD: CMD18(0012)(00000000) READ_MULTIPLE_BLOCK
SD: CMD13(000D)(00050000) GET_STATUS
SD: CMD18(0012)(00001000) READ_MULTIPLE_BLOCK
SD: CMD13(000D)(00050000) GET_STATUS
SD: CMD18(0012)(00004E00) READ_MULTIPLE_BLOCK
SD: CMD13(000D)(00050000) GET_STATUS
SD: CMD18(0012)(00005E00) READ_MULTIPLE_BLOCK
SD: CMD13(000D)(00050000) GET_STATUS
...

And some of the 40048xxh values from no$gba I/O map window (when viewing the DSi camera Album on SD card, and on internal eMMC):
Code:
addr    SD    MMC
4004802 0200  0201(!) sd_port
4004808 0100  0100    sd_stop
4004824 0000  0000    sd_clk
4004828 40EA  40E0(!) sd_opt
40048D8 1012  1012    sd_datactl
40048E0 0007  0007    sd_reset
4004900 0002  0802(!) sd_irq32
 

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
Yeah, that XPC bit. But the official specs are really unclear about if/when/why/how one would be supposed or allowed to set that bit. Anyways, it should be needed only for some faster speed mode, so, for 16MHz, you can just keep it set to zero (unless the test result tells that it's working with that bit set).

Physical Layer Specification Version 5.00, p.29
Re-initialization is required to change XPC selection.
At least implies it should be set in initialization stage if you know what mode to choose.
Edit: Actually not. Initialization process diagram is at p.28 - no XPC set at this stage.

Agreed, it should work fine in SRD and HDR modes with no XPC set. DSi and 3DS both not officially compatible with SDXC, so detects SDCS/SDHC with CMD8 and sets HCS with ACMD41 and only then reading CSD. While we need to know CSD before ACMD41 to set XPC and it is unclear will it work fine with CMD9 just after SET_IF_COND. %)

sd_opt lower byte is still unknown?

Anyway, in case forced XPC did not work the only thing left is to make error handling with reinitialization working on that failed card. BTW in last test error occured after over 4Gb written and 5Gb read.

UPD: at least, issuing second ACMD41 with XPC set after CSD is working with SDXC card. However it is unknown if XPC was actually enabled after that.
 
Last edited by duke_srg,

nocash123

Well-Known Member
OP
Member
Joined
Aug 4, 2015
Messages
133
Trophies
0
XP
900
Country
Afghanistan
sd_opt lower byte is still unknown?
Yes, half of it (the lower 4bit).

UPD: at least, issuing second ACMD41 with XPC set after CSD is working with SDXC card. However it is unknown if XPC was actually enabled after that.
Directly after reading CSD, without first switching to idle mode? That shouldn't work (going by specs). With re-initialization they must mean that you should restart initialization via GO_IDLE_STATE after reading CSD. See here for some list about what can be done in which state: http://problemkaputt.de/gbatek.htm#dsisdmmcprotocolstate - but I doubt that XPC would fix the problem.

I am wondering why you are getting an UNDERRUN error. The CLK comes from the console, so even if the card misses some CLK pulses, it would still output garbage on the databus, which would causes a CRC error at the end of the transfer - but I can't see how it could cause underrun errors... or is there some extra status signal elsewhere, other than on databus?

Theoretically underrun could happen only if the card fails to output start bits - but your software shouldn't even trying to start reading data in that case. Or, underrun might happen if you are reading data at a rate faster than 4bit*16Mhz, best workaround would be to wait until the FIFO is full (see the port 4004900h.bit8 IRQ flag), and then read the 200h bytes (80h words) from the DATA32 FIFO. Are you doing that somehow different?
 
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
Yes, half of it (the lower 4bit).


Directly after reading CSD, without first switching to idle mode? That shouldn't work (going by specs). With re-initialization they must mean that you should restart initialization via GO_IDLE_STATE after reading CSD. See here for some list about what can be done in which state: http://problemkaputt.de/gbatek.htm#dsisdmmcprotocolstate - but I doubt that XPC would fix the problem.

I am wondering why you are getting an UNDERRUN error. The CLK comes from the console, so even if the card misses some CLK pulses, it would still output garbage on the databus, which would causes a CRC error at the end of the transfer - but I can't see how it could cause underrun errors... or is there some extra status signal elsewhere, other than on databus?

Theoretically underrun could happen only if the card fails to output start bits - but your software shouldn't even trying to start reading data in that case. Or, underrun might happen if you are reading data at a rate faster than 4bit*16Mhz, best workaround would be to wait until the FIFO is full (see the port 4004900h.bit8 IRQ flag), and then read the 200h bytes (80h words) from the DATA32 FIFO. Are you doing that somehow different?

You're right, ACMD41 only works in idle state. I wonder my hard did not respond with error on wrong sequence and worked fine:
Code:
MMC_GO_IDLE_STATE
SD_SEND_IF_COND
MMC_APP_CMD/SD_APP_OP_COND
MMC_ALL_SEND_CID
MMC_SET_RELATIVE_ADDR
MMC_SEND_CSD
MMC_APP_CMD/SD_APP_OP_COND
(set clock)
MMC_SELECT_CARD
MMC_APP_CMD/SD_APP_SET_BUS_WIDTH
MMC_APP_CMD/SD_APP_SET_CLR_CARD_DETECT
MMC_SEND_STATUS
MMC_SET_BLOCKLEN
So I must repeat repeat all sequence before second OP_COND, except CID and CSD requests to properly initialize with XPC high?

Underrun situation is described in eMMC specifications http://rere.qmqm.pl/~mirq/JESD84-A44.pdf p.50. It is not the clocking isue itself, card controller just unable to read data at chat clock and would return garbage in several cycles, signaling with underrun bit, so situation could be handled. CRC error might be calculated based on the received data and in case of garbage received it will be reported too IMO. SD specs have no such definition so I wonder what this controllr condition actually means.
 

nocash123

Well-Known Member
OP
Member
Joined
Aug 4, 2015
Messages
133
Trophies
0
XP
900
Country
Afghanistan
So I must repeat repeat all sequence before second OP_COND, except CID and CSD requests to properly initialize with XPC high?
Yes, CID/CSD (probably) won't change, but it'd be easier to re-read them anyways, so you could re-use the same init function. And of course, the ALL_SEND_CID is important for 'selecting' the card (dating back to support for multiple cards on the same SD-bus), so never remove that command.
But, you need XPC only if you want to use transfers somewhere faster than 25MHz, and only if your console's power supply is actually rated to output 0.54 Watts for SD card use. If the XPC bit doesn't fix the problem, then better remove the XPC stuff from your code.

Underrun situation is described in eMMC specifications... signaling with underrun bit, so situation could be handled.
There's an underrun bit in MMC? Oh, yes, didn't knew about that. Maybe it's only in newer eMMC specs, or I just didn't compare SD and MMC specs well enough.
But no, that UNDERRUN bit is located in CSR.bit18. I don't think that the DSi/3DS hardware could automatically copy that bit to the TXUNDERRUN flag in 400481Ch.bit21, so that must be something different.
I would assume that TXUNDERRUN just means that your software or DMA has tried to read from empty FIFO, which would be just a software bug... reading data before it's in the FIFO... or reading an extra data block after the end of the transfer? (though, then, the same problem could also occur with other cards, and also with slower CLKs, unless your code is almost stable, and fails only if a card replies a nanosecond later/earlier than others).

Oh, and messing with SD_CARD_IRQ_ENABLE (4004834h) could also cause TXUNDERRUN, no idea what's happening there. Best have SD_CARD_IRQ_ENABLE set to 0000h.

PS. what did you mean by SDXC not being officially supported on 3DS? Does the original 3DS firmware have "inofficial" support for SDXC cards? If it does, then I would assume that Nintendo's using 16MHz, too. So one could figure out if it's a hardware problem (card isn't 3DS compatible), or software problem (occurring only with homebrew code).
 
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
Yes, CID/CSD (probably) won't change, but it'd be easier to re-read them anyways, so you could re-use the same init function. And of course, the ALL_SEND_CID is important for 'selecting' the card (dating back to support for multiple cards on the same SD-bus), so never remove that command.
But, you need XPC only if you want to use transfers somewhere faster than 25MHz, and only if your console's power supply is actually rated to output 0.54 Watts for SD card use. If the XPC bit doesn't fix the problem, then better remove the XPC stuff from your code.


There's an underrun bit in MMC? Oh, yes, didn't knew about that. Maybe it's only in newer eMMC specs, or I just didn't compare SD and MMC specs well enough.
But no, that UNDERRUN bit is located in CSR.bit18. I don't think that the DSi/3DS hardware could automatically copy that bit to the TXUNDERRUN flag in 400481Ch.bit21, so that must be something different.
I would assume that TXUNDERRUN just means that your software or DMA has tried to read from empty FIFO, which would be just a software bug... reading data before it's in the FIFO... or reading an extra data block after the end of the transfer? (though, then, the same problem could also occur with other cards, and also with slower CLKs, unless your code is almost stable, and fails only if a card replies a nanosecond later/earlier than others).

Oh, and messing with SD_CARD_IRQ_ENABLE (4004834h) could also cause TXUNDERRUN, no idea what's happening there. Best have SD_CARD_IRQ_ENABLE set to 0000h.

PS. what did you mean by SDXC not being officially supported on 3DS? Does the original 3DS firmware have "inofficial" support for SDXC cards? If it does, then I would assume that Nintendo's using 16MHz, too. So one could figure out if it's a hardware problem (card isn't 3DS compatible), or software problem (occurring only with homebrew code).

What do you mean, 4004834h/4004A34h is SD_TRANSACTION_CTL - Transaction Control.
Read loop have count is set to the same value sent to controller, so there can't be excessive reads. You can check the read loop by yourself, it is controlled by IRQ https://github.com/dukesrg/rxTools/blob/dev-cardboost/rxtools/source/lib/tmio/tmio.c#L144
The issue only appears in high clock and on one card, so it is not likely a software issue.

I only meant 3DS literally do not support SDXC. So there is no obligation to support higher current enabled by XPC high performance mode.
Anyway I disabled XPC for now, it doesn't help anyway, unlike CD pullup disable. Now only need to find the solution to properly reinitialize the card after failed operation, since repeating all initialization from the begining did not help, so card or controller of 3DS unit might be in a special state.
 

nocash123

Well-Known Member
OP
Member
Joined
Aug 4, 2015
Messages
133
Trophies
0
XP
900
Country
Afghanistan
Another thing: I've found some old sd/mmc source code, and that code seems to start/stop the CLK for each and every read/write sector command (or it least it messes with CLK_CTL bit8, apparently forcing the CLK pin LOW after each sector). If there's no really good reason to do that stuff, then it should be better and more reliable to initialize CLK_CTL once during init, and then keep it enabled and never touch the register again (unless you want to implement some power-saving sleep mode).
EDIT: The https://github.com/dukesrg/rxTools/blob/dev-cardboost/rxtools/source/lib/tmio/tmio.c#L144 code is doing similar stuff, when doing that "target" selection within the read/write sector functions - I guess that might explain CLK problems.

PS. SD_TRANSACTION_CTL dates back to old datasheets, there seems to be no such thing at port 4004834h in DSi/3DS. The dsibrew page is a bit outdated on that, see gbatek.htm for newer specs: http://problemkaputt.de/gbatek.htm#dsisdmmcprotocolandioports
 
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
Another thing: I've found some old sd/mmc source code, and that code seems to start/stop the CLK for each and every read/write sector command (or it least it messes with CLK_CTL bit8, apparently forcing the CLK pin LOW after each sector). If there's no really good reason to do that stuff, then it should be better and more reliable to initialize CLK_CTL once during init, and then keep it enabled and never touch the register again (unless you want to implement some power-saving sleep mode).
EDIT: The https://github.com/dukesrg/rxTools/blob/dev-cardboost/rxtools/source/lib/tmio/tmio.c#L144 code is doing similar stuff, when doing that "target" selection within the read/write sector functions - I guess that might explain CLK problems.

PS. SD_TRANSACTION_CTL dates back to old datasheets, there seems to be no such thing at port 4004834h in DSi/3DS. The dsibrew page is a bit outdated on that, see gbatek.htm for newer specs: http://problemkaputt.de/gbatek.htm#dsisdmmcprotocolandioports

It is unclear how actual CLK driven by the controller on target device change. But at least in case the same clock selected for both SD and eMMC it worth to try skipping setting CLK on inittarget, it might really increase stability. I'll try this recipe.
 

nocash123

Well-Known Member
OP
Member
Joined
Aug 4, 2015
Messages
133
Trophies
0
XP
900
Country
Afghanistan
Checked with no CLK there - operations slows down :(
Don't know what happened there - but that's not the expected/intended effect.
Did you make sure to keep initializing the correct CLK elsewhere?
And also make sure to do it for SD card (just in case that there might be separate CLK registers for MMC and SD ports internally).
Or could there be something 'hanging' in a busy state, until some timeout occurs? Maybe messing with the CLK does forcefully abort such things.

Attached below are my own init/read/write functions - it's rather experimental code, I haven't benchmarked it's performance, and don't know if it's more reliable than yours. But maybe it helps on figuring out how to initialize which ports with what values.
Some of your code looks a bit overcomplicated, the read command should be just "MMC_READ_MULTIPLE_BLOCK" (instead of "(count > 1 ? (MMC_READ_MULTIPLE_BLOCK | TMIO_CMD_TRANSFER_MULTI) : MMC_READ_SINGLE_BLOCK) | TMIO_CMD_RESP_R1 | TMIO_CMD_DATA_PRESENT | TMIO_CMD_TRANSFER_READ").
Ah, and that "if (!((uint32_t)dataPtr & 3)) {" - I am not sure what that's trying to do, but it can't work. Either you use DATA32, or don't use it.

Code:
;------------------
sdmmc_init_device:
 push r0-r12,lr
 ldr  r0,=sdmmc_sha1_cid   ;dst ;\
 ldr  r1,=2FFD7BCh  ;cid   ;src ; SHA1 init+update+fin
 mov  r2,10h               ;len ;
 swi  27h shl 16   ;sha1        ;/
 ;---
 ldr  r9,=4004800h      ;-base
 ldrh r0,[r9,0e0h]      ;\
 bic  r0,3              ; SD_SOFT_RESET clear bit0-1
 strh r0,[r9,0e0h]      ;/
 ldrh r0,[r9,0e0h]      ;\
 orr  r0,3              ; SD_SOFT_RESET set bit0-1
 strh r0,[r9,0e0h]      ;/
 ldrh r0,[r9,008h]      ;\
 bic  r0,1              ; SD_STOP_INTERNAL clear bit0
 orr  r0,100h ;autostop ;
 strh r0,[r9,008h]      ;/
 ldrb r0,[sdmmc_curr_device]            ;\
 orr  r0,400h  ;bit0: 0=sd slot, 1=eMMC ;  SD_CARD_PORT_SELECT
 strh r0,[r9,002h]                      ;/

 mov  r0,0040h          ;\SD_CARD_CLK_CTL = 0040h
;mov r0,0020h  ;try affect timer...?
;mov r0,002h
mov r0,0
 strh r0,[r9,024h]      ;/
 ldr  r0,=00d0h         ;\SD_CARD_OPTION = 80D0h (timeouts, buswidth)
 strh r0,[r9,028h]      ;/
 ldrh r0,[r9,028h]      ;\
 orr  r0,8000h          ; SD_CARD_OPTION set bit15
   bic r0,8000h               ;clear --> want 4bit DATA mode !!!
 strh r0,[r9,028h]      ;/
 ;---part2b
 ldrh r0,[r9,028h]      ;\
 orr  r0,0100h          ; SD_CARD_OPTION set bit8
 strh r0,[r9,028h]      ;/
 ldrh r0,[r9,028h]      ;\
 bic  r0,0100h          ; SD_CARD_OPTION clear bit8
 strh r0,[r9,028h]      ;/
 ;---part3a
 ldrh r0,[r9,024h]      ;\
 orr  r0,0100h          ; SD_CARD_CLK_CTL set bit8
mov r0,100h  ;<-- this works, unlike ORing zero by 100h ???
;;;;add r0,40h
 strh r0,[r9,024h]      ;/

 mov  r0,002h                           ;\want data32 mode, step 1
 strh r0,[r9,0d8h] ;SD_DATA_CTL         ;/
 ldr  r0,=402h ;clear fifo, data32 mode ;\want data32 mode, step 2
 str  r0,[r9,100h] ;SD_IRQ32            ;/

 pop  r0-r12,pc
;------------------
sdmmc_load_sector:       ;in: r0=sector, r1=dest
 mov  r2,200h  ;len
;- - - - - --------
sdmmc_load_sectors:      ;in: r0=sector, r1=dest, r2=len
 push r0-r12,lr
 mov  r10,r0  ;sector
 mov  r11,r1  ;dest
 mov  r12,r2  ;len
 ldr  r9,=4004800h                              ;\
 mov  r0,r12,lsr 9  ;num_blk's = len/200h       ; apply num blk's
 strh r0,[r9,00ah] ;SD_NUMBLK16                 ;
 str  r0,[r9,108h] ;SD_NUMBLK32                 ;/
 mov  r0,200h                                   ;\
 strh r0,[r9,026h] ;SD_BLKLEN16                 ; apply blk_len
 str  r0,[r9,104h] ;SD_BLKLEN32                 ;/
 ldrb r0,[sdmmc_curr_is_sdhc]                   ;\
 cmp  r0,0                                      ;
 moveq r0,r10,lsl 9  ;sector*200h (SDSC)        ; issue READ_MULTIPLE
 movne r0,r10        ;sector (SDHC/SDXC)        ;
 mov  r1,12h      ;CMD18 READ_MULTIPLE          ;
 bl   sdmmc_read_register                       ;/
@@blk_lop:                                      ;-lop blk's...
 mov  r1,r11    ;dest                           ;\
 mov  r2,200h   ;len                            ; read sector
 bl   sdmmc_read_data                           ;/
 ldrb r0,[sdmmc_curr_device]                    ;\
 cmp  r0,1      ;1=eMMC (need decrypt)          ; decrypt (if eMMC)
 mov  r0,r10    ;sector                         ;
 mov  r1,r11    ;src/dst                        ;
 bleq sdmmc_decrypt_sector                      ;/
 add  r10,1     ;sector                         ;\
 add  r11,200h  ;dest                           ; lop next blk
 subs r12,200h  ;len                            ;
 bne  @@blk_lop                                 ;/
; mov  r0,0001h shl 16    ;XXX RCA               ;\
; mov  r1,0dh    ;CMD13 SEND_STATUS              ; issue GET_STATUS
; bl   sdmmc_read_register                       ;/  XXX for SD: need other RCA?
 pop  r0-r12,pc
;------------------
sdmmc_write_sector:       ;in: r0=sector, r1=src
 mov  r2,200h  ;len
;- - - - - --------
sdmmc_write_sectors:      ;in: r0=sector, r1=src, r2=len
 push r0-r12,lr
 mov  r10,r0  ;sector
 mov  r11,r1  ;src
 mov  r12,r2  ;len
 ldr  r9,=4004800h                              ;\
 mov  r0,r12,lsr 9  ;num_blk's = len/200h       ; apply num blk's
 strh r0,[r9,00ah] ;SD_NUMBLK16                 ;
 str  r0,[r9,108h] ;SD_NUMBLK32                 ;/
 mov  r0,200h                                   ;\
 strh r0,[r9,026h] ;SD_BLKLEN16                 ; apply blk_len
 str  r0,[r9,104h] ;SD_BLKLEN32                 ;/
 ldrb r0,[sdmmc_curr_is_sdhc]                   ;\
 cmp  r0,0                                      ;
 moveq r0,r10,lsl 9  ;sector*200h (SDSC)        ; issue WRITE_MULTIPLE
 movne r0,r10        ;sector (SDHC/SDXC)        ;
 mov  r1,19h      ;CMD25 WRITE_MULTIPLE          ;
 bl   sdmmc_read_register                       ;/
@@blk_lop:                                      ;-lop blk's...
 ldrb r0,[sdmmc_curr_device]                    ;\
 cmp  r0,1      ;1=eMMC (need decrypt)          ; encrypt (if eMMC)
 mov  r0,r10    ;sector                         ;
 mov  r1,r11    ;src/dst                        ;
 bleq sdmmc_encrypt_sector                      ;/
 mov  r1,r11    ;src                            ;\
 mov  r2,200h   ;len                            ; write sector
 bl   sdmmc_write_data                          ;/
 add  r10,1     ;sector                         ;\
 add  r11,200h  ;dest                           ; lop next blk
 subs r12,200h  ;len                            ;
 bne  @@blk_lop                                 ;/
; mov  r0,0001h shl 16    ;XXX RCA               ;\
; mov  r1,0dh    ;CMD13 SEND_STATUS              ; issue GET_STATUS
; bl   sdmmc_read_register                       ;/  XXX for SD: need other RCA?
 pop  r0-r12,pc
 
Last edited by nocash123,
  • Like
Reactions: I pwned U! and Coto

ahezard

Well-Known Member
Member
Joined
Feb 17, 2016
Messages
116
Trophies
0
XP
1,140
Country
France
Don't know what happened there - but that's not the expected/intended effect.
Did you make sure to keep initializing the correct CLK elsewhere?
And also make sure to do it for SD card (just in case that there might be separate CLK registers for MMC and SD ports internally).
Or could there be something 'hanging' in a busy state, until some timeout occurs? Maybe messing with the CLK does forcefully abort such things.

Attached below are my own init/read/write functions - it's rather experimental code, I haven't benchmarked it's performance, and don't know if it's more reliable than yours. But maybe it helps on figuring out how to initialize which ports with what values.
Some of your code looks a bit overcomplicated, the read command should be just "MMC_READ_MULTIPLE_BLOCK" (instead of "(count > 1 ? (MMC_READ_MULTIPLE_BLOCK | TMIO_CMD_TRANSFER_MULTI) : MMC_READ_SINGLE_BLOCK) | TMIO_CMD_RESP_R1 | TMIO_CMD_DATA_PRESENT | TMIO_CMD_TRANSFER_READ").
Ah, and that "if (!((uint32_t)dataPtr & 3)) {" - I am not sure what that's trying to do, but it can't work. Either you use DATA32, or don't use it.

Code:
;------------------
sdmmc_init_device:
...
 pop  r0-r12,pc
I would like to found out if your code is faster but it is currently not complete :
sdmmc_read_register, sdmmc_read_data, sdmmc_decrypt_sector, sdmmc_write_sectors, sdmmc_read_register, sdmmc_encrypt_sector and sdmmc_write_data are not defined.
 

nocash123

Well-Known Member
OP
Member
Joined
Aug 4, 2015
Messages
133
Trophies
0
XP
900
Country
Afghanistan
I would like to found out if your code is faster but it is currently not complete :
sdmmc_read_register, sdmmc_read_data, sdmmc_decrypt_sector, sdmmc_write_sectors, sdmmc_read_register, sdmmc_encrypt_sector and sdmmc_write_data are not defined.
Hmmm, yeah, I was afraid that somebody might complain there - especially when seeing the source code for that functions.
But okay, here it is. But the timeout/error handling in that 3 functions is probably all wrong.
Code:
;------------------
sdmmc_read_register:   ;in: r0=param, r1=cmd
 push r1-r12,lr
 bl   sdmmc_verify_fixed_values
        mov r2,100h
       @@pre_wait:
        subs r2,1
        bne @@pre_wait

 ldr  r9,=4004800h
 strh r0,[r9,004h]      ;\
 mov  r0,r0,lsr 16      ; SD_CMD_PARAM
 strh r0,[r9,06h]       ;/
 ldr  r0,[r9,01ch]      ;\SD_IRQ_STAT
 bic  r0,83000000h      ; clear bit31,25,24 (error, txrq, rxrdy)
 bic  r0,007f0000h      ; clear bit22..16   (error)
 bic  r0,00000005h      ; clear bit2,0      (dataend,cmdrespend)
mov r0,0
 str  r0,[r9,01ch]      ;/

;;;mov r0,-1              ;\
;;;str  r0,[r9,020h]      ;/
 bl   sdmmc_verify_fixed_values
 ldrh r0,[r9,008h]      ;\
 bic  r0,1              ; SD_STOP_INTERNAL clear bit0
 strh r0,[r9,008h]      ;/
 bl   sdmmc_verify_fixed_values
 strh r1,[r9,000h]      ;-SD_CMD
 ;- - -
 mov  r2,100000h ;timeout (ca. 1 Million) ;<-- ENDLESS SLOW (at least several MINUTES... or HOURS) (ie. in fact NEVER)
    mov r2,1000h                          ;<-- REASONABLE SLOW (hmmm, even for 256-bytes, this is WAYS FASTER than above delay, which is 256-times slower, how is THAT possible??)
        mov r2,10000h
@@busy_lop:
 bl   sdmmc_verify_fixed_values
 ldrh r0,[r9,02ch]      ;\SD_ERROR_DETAIL_LO
 tst   r0,005h          ;  bit0, CMD CmdIndex-Error
 tsteq r0,100h          ;  bit2, CMD End-Bit-Error
 bne  @@error_detail    ;/ bit8, CMD CRC-Error
 ldrh r0,[r9,01ch]      ;\SDIO_IRQ_STAT_LO
 tst  r0,1              ;  bit0, CMDRESPEND
 bne  @@busy_done       ;/
 subs r2,1              ;\lop next, till timeout
 bne  @@busy_lop        ;/
 b    @@error_sw_timeout     ;XXX accessing DISABLED function 1 does HANG (rather than reaching timeout?)
 ;---
@@busy_done:
 bl   sdmmc_verify_fixed_values
 ldrh r0,[r9,01eh]      ;\SD_IRQ_STAT_HI
 tst  r0,40h            ;  bit22, CMDTIMEOUT
 bne  @@error_hw_timeout;/
 ldr  r0,[r9,00ch]      ;\SD_REPLY (00001000h, ie. state = "dis"; if it's "CSR")
;;; and  r0,00ffh          ;/
@@done:
        ;; bl   wrhex32bit
        ;;bl wrcrlf
 bl   sdmmc_verify_fixed_values
 pop  r1-r12,pc
;---
@@error_detail:
@@error_sw_timeout:
@@error_hw_timeout:
 mov  r0,-1
 b    @@done
;------------------
sdmmc_read_data:    ;in: r1=dst, r2=len
 ;based on experimental "sdmmc_data_xfer"...
 push r1-r12,lr
 mov  r11,r1
 mov  r12,r2
 ldr  r9,=4004800h              ;-
 ldrh r0,[r9,0d8h] ;SD_DATA_CTL         ;\
 tst  r0,2                              ;
 beq  @@dta16                           ; redirect data16 / data32
 ldr  r0,[r9,100h] ;SD_DATA32_IRQ       ;
 tst  r0,2                              ;
 beq  @@dta16                           ;/
;---DATA32...
 mov  r2,10000h                 ;\
@@dta32_wait_rxrdy:             ;
 subs r2,1                      ; wait for data
 beq  @@error_sw_timeout        ;

;ldrh r0,[r9,01eh] ;SD_IRQ_STAT_HI
;tst  r0,100h  ;RXRDY32 (full)  ;

 ldr  r0,[r9,100h] ;SD_IRQ32    ;
 tst  r0,100h ;RXRDY32 (full)   ;
 beq  @@dta32_wait_rxrdy        ;/

@@dta32_rx_lop:                 ;\
 ldr  r0,[r9,10ch]  ;SD_DATA32  ;
 str  r0,[r11],4                ; read data
 subs r12,4                     ;
 bne  @@dta32_rx_lop            ;/
 b    @@finish
;-------
@@dta16:
 mov  r2,10000h                 ;\
@@dta16_wait_rxrdy:             ;
 subs r2,1                      ; wait for data
 beq  @@error_sw_timeout        ;
 ldrh r0,[r9,01eh] ;SD_IRQ_STAT_HI
 tst  r0,100h  ;RXRDY16         ;
 beq  @@dta16_wait_rxrdy        ;/

@@dta16_rx_lop:                 ;\
 ldrh r0,[r9,030h]  ;SD_DATA16  ;
 strh r0,[r11],2                ; read data
 subs r12,2                     ;
 bne  @@dta16_rx_lop            ;/
 b    @@finish
;- - - -
@@finish:
    @@wait_dataend:             ;\
     subs r2,1                  ;
     beq  @@error_sw_timeout    ;
     ldrh r0,[r9,01ch]          ; SD_IRQ_STAT_LO
     tst  r0,4     ;dataend     ;          (works BETTER with this!)
     beq  @@wait_dataend        ;/
 mov  r0,0   ;okay
@@done:
 pop  r1-r12,pc
;---
@@error_sw_timeout:
 mov  r0,-1  ;error/timeout
 b    @@done
;------------------
sdmmc_write_data:     ;in: r1=src, r2=len
 push r1-r12,lr
 mov  r11,r1     ;src
 mov  r12,r2     ;len
 ldr  r9,=4004800h
 mov  r2,1000000h                       ;\
@@wait_txrq:                            ;
 subs r2,1                              ;
 beq  @@error_sw_timeout                ; wait ready
;;; ldrh r0,[r9,01eh] ;SD_IRQ_STAT_HI
;;; tst  r0,200h  ;txrq
;;; mov r0,not 200h
;;; strh r0,[r9,01eh]     ;ACK now
 ldr  r0,[r9,100h]                      ;
 tst  r0,200h  ;TXRDY32 (0=empty)       ;
 bne  @@wait_txrq                       ;/
@@dta_tx_lop:                           ;\
 ldr  r0,[r11],4                        ;
 str  r0,[r9,10ch]  ;SD_DATA32          ; write data
 subs r12,4                             ;
 bne  @@dta_tx_lop                      ;/
@@wait_dataend:                         ;\
 subs r2,1                              ;
 beq  @@error_sw_timeout                ; wait end
 ldrh r0,[r9,01ch] ;SD_IRQ_STAT         ;
 tst  r0,4     ;dataend                 ;          (works BETTER with this!)
 beq  @@wait_dataend                    ;/
 mov  r0,0   ;okay
@@done:
 pop  r1-r12,pc
;---
@@error_sw_timeout:
 mov  r0,-1  ;error/timeout
 b    @@done
For the other functions: sdmmc_write_sectors was included in previous post. Encrypt/decrypt would be needed only for eMMC. Verify_fixed_values would be some optional selfcheck for rev-engineering the hardware (see older posts from last year).
 
  • Like
Reactions: ahezard

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
Don't know what happened there - but that's not the expected/intended effect.
Did you make sure to keep initializing the correct CLK elsewhere?
And also make sure to do it for SD card (just in case that there might be separate CLK registers for MMC and SD ports internally).
Or could there be something 'hanging' in a busy state, until some timeout occurs? Maybe messing with the CLK does forcefully abort such things.

Attached below are my own init/read/write functions - it's rather experimental code, I haven't benchmarked it's performance, and don't know if it's more reliable than yours. But maybe it helps on figuring out how to initialize which ports with what values.
Some of your code looks a bit overcomplicated, the read command should be just "MMC_READ_MULTIPLE_BLOCK" (instead of "(count > 1 ? (MMC_READ_MULTIPLE_BLOCK | TMIO_CMD_TRANSFER_MULTI) : MMC_READ_SINGLE_BLOCK) | TMIO_CMD_RESP_R1 | TMIO_CMD_DATA_PRESENT | TMIO_CMD_TRANSFER_READ").
Ah, and that "if (!((uint32_t)dataPtr & 3)) {" - I am not sure what that's trying to do, but it can't work. Either you use DATA32, or don't use it.

The only changes were made is removing setckl call from inittarget and adding it after inittarget call insinde of tmio_init_dev.
I.e. clocks only set twice in tmio_init_dev - CLK/128 before initialization and CLK/2 after. So it works definitely faster than CLK/128 but slower than before with CLK/2 and this is all measured on SD operations, so eMMC actually should not interfere.

As for Single block/multiple block addition, it is not necessary, but I added it to speedup single sector operations a bit, it is not interfering.

And about (!((uint32_t)dataPtr & 3)), I tracked older Normmatt's versions, it was added because of an unaligned transfer issues in 32-bit mode.
 

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
    NinStar @ NinStar: you are a product of my imagination