參考資料:
http://nano.lichee.pro/
https://mangopi.org/mangopi_r
http://www.zeroplus.com.tw/E-paper/200907/image/SD_command%20and%20register%20list.pdf
暫存器
腳位
main.s
.global _start .equiv SDC0_BASE, 0x01c0f000 .equiv CCU_BASE, 0x01c20000 .equiv PIO_BASE, 0x01c20800 .equiv UART1_BASE, 0x01c25400 .equiv PA, (0 * 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, #(PA + PIO_CFG0)] bic r1, #0xff00 orr r1, #0x5500 str r1, [r4, #(PA + PIO_CFG0)] ldr r4, =CCU_BASE ldr r1, [r4, #BUS_CLK_GATING_REG2] orr r1, #(1 << 21) str r1, [r4, #BUS_CLK_GATING_REG2] ldr r1, [r4, #BUS_SOFT_RST_REG2] orr r1, #(1 << 21) str r1, [r4, #BUS_SOFT_RST_REG2] ldr r4, =UART1_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, =UART1_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
完成