DSi Reverse Engineering: SD/MMC/SDIO Registers

Discussion in 'NDS - Emulation and Homebrew' started by nocash123, Aug 25, 2015.

  1. duke_srg

    duke_srg GBAtemp Advanced Maniac

    Member
    6
    Mar 1, 2011
    Serbia, Republic of
    Moscow
    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, Feb 21, 2017
  2. nocash123
    OP

    nocash123 GBAtemp Regular

    Member
    6
    Aug 4, 2015
    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
     
  3. duke_srg

    duke_srg GBAtemp Advanced Maniac

    Member
    6
    Mar 1, 2011
    Serbia, Republic of
    Moscow
    Physical Layer Specification Version 5.00, p.29
    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, Feb 21, 2017
  4. nocash123
    OP

    nocash123 GBAtemp Regular

    Member
    6
    Aug 4, 2015
    Afghanistan
    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?
     
    Last edited by nocash123, Feb 22, 2017
  5. duke_srg

    duke_srg GBAtemp Advanced Maniac

    Member
    6
    Mar 1, 2011
    Serbia, Republic of
    Moscow
    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.
     
  6. nocash123
    OP

    nocash123 GBAtemp Regular

    Member
    6
    Aug 4, 2015
    Afghanistan
    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).
     
    Last edited by nocash123, Feb 22, 2017
  7. duke_srg

    duke_srg GBAtemp Advanced Maniac

    Member
    6
    Mar 1, 2011
    Serbia, Republic of
    Moscow
    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.
     
  8. nocash123
    OP

    nocash123 GBAtemp Regular

    Member
    6
    Aug 4, 2015
    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, Feb 22, 2017
  9. duke_srg

    duke_srg GBAtemp Advanced Maniac

    Member
    6
    Mar 1, 2011
    Serbia, Republic of
    Moscow
    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.
     
  10. duke_srg

    duke_srg GBAtemp Advanced Maniac

    Member
    6
    Mar 1, 2011
    Serbia, Republic of
    Moscow
    Checked with no CLK there - operations slows down :(
     
  11. nocash123
    OP

    nocash123 GBAtemp Regular

    Member
    6
    Aug 4, 2015
    Afghanistan
    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, Mar 5, 2017
    I pwned U! and Coto like this.
  12. ahezard

    ahezard GBAtemp Regular

    Member
    6
    Feb 17, 2016
    France
    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.
     
  13. nocash123
    OP

    nocash123 GBAtemp Regular

    Member
    6
    Aug 4, 2015
    Afghanistan
    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).
     
    ahezard likes this.
  14. duke_srg

    duke_srg GBAtemp Advanced Maniac

    Member
    6
    Mar 1, 2011
    Serbia, Republic of
    Moscow
    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.
     
Quick Reply
Draft saved Draft deleted
Loading...