F1C100S >> Assembly

SDMMC


參考資料:
1. pdf
2. emmc_e
3. lichee
4. mangopi_r
5. allwinner
6. sdcard_command_list

暫存器


腳位


main.s

  .global _start
   
  .equiv SDC0_BASE,             0x01c0f000
  .equiv CCU_BASE,              0x01c20000
  .equiv PIO_BASE,              0x01c20800
  .equiv UART0_BASE,            0x01c25000

  .equiv PA,                    (0 * 0x24)
  .equiv PE,                    (4 * 0x24)
  .equiv PF,                    (5 * 0x24)
  .equiv PIO_CFG0,              0x00
  .equiv PIO_DATA,              0x10

  .equiv PLL_PERIPH_CTRL_REG,   0x0028
  .equiv AHB_APB_HCLKC_CFG_REG, 0x0054
  .equiv BUS_CLK_GATING_REG0,   0x0060
  .equiv BUS_CLK_GATING_REG2,   0x0068
  .equiv SDMMC0_CLK_REG,        0x0088
  .equiv BUS_SOFT_RST_REG0,     0x02c0
  .equiv BUS_SOFT_RST_REG2,     0x02d0

  .equiv UART_RBR,              0x0000
  .equiv UART_DLL,              0x0000
  .equiv UART_DLH,              0x0004
  .equiv UART_IER,              0x0004
  .equiv UART_IIR,              0x0008
  .equiv UART_LCR,              0x000c
  .equiv UART_MCR,              0x0010
  .equiv UART_USR,              0x007c

  .equiv SD_GCTL_REG,           0x0000
  .equiv SD_CKCR_REG,           0x0004
  .equiv SD_TMOR_REG,           0x0008
  .equiv SD_BWDR_REG,           0x000c
  .equiv SD_BKSR_REG,           0x0010
  .equiv SD_BYCR_REG,           0x0014
  .equiv SD_CMDR_REG,           0x0018
  .equiv SD_CAGR_REG,           0x001c
  .equiv SD_RESP0_REG,          0x0020
  .equiv SD_RESP1_REG,          0x0024
  .equiv SD_RESP2_REG,          0x0028
  .equiv SD_RESP3_REG,          0x002c
  .equiv SD_IMKR_REG,           0x0030
  .equiv SD_MISR_REG,           0x0034
  .equiv SD_RISR_REG,           0x0038
  .equiv SD_STAR_REG,           0x003c
  .equiv SD_FWLR_REG,           0x0040
  .equiv SD_FUNS_REG,           0x0044
  .equiv SD_CBCR_REG,           0x0048
  .equiv SD_BBCR_REG,           0x004c
  .equiv SD_DBGC_REG,           0x0050
  .equiv SD_A12A_REG,           0x0058
  .equiv SD_HWRST_REG,          0x0078
  .equiv SD_DMAC_REG,           0x0080
  .equiv SD_DLBA_REG,           0x0084
  .equiv SD_IDST_REG,           0x0088
  .equiv SD_IDIE_REG,           0x008c
  .equiv SD_CHDA_REG,           0x0090
  .equiv SD_CBDA_REG,           0x0094
  .equiv CARD_THLDC_REG,        0x0100
  .equiv EMMC_DSBD_REG,         0x010c
  .equiv SD_FIFO_REG,           0x0200
 
  .equiv MMC_RSP_NONE,                 (0)
  .equiv MMC_RSP_R1,                   (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
  .equiv MMC_RSP_R1b,                  (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE | MMC_RSP_BUSY)
  .equiv MMC_RSP_R2,                   (MMC_RSP_PRESENT | MMC_RSP_136 | MMC_RSP_CRC)
  .equiv MMC_RSP_R3,                   (MMC_RSP_PRESENT)
  .equiv MMC_RSP_R4,                   (MMC_RSP_PRESENT)
  .equiv MMC_RSP_R5,                   (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
  .equiv MMC_RSP_R6,                   (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
  .equiv MMC_RSP_R7,                   (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)

  .equiv MMC_RSP_PRESENT,              (1 << 0)
  .equiv MMC_RSP_136,                  (1 << 1)
  .equiv MMC_RSP_CRC,                  (1 << 2)
  .equiv MMC_RSP_BUSY,                 (1 << 3)
  .equiv MMC_RSP_OPCODE,               (1 << 4)

  .equiv MMC_CMD_GO_IDLE_STATE,        0
  .equiv MMC_CMD_SEND_OP_COND,         1
  .equiv MMC_CMD_ALL_SEND_CID,         2
  .equiv MMC_CMD_SET_RELATIVE_ADDR,    3
  .equiv MMC_CMD_SET_DSR,              4
  .equiv MMC_CMD_SWITCH,               6
  .equiv MMC_CMD_SELECT_CARD,          7
  .equiv MMC_CMD_SEND_EXT_CSD,         8
  .equiv MMC_CMD_SEND_CSD,             9
  .equiv MMC_CMD_SEND_CID,             10
  .equiv MMC_CMD_STOP_TRANSMISSION,    12
  .equiv MMC_CMD_SEND_STATUS,          13
  .equiv MMC_CMD_SET_BLOCKLEN,         16
  .equiv MMC_CMD_READ_SINGLE_BLOCK,    17
  .equiv MMC_CMD_READ_MULTIPLE_BLOCK,  18
  .equiv MMC_CMD_SET_BLOCK_COUNT,      23
  .equiv MMC_CMD_WRITE_SINGLE_BLOCK,   24
  .equiv MMC_CMD_WRITE_MULTIPLE_BLOCK, 25
  .equiv MMC_CMD_ERASE_GROUP_START,    35
  .equiv MMC_CMD_ERASE_GROUP_END,      36
  .equiv MMC_CMD_ERASE,                38
  .equiv MMC_CMD_APP_CMD,              55
  .equiv MMC_CMD_SPI_READ_OCR,         58
  .equiv MMC_CMD_SPI_CRC_ON_OFF,       59
  .equiv MMC_CMD_RES_MAN,              62
  .equiv MMC_VDD_32_33,                0x00100000
  .equiv MMC_VDD_33_34,                0x00200000

  .equiv SD_CMD_SEND_RELATIVE_ADDR,    3
  .equiv SD_CMD_SWITCH_FUNC,           6
  .equiv SD_CMD_SEND_IF_COND,          8
  .equiv SD_CMD_SWITCH_UHS18V,         11
  .equiv SD_CMD_APP_SET_BUS_WIDTH,     6
  .equiv SD_CMD_APP_SD_STATUS,         13
  .equiv SD_CMD_ERASE_WR_BLK_START,    32
  .equiv SD_CMD_ERASE_WR_BLK_END,      33
  .equiv SD_CMD_APP_SEND_OP_COND,      41
  .equiv SD_CMD_APP_SEND_SCR,          51

  .equiv OCR_BUSY,                     0x80000000
  .equiv OCR_HCS,                      0x40000000
  .equiv OCR_VOLTAGE_MASK,             0x007fff80
  .equiv OCR_ACCESS_MODE,              0x60000000

  .equiv MMC_STATUS_SWITCH_ERROR,      (0x01 << 7)
  .equiv MMC_STATUS_RDY_FOR_DATA,      (0x01 << 8)
  .equiv MMC_STATUS_CURR_STATE,        (0x0f << 9)
  .equiv MMC_STATUS_ERROR,             (0x01 << 19)
  .equiv MMC_STATE_PRG,                (0x07 << 9)

  .equiv SUNXI_MMC_CMD_RESP_EXPIRE,          (1 << 6)
  .equiv SUNXI_MMC_CMD_LONG_RESPONSE,        (1 << 7)
  .equiv SUNXI_MMC_CMD_CHK_RESPONSE_CRC,     (1 << 8)
  .equiv SUNXI_MMC_CMD_DATA_EXPIRE,          (1 << 9)
  .equiv SUNXI_MMC_CMD_WRITE,                (1 << 10)
  .equiv SUNXI_MMC_CMD_AUTO_STOP,            (1 << 12)
  .equiv SUNXI_MMC_CMD_WAIT_PRE_OVER,        (1 << 13)
  .equiv SUNXI_MMC_CMD_SEND_INIT_SEQ,        (1 << 15)
  .equiv SUNXI_MMC_CMD_UPCLK_ONLY,           (1 << 21)
  .equiv SUNXI_MMC_CMD_START,                (1 << 31)
  .equiv SUNXI_MMC_RINT_RESP_ERROR,          (1 << 1)
  .equiv SUNXI_MMC_RINT_COMMAND_DONE,        (1 << 2)
  .equiv SUNXI_MMC_RINT_DATA_OVER,           (1 << 3)
  .equiv SUNXI_MMC_RINT_TX_DATA_REQUEST,     (1 << 4)
  .equiv SUNXI_MMC_RINT_RX_DATA_REQUEST,     (1 << 5)
  .equiv SUNXI_MMC_RINT_RESP_CRC_ERROR,      (1 << 6)
  .equiv SUNXI_MMC_RINT_DATA_CRC_ERROR,      (1 << 7)
  .equiv SUNXI_MMC_RINT_RESP_TIMEOUT,        (1 << 8)
  .equiv SUNXI_MMC_RINT_DATA_TIMEOUT,        (1 << 9)
  .equiv SUNXI_MMC_RINT_VOLTAGE_CHANGE_DONE, (1 << 10)
  .equiv SUNXI_MMC_RINT_FIFO_RUN_ERROR,      (1 << 11)
  .equiv SUNXI_MMC_RINT_HARD_WARE_LOCKED,    (1 << 12)
  .equiv SUNXI_MMC_RINT_START_BIT_ERROR,     (1 << 13)
  .equiv SUNXI_MMC_RINT_AUTO_COMMAND_DONE,   (1 << 14)
  .equiv SUNXI_MMC_RINT_END_BIT_ERROR,       (1 << 15)
  .equiv SUNXI_MMC_RINT_SDIO_INTERRUPT,      (1 << 16)
  .equiv SUNXI_MMC_RINT_CARD_INSERT,         (1 << 30)
  .equiv SUNXI_MMC_RINT_CARD_REMOVE,         (1 << 31)
  .equiv SUNXI_MMC_GCTRL_SOFT_RESET,         (1 << 0)
  .equiv SUNXI_MMC_GCTRL_FIFO_RESET,         (1 << 1)
  .equiv SUNXI_MMC_GCTRL_DMA_RESET,          (1 << 2)
  .equiv SUNXI_MMC_GCTRL_RESET,              (SUNXI_MMC_GCTRL_SOFT_RESET | SUNXI_MMC_GCTRL_FIFO_RESET | SUNXI_MMC_GCTRL_DMA_RESET)
  .equiv SUNXI_MMC_GCTRL_DMA_ENABLE,         (1 << 5)
  .equiv SUNXI_MMC_GCTRL_ACCESS_BY_AHB,      (1 << 31)
  .equiv SUNXI_MMC_CLK_ENABLE,               (1 << 16)

  .equiv SUNXI_MMC_STATUS_RXWL_FLAG,         (1 << 0)
  .equiv SUNXI_MMC_STATUS_TXWL_FLAG,         (1 << 1)
  .equiv SUNXI_MMC_STATUS_FIFO_EMPTY,        (1 << 2)
  .equiv SUNXI_MMC_STATUS_FIFO_FULL,         (1 << 3)
  .equiv SUNXI_MMC_STATUS_CARD_PRESENT,      (1 << 8)
  .equiv SUNXI_MMC_STATUS_CARD_DATA_BUSY,    (1 << 9)
  .equiv SUNXI_MMC_STATUS_DATA_FSM_BUSY,     (1 << 10)

  .arm
  .text
_start:
  .long 0xea000016
  .byte 'e', 'G', 'O', 'N', '.', 'B', 'T', '0'
  .long 0, __spl_size
  .byte 'S', 'P', 'L', 2
  .long 0, 0
  .long 0, 0, 0, 0, 0, 0, 0, 0
  .long 0, 0, 0, 0, 0, 0, 0, 0
    
_vector:
  b reset
  b .
  b .
  b .
  b .
  b .
  b .
  b .
    
reset:
  bl ccu_init
  bl uart_init
  bl sdcard_init
  
  ldr r0, =MMC_CMD_GO_IDLE_STATE
  mov r1, #0
  ldr r2, =MMC_RSP_NONE
  mov r3, #0
  bl sdcard_cmd

  ldr r0, =SD_CMD_SEND_IF_COND
  ldr r1, =0x1aa
  ldr r2, =MMC_RSP_R7
  mov r3, #0
  bl sdcard_cmd

0:
  ldr r0, =MMC_CMD_APP_CMD
  mov r1, #0
  ldr r2, =MMC_RSP_R1
  mov r3, #0
  bl sdcard_cmd

  ldr r0, =SD_CMD_APP_SEND_OP_COND
  ldr r1, =OCR_HCS | MMC_VDD_32_33 | MMC_VDD_33_34
  ldr r2, =MMC_RSP_R3
  mov r3, #0
  bl sdcard_cmd

  tst r0, #OCR_BUSY
  beq 0b

  ldr r0, =MMC_CMD_ALL_SEND_CID
  mov r1, #0
  ldr r2, =MMC_RSP_R2
  mov r3, #0
  bl sdcard_cmd
  
  ldr r0, =SD_CMD_SEND_RELATIVE_ADDR
  mov r1, #0
  ldr r2, =MMC_RSP_R6
  mov r3, #0
  bl sdcard_cmd
  
  mov r1, r0, lsr #8
  lsl r1, #8
  ldr r2, =mmc_rca
  str r1, [r2]

  ldr r0, =MMC_CMD_SEND_CSD
  ldr r2, =MMC_RSP_R2
  mov r3, #0
  bl sdcard_cmd
  
  ldr r0, =MMC_CMD_SELECT_CARD
  ldr r1, =mmc_rca
  ldr r1, [r1]
  ldr r2, =MMC_RSP_R1
  mov r3, #0
  bl sdcard_cmd
 
  ldr r0, =MMC_CMD_APP_CMD
  ldr r1, =mmc_rca
  ldr r1, [r1]
  ldr r2, =MMC_RSP_R1
  mov r3, #0
  bl sdcard_cmd

  ldr r0, =MMC_CMD_SWITCH
  mov r1, #2
  ldr r2, =MMC_RSP_R1b
  mov r3, #0
  bl sdcard_cmd
  bl sdcard_wait
  
  ldr r4, =SDC0_BASE
  mov r1, #1
  str r1, [r4, #SD_BWDR_REG]
  
  ldr r0, =MMC_CMD_SET_BLOCKLEN
  mov r1, #512
  ldr r2, =MMC_RSP_R1
  mov r3, #0
  bl sdcard_cmd

  ldr r0, =SD_CMD_ERASE_WR_BLK_START
  ldr r1, =0x2000
  ldr r2, =MMC_RSP_R1
  mov r3, #0
  bl sdcard_cmd
  
  ldr r0, =SD_CMD_ERASE_WR_BLK_END
  ldr r1, =0x2000 + 512
  ldr r2, =MMC_RSP_R1
  mov r3, #0
  bl sdcard_cmd
  
  ldr r0, =MMC_CMD_ERASE
  mov r1, #0
  ldr r2, =MMC_RSP_R1b
  mov r3, #0
  bl sdcard_cmd
  bl sdcard_wait
  
  ldr r1, =mmc_wr
  mov r2, #512
  mov r3, #0
0:
  str r3, [r1]
  add r3, #1
  add r1, #4
  subs r2, #4
  bne 0b
  
  ldr r0, =MMC_CMD_WRITE_SINGLE_BLOCK
  ldr r1, =0x2000
  ldr r2, =MMC_RSP_R1
  ldr r3, =512
  bl sdcard_cmd
  bl sdcard_wait
 
  ldr r1, =mmc_rd
  mov r2, #512
  mov r3, #0
0:
  str r3, [r1]
  add r1, #4
  subs r2, #4
  bne 0b

  ldr r0, =MMC_CMD_READ_SINGLE_BLOCK
  ldr r1, =0x2000
  ldr r2, =MMC_RSP_R1
  ldr r3, =512
  bl sdcard_cmd

  ldr r4, =mmc_rd
  mov r5, #512
0:
  ldr r0, [r4]
  bl uart_4byte
  add r4, #4
  subs r5, #4
  bne 0b
  b .

sdcard_wait:
  push {lr}
0:
  ldr r0, =MMC_CMD_SEND_STATUS
  ldr r1, =mmc_rca
  ldr r1, [r1]
  ldr r2, =MMC_RSP_R1
  mov r3, #0
  bl sdcard_cmd
  tst r0, #MMC_STATUS_RDY_FOR_DATA
  beq 0b
  tst r0, #MMC_STATE_PRG
  beq 0b
  pop {pc}

sdcard_wr:
  push {r4, lr}
  ldr r4, =SDC0_BASE
  ldr r1, =mmc_wr
0:
  ldr r2, [r4, #SD_STAR_REG]
  tst r2, #SUNXI_MMC_STATUS_FIFO_FULL
  bne 0b
  
  ldr r2, [r1]
  str r2, [r4, #SD_FIFO_REG]
  add r1, #4
  subs r0, #4
  bne 0b
  pop {r4, pc}
  
sdcard_rd:
  push {r4, lr}
  ldr r4, =SDC0_BASE
  ldr r1, =mmc_rd
0:
  ldr r2, [r4, #SD_STAR_REG]
  tst r2, #SUNXI_MMC_STATUS_FIFO_EMPTY
  bne 0b

  ldr r2, [r4, #SD_FIFO_REG]
  str r2, [r1]
  add r1, #4
  subs r0, #4
  bne 0b
  pop {r4, pc}
  
sdcard_cmd:
  push {r4, r5, r6, r7, lr}
  ldr r4, =SDC0_BASE
  
  mov r5, r2
  mov r6, #SUNXI_MMC_RINT_COMMAND_DONE
  mov r7, r0

  cmp r7, #MMC_CMD_GO_IDLE_STATE
  orreq r0, #SUNXI_MMC_CMD_SEND_INIT_SEQ
  orr r0, #SUNXI_MMC_CMD_START
  tst r2, #MMC_RSP_PRESENT
  orrne r0, #SUNXI_MMC_CMD_RESP_EXPIRE
  tst r2, #MMC_RSP_136
  orrne r0, #SUNXI_MMC_CMD_LONG_RESPONSE
  tst r2, #MMC_RSP_CRC
  orrne r0, #SUNXI_MMC_CMD_CHK_RESPONSE_CRC

  cmp r7, #MMC_CMD_WRITE_SINGLE_BLOCK
  orreq r0, #SUNXI_MMC_CMD_WRITE
  
  cmp r3, #0
  orrne r6, #SUNXI_MMC_RINT_DATA_OVER
  strne r3, [r4, #SD_BKSR_REG]
  strne r3, [r4, #SD_BYCR_REG]
  orrne r0, #SUNXI_MMC_CMD_DATA_EXPIRE
  orrne r0, #SUNXI_MMC_CMD_WAIT_PRE_OVER
  str r1, [r4, #SD_CAGR_REG]
  str r0, [r4, #SD_CMDR_REG]
  beq 0f

  ldr r1, [r4, #SD_GCTL_REG]
  orr r1, #SUNXI_MMC_GCTRL_ACCESS_BY_AHB
  str r1, [r4, #SD_GCTL_REG]

  mov r0, r3
  cmp r7, #MMC_CMD_WRITE_SINGLE_BLOCK
  bleq sdcard_wr
  blne sdcard_rd

0:
  ldr r1, [r4, #SD_RISR_REG]
  tst r1, r6
  beq 0b

  ldr r1, =0xffffffff
  str r1, [r4, #SD_RISR_REG]

  ldr r1, [r4, #SD_GCTL_REG]
  orr r1, #SUNXI_MMC_GCTRL_FIFO_RESET
  str r1, [r4, #SD_GCTL_REG]
 
  tst r5, #MMC_RSP_136
  ldrne r3, [r4, #SD_RESP0_REG]
  ldrne r2, [r4, #SD_RESP1_REG]
  ldrne r1, [r4, #SD_RESP2_REG]
  ldrne r0, [r4, #SD_RESP3_REG]
  ldreq r0, [r4, #SD_RESP0_REG]
  ldreq r1, [r4, #SD_RESP1_REG]
  ldreq r2, [r4, #SD_RESP2_REG]
  ldreq r3, [r4, #SD_RESP3_REG]
  pop {r4, r5, r6, r7, pc}

ccu_init:
  push {r4, lr}
  ldr r4, =CCU_BASE
  ldr r1, =0x80041800
  str r1, [r4, #PLL_PERIPH_CTRL_REG]
0:
  ldr r1, [r4, #PLL_PERIPH_CTRL_REG]
  tst r1, #(1 << 28)
  beq 0b

  ldr r1, =0x00003180
  str r1, [r4, #AHB_APB_HCLKC_CFG_REG]
  pop {r4, pc}

sdcard_init:
  push {r4, lr}
  ldr r4, =PIO_BASE
  ldr r1, =0x222222
  str r1, [r4, #(PF + PIO_CFG0)]

  ldr r4, =CCU_BASE
  ldr r1, [r4, #BUS_CLK_GATING_REG0]
  orr r1, #(1 << 8)
  str r1, [r4, #BUS_CLK_GATING_REG0]

  ldr r1, [r4, #BUS_SOFT_RST_REG0]
  orr r1, #(1 << 8)
  str r1, [r4, #BUS_SOFT_RST_REG0]
 
  ldr r1, =(1 << 31) | (1 << 24) | (3 << 0)
  str r1, [r4, #SDMMC0_CLK_REG]
  
  ldr r4, =SDC0_BASE
  ldr r1, =SUNXI_MMC_GCTRL_RESET
  str r1, [r4, #SD_GCTL_REG]
  
  ldr r1, =SUNXI_MMC_CLK_ENABLE
  str r1, [r4, #SD_CKCR_REG]
  
  ldr r1, =SUNXI_MMC_CMD_START | SUNXI_MMC_CMD_UPCLK_ONLY | SUNXI_MMC_CMD_WAIT_PRE_OVER
  str r1, [r4, #SD_CMDR_REG]
0:
  ldr r1, [r4, #SD_CMDR_REG]
  tst r1, #SUNXI_MMC_CMD_START
  bne 0b
  ldr r1, =0xffffffff
  str r1, [r4, #SD_RISR_REG]
  
  ldr r1, =0
  str r1, [r4, #SD_BWDR_REG]
  pop {r4, pc}

uart_init:
  push {r4, lr}
  ldr r4, =PIO_BASE
  ldr r1, [r4, #(PE + PIO_CFG0)]
  bic r1, #0xff
  orr r1, #0x55
  str r1, [r4, #(PE + PIO_CFG0)]

  ldr r4, =CCU_BASE
  ldr r1, [r4, #BUS_CLK_GATING_REG2]
  orr r1, #(1 << 20)
  str r1, [r4, #BUS_CLK_GATING_REG2]

  ldr r1, [r4, #BUS_SOFT_RST_REG2]
  orr r1, #(1 << 20)
  str r1, [r4, #BUS_SOFT_RST_REG2]

  ldr r4, =UART0_BASE
  ldr r1, =0x00
  str r1, [r4, #UART_IER]
  ldr r1, =0xf7
  str r1, [r4, #UART_IIR]
  ldr r1, =0x00
  str r1, [r4, #UART_MCR]
  ldr r1, [r4, #UART_LCR]
  orr r1, #(1 << 7)
  str r1, [r4, #UART_LCR]
  ldr r1, =54
  str r1, [r4, #UART_DLL]
  ldr r1, =0x00
  str r1, [r4, #UART_DLH]
  ldr r1, [r4, #UART_LCR]
  bic r1, #(1 << 7)
  str r1, [r4, #UART_LCR]
  ldr r1, [r4, #UART_LCR]
  bic r1, #0x1f
  orr r1, #0x03
  str r1, [r4, #UART_LCR]
  pop {r4, pc}

uart_byte:
  push {r4, lr}
  ldr r4, =UART0_BASE
0:
  ldr r1, [r4, #UART_USR]
  tst r1, #(1 << 1)
  beq 0b
  strb r0, [r4, #UART_RBR]
  pop {r4, pc}

uart_4byte:
  push {r4, lr}
  mov r4, r0
  lsr r0, #24
  bl uart_byte

  mov r0, r4
  lsr r0, #16
  bl uart_byte
  
  mov r0, r4
  lsr r0, #8
  bl uart_byte
  
  mov r0, r4
  bl uart_byte
  pop {r4, pc}

uart_resp:
  push {r4, r5, r6, r7, lr}
  mov r4, r0
  mov r5, r1
  mov r6, r2
  mov r7, r3

  mov r0, r4
  bl uart_4byte

  mov r0, r5
  bl uart_4byte

  mov r0, r6
  bl uart_4byte

  mov r0, r7
  bl uart_4byte
  pop {r4, r5, r6, r7, pc}

  .data
mmc_rca: .word 0
mmc_rd: .skip 512
mmc_wr: .skip 512
  .end

完成


返回上一頁