⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bbu_mmc.s

📁 关于PXA310的最小系统的程序,初级学习阶段会有所帮助,汇编语言编写的
💻 S
📖 第 1 页 / 共 4 页
字号:
;       frequency that was saved in r4 (which is in KHz).
;
        ldr     r0,     =2000           ; 2,000 is equal to 20 MHz in r4
        cmp     r4,     r0              ; Is the card capable of 20 MHz?
        
        mov     r3,     #0              ; Set clock to 19.5 MHz
        str     r3,     [r1, #BBU_MMC_CLKRT_offset]     ; Update clock rate register
;
;*******************************************************************************
;
;       The next command is the SWITCH command and switches the card from 1-bit
;       data transfer mode to 4-bit data transfer mode. Set bit 8 in location
;       BBU_MMC_CMDAT_value so future data transfers occur in 4-bit mode.
;       MMC cards use CMD6 while SD cards use ACMD6 command (and the data is
;       different!)
;
;        mov     r0,     #0              ; No data
;        mov     r1,     #55             ; APP_CMD Command (CMD055)
;        ldr     r2,     =bbu_MiscBuffer ; Address where data goes
;        bl      BBU_MMC_Cmd             ; Send out command
;        cmp     r0,     #0xFF           ; Error detected?
;        beq     %F40                    ; Yes - return to caller

;        ldr     r0,     =0x03B70100     ; Data to set 4-bit transfer mode
;        mov     r1,     #6              ; CMD06 - SWITCH command
;        ldr     r2,     =bbu_MiscBuffer ; Address where data goes
;        bl      BBU_MMC_Cmd             ; Send out command

;        ldr     r0,     =BBU_MMC_CMDAT_value    ; Address of data to be ORred
;        mov     r1,     #0x100                  ; Bit 8 enables 4 bit transfers
;        str     r1,     [r0]            ; Update this memory location
;        mov     r0,     #0x1            ; Set up for a short delay
;        bl      BBU_msWait              ; Delay r0 milliseconds   
;
;*******************************************************************************
;    
;
;       Exit path
;
        ldr     r3,     =BBU_MMC_CT     ; Card type storage location
        strh    r6,     [r3]            ; Save the card type here
        mov     r0,     r6              ; Copy card type into r0
        mov     r1,     r5              ; Byte count is copied into r1
40      ldmfd   sp!,    {r2-r6, pc}     ; Restore used registers and return to caller
        ENDFUNC

BBU_MMC_FREQ    DCD     0       ; Maximum card freq saved here (in 10KZ units)
BBU_RCA         DCD     0       ; SD card relative address is saved here.
BBU_MMC_EGS     DCW     0       ; Erase Group Size
BBU_MMC_CT      DCW     0       ; Card type is saved here
BBU_MMC_MUL     DCB     0,10,12,13,15,20,25,30,35,40,45,50,55,60,70,80  ; 16 multipliers
        ALIGN   4
;
;*********************************************************************************
;
;       ***************
;       *             * 
;       * BBU_MMC_Cmd *
;       *             *
;       ***************
;
;       This subroutine sends a command and sends/receives data as required
;       by the command number that is evoked. Any CMD data that comes back is
;       saved in the raw order in which it came in (for now) So the order may
;       look a little goofy as the data comes in to the controller MSB to LSB
;       so when BBU reads a 6 byte string from the MMC the byte order is:
;       1, 0, 3, 2, 5, 4. Byte 0 is a status byte so the actual data starts
;       in byte 1 and goes to byte 4.
;
; PARAMETER PASSING:
;
;       INPUT - r0 = Data to be sent out with command
;               r1 = MMC command number (if bit 6 is set, set the INIT bit in command register)
;               r2 = pointer to data to be sent or buffer to receive data
;                    (NOTE: pointer not required for all commands)
;
;               COMMAND OUTPUT FORMAT:
;
;                       48 bits as follows:
;
;                       Bit pos:  47      46     [45:40]   [39:8]    [7:1]    0
;                         Width:   1       1         6       32        7      1
;                         Value:   0       1         x        x        x      1
;                   Description: start  transmit  command  argument   crc7   end
;                              :  bit     bit      index                     bit
;
;
;               NOTE: A 32 bit status word is returend by most commands. The raw data
;                     is located starting at the address in r2 but the bytes need to
;                     be rearanged to get them in the right order to form the status
;                     word. Dat is sent MSB first in 16 bit words. The first 8 bits
;                     sent are other control bits (in offset 0x1) so they are skipped.
;
;                     +------------+------------+------------+------------+
;                     | bits 31:24 | bits 23:16 | bits 15:08 | bits 07:00 | MMC Satus Word
;                     +------------+------------+------------+------------+
;                     | offset 0x0 | offset 0x3 | offset 0x2 | offset 0x5 | Offset from r2
;                     +------------+------------+------------+------------+
;
;       OUTPUT - r0 = 0xFF for BBU detected error. Otherwise...
;                r0 = contents of MMC_STAT register
;                r1 = base address of MMC controller being used
;
BBU_MMC_Cmd     FUNCTION

        stmfd   sp!,    {r2-r7, lr}     ; Save used registers

        ldr     r4,     =BBU_MMC_lastInit       ; Address where # of last MMC port initialized is
        ldrb    r5,     [r4]                    ; Fetch MMC # last initialized
        ldr     r3,     =BBU_MMC1_PHYSICAL_BASE ; Load base address for MMC1 controller
        cmp     r5,     #2                      ; Was MMC2 the last MMC initialized?
        ldreq   r3,     =BBU_MMC2_PHYSICAL_BASE ; YES - Load base address for MMC2 controller
;
;       Make sure the clock is stopped (it may (should) be stopped already)
;
        mov     r4,     #BBU_stop_clk                   ; Set the stop clock bit
        str     r4,     [r3, #BBU_MMC_STRPCL_offset]    ; Stop the clock
5       ldr     r4,     [r3, #BBU_MMC_STAT_offset]      ; Get the status
        ands    r4,     r4,     #BBU_clk_en             ; Test the clock enable bit
        bne     %B5                                     ; Loop until clock is stopped
;
;       Fill registers with user supplied data
;
        and     r6,     r1,     #0x40                   ; Save out init bit
        and     r7,     r1,     #0x3F                   ; Save off bits 5:0
        strb    r1,     [r3, #BBU_MMC_CMD_offset]       ; Place command in register
        mov     r1,     r0,     LSR #16                 ; r1 = MSW of data to be sent with command
        strh    r1,     [r3, #BBU_MMC_ARGH_offset]      ; place in MSW
        ldr     r1,     =0xFFFF                         ; Set up mask word
        and     r0,     r0,     r1                      ; Extract LSW of command
        strh    r0,     [r3, #BBU_MMC_ARGL_offset]      ; place in LSW
;
;       If command is doing a data transfer, the DATA_EN bit (bit #2) in the
;       MMC_CMDAT register needs to be set.
;
        ldr     r0,     =MMC_DTC        ; List of commands that have data transfers
7       ldrb    r1,     [r0],   #1      ; fetch a command number
        cmp     r1,     r7              ; Do the commands match?
        orreq   r6,     r6,     #0x4    ; Yes - set DATA_EN bit
        cmp     r1,     #0              ; At end of the list?
        beq     %F8                     ; Yes - take normal exit path
        b       %B7                     ; Get another command number from the list
;
;       Figure out how the RES_TYPE bits are to be set based on the user supplied
;       command number. (See description in table below).
;
8       ldr     r4,     =MMC_RESULT     ; Get address of lookup table
        mov     r5,     r7,     LSR #2  ; Divide command number by 4 and put in r5
        add     r4,     r4,     r5      ; Add r5 offset to desired fetch byte
        ldrb    r5,     [r4]            ; Fetch the desired byte
        mov     r4,     r7,     LSL #1  ; Multiply command number by 2
        and     r4,     r4,     #0x6    ; Only save off bits 2:1
        mov     r5,     r5,     LSR r4  ; Shift right by r4 bits
        ands    r5,     r5,     #0x3    ; Save off bits 1:0
;
;       Write the MMC_CMDAT register to process the command
;
        orr     r6,     r6,     r5                      ; Set the RES_TYPE bits as required
        ldr     r4,     =BBU_MMC_CMDAT_value            ; Address of other bits to be set
        ldr     r0,     [r4]                            ; Get this data
        orr     r6,     r6,     r0                      ; Or in any other bits needed
        str     r6,     [r3, #BBU_MMC_CMDAT_offset]     ; Write the CMDAT register
;
;       Start the clock
;
        mov     r4,     #BBU_strt_clk                   ; Set the start clock bit
        str     r4,     [r3, #BBU_MMC_STRPCL_offset]    ; Stop the clock
;
;       Spin on MMC_RXFIFO_RD_REQ bit and read data when it becomes available.
;       Monitor DATA_TRAN_DONE (and time out) bit to know when transfer is done.
;
        mov     r6,     #0x100000                       ; Time out setting
10      ldr     r0,     [r3, #BBU_MMC_STAT_offset]      ; Get MMC_STATUS register contents
        ands    r1,     r0,     #BBU_end_cmd_res        ; Is command and response sequence done?
        bne     %F15                                    ; Yes - get data
        subs    r6,     r6,     #1      ; No - Decrement time out counter
        bne     %B10                    ; Loop until timed out.
        mov     r0,     #0xFF           ; Timed out - set the error code...
        b       %F22                    ; ... and take the exit path
;
;       Check result time out bit
;
15      ldr     r0,     [r3, #BBU_MMC_STAT_offset]      ; Get MMC_STATUS register contents
        ands    r1,     r0,     #BBU_time_out_res       ; Is the result time out bit set?
        movne   r0,     #0xFF                           ; Yes - set all the bits high
        bne     %F22            ; ... and return to caller
;
;       No error - Service the FIFO. The number of bytes expected depends on the
;       setting of MMC_CMDAT bits 1:0 as definded in the table at the end of this
;       subroutine.
;
        ldr     r1,     [r3, #BBU_MMC_CMDAT_offset]     ; Get contents of CMDAT register
        ands    r1,     r1,     #3                      ; Test bits 1:0
        moveq   r0,     #0              ; Load with zero if no response expected
        streq   r0,     [r2]            ; Store in buffer
        beq     %F20                    ; and exit
;
;       If the code got here - we are expecting 6 0r 17 bytes to be returned
;       Register is 16 bits wide so BBU reads using word (16-bit) commands.
;
        mov     r4,     #3      ; Set bytes expected count to 6/2 bytes
        cmp     r1,     #2      ; If type 2 response expected...
        moveq   r4,     #9                              ; ...then expect 17/2 bytes to come back
17      ldrh    r0,     [r3, #BBU_MMC_RES_FIFO_offset]  ; Fetch a word of data
        strh    r0,     [r2],   #2                      ; Store data & increment pointer
        subs    r4,     r4,     #1      ; Decrement byte transfered count
        bne     %B17                    ; Loop until all the data is transfered
;
;       If this is a command that is expecting data, the clock needs to
;       continue running to clock the data into (or out of) the MMC
;
        ldr     r1,     [r3, #BBU_MMC_CMDAT_offset]     ; Get contents of CMDAT register
        ands    r1,     r1,     #0x4                    ; Is the DATA_EN bit set?
        bne     %F24                                    ; Yes - just exit (for now)
;
;       Fetch status and return to caller
;
20      ldr     r0,     [r3, #BBU_MMC_STAT_offset]      ; Get status
;
;       Stop the clock and return
;
22      mov     r4,     #BBU_stop_clk                   ; Set the stop clock bit
        str     r4,     [r3, #BBU_MMC_STRPCL_offset]    ; Stop the clock
24      mov     r1,     r3                              ; Return controller base address
        ldmfd   sp!,    {r2-r7, pc}                     ; Restore registers and return
;
;       **** MMC RES_TYPE lookup table ****
;
;       Different MMC commands result in different responses from the MMC which
;       the controller needs to be aware of. The following lookup table is used
;       to configure the controller for the type of command that was issued by setting
;       the RES_TYPE[1] and RES_TYPE[0] bits in the MMC_CMDAT register. The table
;       makes it easier for the user (one less thing to worry about). The RES_TYPE
;       bits are set as follows:
;
;       0b00 = No response expected
;       0b01 = r1, r4, r5 response of 6 bytes
;       0b10 = r2 response of 17 bytes
;       0b11 = r3 response of 6 bytes
;
;       Since there are only two bits required per command, they are packed in the
;       table so each byte covers 4 commands starting with command zero at the
;       LSBs and working up through memory to command number 63. NOTE: any reserved
;       commands in this range are coded with 0b00 for the response.
;
MMC_RESULT      DCB     0x6C,   0x44,   0x68,   0x15    ; Commands  0-15
                DCB     0x15,   0x41,   0x55,   0x15    ; Commands 16-31
                DCB     0x50,   0x55,   0x0D,   0x00    ; Commands 32-47
                DCB     0x00,   0x40,   0x01,   0x00    ; Commands 48-63
;
;       The following command numbers have data transfers associated with them
;       and need the CLK line to continue to toggle for the data transfer.
;       The command value 0x0 marks the end of the list.
;
MMC_DTC         DCB     17, 24, 38, 0       ; Data Transfer Commands list
        ALIGN   4

BBU_MMC_CSD             DCD     0,0,0,0 ; MMC - CSD register 128 bits
BBU_MMC_lastInit        DCB     0       ; Number of last MMC port initalized

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -