📄 bbu_mmc.s
字号:
ALIGN 4
ENDFUNC
;
; ******************
; ** **
; ** LITERAL POOL ** LOCAL DATA STORAGE
; ** **
; ******************
;
LTORG
;
;*********************************************************************************
;
; ****************
; * *
; * BBU_MMC_Read * READ A SINGLE SECTOR OF DATA FROM A MMC/SD CARD
; * *
; ****************
;
; This subroutine will read a block of data from a MMC that has already been
; initalized with the BBU IMMC command and save the data (usually 512 bytes)
; in the user specified buffer.
;
; PARAMETER PASSING:
;
; INPUT - r0 = Sector # to be read from the device
; r1 = Address where data is to be written to
;
; OUTPUT - r0 = 0xFF for BBU detected error. Otherwise...
; r0 = the sector length of the device (in bytes)
; r1 = destroyed
;
BBU_MMC_Read FUNCTION
stmfd sp!, {r2-r5, lr} ; Save used registers
mov r4, r0 ; Save off read block number
mov r5, r1 ; Save off buffer address into r5
mov r3, #0x200 ; Set sector length to 512 bytes for now
;
; Prepare to read a single sector from the selected device
;
mul r0, r4, r3 ; Generate the starting address for the read
mov r1, #17 ; Command to be sent (CMD17 = READ SINGLE SECTOR)
ldr r2, =bbu_MiscBuffer ; Address where CMD data is to be sent
bl BBU_MMC_Cmd ; Send out command
cmp r0, #0xFF ; Error detected?
beq %F38 ; Yes - exit with error code in r0
;
; Monitor MMC_I_REG for requests to read data from the MMC
; Note: Bit is set when there are 32 bytes ready to read.
;
mov r4, #0x10000 ; Set up time out counter
32 subs r4, r4, #1 ; Decrement loop counter
moveq r0, #0xFF ; Set error code if timed out
beq %F38 ; ..and exit if timed out
ldr r2, [r1, #BBU_MMC_I_REG_offset] ; Fetch interrupt register status
ands r2, r2, #BBU_MMC_RD_REQ ; read request?
beq %B32 ; No - keep looping
;
; Move 32 bytes of data into the memory address provided by caller then
; wait for another read request by the controller.
;
mov r4, #0x20 ; Move 32 bytes
34 ldrb r2, [r1, #BBU_MMC_RXFIFO_offset] ; Fetch a byte
strb r2, [r5], #1 ; Save in memory
subs r4, r4, #1 ; decrement byte transfer count
bne %B34 ; Loop until done
subs r3, r3, #0x20 ; Decrement total byte transfer count from block size
bne %B32 ; Fetch data until block is transfered
;
; Stop the MMC clock
;
mov r4, #BBU_stop_clk ; Set the stop clock bit
str r4, [r1, #BBU_MMC_STRPCL_offset] ; Stop the clock
ldr r0, [r1, #BBU_MMC_BLKLEN_offset] ; Get block length of this MMC
38 ldmfd sp!, {r2-r5, pc} ; Restore registers and return
ENDFUNC
;
;*********************************************************************************
;
; *****************
; * *
; * BBU_MMC_Erase * ERASE A SINGLE BLOCK OF DATA IN THE MMC
; * *
; *****************
;
; This subroutine will erase a block of data from a MMC that has already been
; initalized with the BBU IMMC command and mounted with the MMC_MOUNT command.
;
; PARAMETER PASSING:
;
; INPUT - r0 = Sector number of the first sector in the block to be erased
;
; OUTPUT - r0 = 0xFF for BBU detected error. Otherwise...
; r0 = Size of the erase group (in sectors)
; r1 = Size of sector (in bytes)
;
BBU_MMC_Erase FUNCTION
stmfd sp!, {r2-r6, lr} ; Save used registers
mov r4, #0x200 ; BBU assumes all sectors are 512 bytes
mul r0, r0, r4 ; Calculate starting address
mov r4, r0 ; Save off starting address
ldr r5, =BBU_RCA ; Location of Relative Card Address
ldr r6, [r5] ; Fetch the RCA & save for later reference
;
; Prepare to erase a single block from the selected card by sending the
; erase group start and stop address. MMC and SD cards use different
; commands to set up the erase length. Under BBU MMC cards use an RCA of
; 5 so any other value is assumed to be a SD card (although this is not
; always guaranteed).
;
cmp r6, #5 ; MMC or SD card?
moveq r1, #35 ; MMC - (CMD35 = ERASE_GROUP_START)
movne r1, #32 ; SD Card - (CMD32 = ERASE_GROUP_START)
ldr r2, =bbu_MiscBuffer ; Address where CMD reply is to be sent
bl BBU_MMC_Cmd ; Send out command & fetch data
cmp r0, #0xFF ; Error detected?
beq %F48 ; Yes - exit with error code in r0
mov r0, #0x1 ; Set up for a short delay
bl BBU_msWait ; Delay r0 milliseconds
;
; Set the ERASE_GROUP_END data (Note: BLKLEN in MMC terms is the same as
; sector size in disk tems)
;
ldr r2, =BBU_MMC_EGS ; Erase Group Size saved here here
ldrh r0, [r2] ; Get this information
ldr r1, =BBU_MMC1_PHYSICAL_BASE ; Load base address for MMC1 controller
ldr r2, [r1, #BBU_MMC_BLKLEN_offset] ; Get block length of this MMC
sub r2, r2, #1 ; Decrement by 1 byte
mul r0, r0, r2 ; Generate an ending address within the erase block
add r0, r0, r4 ; Add 1 block to base address
cmp r6, #5 ; MMC or SD card?
moveq r1, #36 ; MMC - (CMD36 = ERASE_GROUP_END)
movne r1, #33 ; SD Card - (CMD33 = ERASE_GROUP_END)
ldr r2, =bbu_MiscBuffer ; Address where CMD reply is to be sent
bl BBU_MMC_Cmd ; Send out command & fetch data
cmp r0, #0xFF ; Error detected?
beq %F48 ; Yes - exit with error code in r0
mov r0, #0x1 ; Set up for a short delay
bl BBU_msWait ; Delay r0 milliseconds
;
; Send the erase command
;
mov r0, #0 ; Stuffer bits
mov r1, #38 ; Command to be sent (CMD038 = ERASE)
ldr r2, =bbu_MiscBuffer ; Address where CMD reply is to be sent
bl BBU_MMC_Cmd ; Send out command & fetch data
cmp r0, #0xFF ; Error detected?
beq %F48 ; Yes - exit with error code in r0
mov r0, #1 ; Set up a delay time
bl BBU_msWait ; Delay for r0 millisecoonds
mov r4, #BBU_stop_clk ; Set the stop clock bit
str r4, [r1, #BBU_MMC_STRPCL_offset] ; Stop the clock
;
; Fecth the size of the erase group from the Card Specific Data (CSD) word
; Erase Group Size in bits 46:42 (+1)
; Erase Group Multipler in bits 41:37 (+1)
;
ldr r2, =BBU_MMC_EGS ; Erase Group Size saved here here
ldrh r0, [r1] ; Fetch this data
ldr r1, [r1, #BBU_MMC_BLKLEN_offset] ; Get block length of this MMC
48 ldmfd sp!, {r2-r6, pc} ; Restore registers and return
ENDFUNC
;
;*********************************************************************************
;
; *****************
; * *
; * BBU_MMC_Write * WRITE A SINGLE BLOCK OF DATA TO THE MMC
; * *
; *****************
;
; This subroutine will write a block of data to a MMC that has already been
; initalized with the BBU IMMC command. (Under development)
;
; PARAMETER PASSING:
;
; INPUT - r0 = Source address of data to be written to MMC/SD device
; r1 = Sector number in the MMC/SD device to be written to
;
; OUTPUT - r0 = 0xFF for BBU detected error. Otherwise...
; r0 = the sector length of the device (in bytes)
;
BBU_MMC_Write FUNCTION
stmfd sp!, {r1-r5, lr} ; Save used registers
mov r4, r1 ; Save off sector number to be written
mov r5, r0 ; Save source address in r5
;
; Get MMC controller base address
;
ldr r1, =BBU_MMC1_PHYSICAL_BASE ; Load base address for MMC1 controller
ldr r3, =BBU_MMC_lastInit ; Address where # of last MMC port initialized is
ldrb r2, [r3] ; Fetch MMC # last initialized
cmp r2, #2 ; Was MMC2 the last MMC initialized?
ldreq r1, =BBU_MMC2_PHYSICAL_BASE ; YES - Load base address for MMC2 controller
;
; Prepare to write a single sector to the selected card by sending the
; block length.
;
ldr r0, [r1, #BBU_MMC_BLKLEN_offset] ; Get block length of this MMC
mov r1, #16 ; Command to be sent (CMD016 = SET BLOCKLEN)
ldr r2, =bbu_MiscBuffer ; Address where CMD reply is to be sent
bl BBU_MMC_Cmd ; Send out command & fetch data
cmp r0, #0xFF ; Error detected?
beq %F58 ; Yes - exit with error code in r0
mov r0, #0x1 ; Set up for a short delay
bl BBU_msWait ; Delay r0 milliseconds
;
; Set up to write a block to the MMC
;
ldr r0, [r1, #BBU_MMC_BLKLEN_offset] ; Get block length of this MMC
mul r0, r0, r4 ; Calculate the starting address
mov r1, #24 ; Command to be sent (CMD024 = WRITE BLOCK)
ldr r2, =bbu_MiscBuffer ; Address where CMD reply is to be sent
bl BBU_MMC_Cmd ; Send out command & fetch data
cmp r0, #0xFF ; Error detected?
beq %F58 ; Yes - exit with error code in r0
;
; Monitor MMC_I_REG for requests to write data to the MMC
; Note: Bit is set when there are 32 bytes ready to write (apparently).
;
ldr r3, [r1, #BBU_MMC_BLKLEN_offset] ; Get block length of this MMC
52 ldr r2, [r1, #BBU_MMC_I_REG_offset] ; Fetch interrupt register status
ands r4, r2, #BBU_MMC_WR_REQ ; Write request?
beq %B52 ; No - keep looping
;
; Move 32 bytes of data from the memory address provided by caller then
; wait for another write request by the controller.
;
mov r4, #0x8 ; Move 32 bytes (8 doublewords)
54 ldr r2, [r5], #4 ; Fetch data from memory
str r2, [r1, #BBU_MMC_TXFIFO_offset] ; Store in transmit buffer
subs r4, r4, #1 ; decrement doubleword transfer count
bne %B54 ; Loop until done
subs r3, r3, #0x20 ; Decrement total byte transfer count from block size
bne %B52 ; Write data until block is transfered
mov r0, #0x1 ; Set up for a short delay
bl BBU_msWait ; Delay r0 milliseconds
mov r0, #1 ; Set up a delay time
bl BBU_msWait ; Delay for r0 millisecoonds
mov r4, #BBU_stop_clk ; Set the stop clock bit
str r4, [r1, #BBU_MMC_STRPCL_offset] ; Stop the clock
ldr r0, [r1, #BBU_MMC_BLKLEN_offset] ; Get block length of this MMC
58 ldmfd sp!, {r1-r5, pc} ; Restore registers and return
ENDFUNC
BBU_MMC_CMDAT_value DCD 0 ; Optional bits to be ORed into command
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -