Miyoo >> Assembly
SPI(NOR Flash)
參考資料:
1. pdf
2. lichee
3. mangopi_r
4. allwinner
SPI0腳位
SPI0_CLK | PC0 |
---|---|
SPI0_CS | PC1 |
SPI0_MISO | PC2 |
SPI0_MOSI | PC3 |
暫存器
初始步驟:
1. 設定SPI Mode為Master
2. 設定DHB模式(避免接收多餘資料)
3. 設定CS_Level為Low
4. 設定CS_Owner為SPI Controller
5. 設定SPI CDR1為50MHz
傳送、接收步驟:
1. 清除RX、TX FIFO(FCR_REG)
2. 設定TXRX全部數量(MBC_REG)
3. 設定TX數量(MTC_REG)
4. 設定TX數量(BCC_REG)
5. 開始傳送接收(TCR_REG.XCH)
6. 等待結束後,從RXD提取資料
main.s
.global _start .equiv SPI0_BASE, 0x01c05000 .equiv CCU_BASE, 0x01c20000 .equiv PIO_BASE, 0x01c20800 .equiv UART1_BASE, 0x01c25400 .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 BUS_SOFT_RST_REG0, 0x02c0 .equiv BUS_SOFT_RST_REG2, 0x02d0 .equiv PA, (0x24 * 0) .equiv PC, (0x24 * 2) .equiv PE, (0x24 * 4) .equiv PIO_CFG0, 0x0000 .equiv PIO_DATA, 0x0010 .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 SPI_GCR, 0x0004 .equiv SPI_TCR, 0x0008 .equiv SPI_IER, 0x0010 .equiv SPI_ISR, 0x0014 .equiv SPI_FCR, 0x0018 .equiv SPI_FSR, 0x001c .equiv SPI_WCR, 0x0020 .equiv SPI_CCR, 0x0024 .equiv SPI_MBC, 0x0030 .equiv SPI_MTC, 0x0034 .equiv SPI_BCC, 0x0038 .equiv SPI_TXD, 0x0200 .equiv SPI_RXD, 0x0300 .equiv CMD_PAGE_PROGRAM, 0x02 .equiv CMD_WRIRE_ENABLE, 0x06 .equiv CMD_WRITE_DISABLE, 0x04 .equiv CMD_READ_STATUS_R1, 0x05 .equiv CMD_READ_STATUS_R2, 0x35 .equiv CMD_READ_DATA, 0x03 .equiv CMD_FAST_READ, 0x0b .equiv CMD_SECTOR_ERASE, 0x20 .equiv CMD_CHIP_ERASE, 0xc7 .equiv CMD_READ_UNIQUE_ID, 0x4b .equiv CMD_JEDEC_ID, 0x9f .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 spi_init bl uart_init bl spi_read_jid bl spi_read_uid ldr r0, =0 ldr r1, =64 bl spi_read_data bl uart_buf ldr r0, =0 bl spi_erase_sector ldr r0, =0 ldr r1, =64 bl spi_read_data bl uart_buf ldr r1, =64 ldr r2, =spi_buf mov r3, #0 0: strb r3, [r2] add r2, #1 add r3, #1 subs r1, #1 bne 0b ldr r0, =0 ldr r1, =64 bl spi_write_data ldr r0, =0 ldr r1, =64 bl spi_read_data bl uart_buf b . ccu_init: push {r4, lr} ldr r4, =CCU_BASE ldr r1, =0x80041800 str r1, [r4, #PLL_PERIPH_CTRL_REG] ldr r1, =0x00003180 str r1, [r4, #AHB_APB_HCLKC_CFG_REG] pop {r4, pc} spi_init: push {r4, lr} ldr r4, =CCU_BASE ldr r1, [r4, #BUS_CLK_GATING_REG0] orr r1, #(1 << 20) str r1, [r4, #BUS_CLK_GATING_REG0] ldr r1, [r4, #BUS_SOFT_RST_REG0] orr r1, #(1 << 20) str r1, [r4, #BUS_SOFT_RST_REG0] ldr r0, =PIO_BASE ldr r1, [r0, #(PC + PIO_CFG0)] ldr r2, =0xffff bic r1, r2 ldr r2, =0x2222 orr r1, r2 str r1, [r0, #(PC + PIO_CFG0)] ldr r4, =SPI0_BASE ldr r1, =(1 << 1) | (1 << 0) str r1, [r4, #SPI_GCR] ldr r1, =(1 << 2) | (1 << 8) str r1, [r4, #SPI_TCR] ldr r1, =(1 << 8) str r1, [r4, #SPI_CCR] ldr r2, =(1 << 31) | (1 << 15) str r2, [r4, #SPI_FCR] 0: ldr r1, [r4, #SPI_FCR] tst r1, r2 bne 0b pop {r4, pc} uart_init: push {r4, lr} 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, =PIO_BASE ldr r1, [r4, #(PA + PIO_CFG0)] bic r1, #0xff00 orr r1, #0x5500 str r1, [r4, #(PA + PIO_CFG0)] 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_buf: push {r4, r5, lr} ldr r4, =64 ldr r5, =spi_buf 0: ldrb r0, [r5] bl uart_byte add r5, #1 subs r4, #1 bne 0b pop {r4, r5, pc} spi_read_jid: push {r4, lr} ldr r4, =SPI0_BASE ldr r1, =5 str r1, [r4, #SPI_MBC] ldr r1, =1 str r1, [r4, #SPI_MTC] ldr r1, =1 str r1, [r4, #SPI_BCC] ldrb r1, =CMD_JEDEC_ID strb r1, [r4, #SPI_TXD] ldr r1, [r4, #SPI_TCR] orr r1, #(1 << 31) str r1, [r4, #SPI_TCR] 0: ldr r1, [r4, #SPI_TCR] tst r1, #(1 << 31) bne 0b ldr r2, =spi_jid ldr r3, =4 0: ldrb r1, [r4, #SPI_RXD] strb r1, [r2] add r2, #1 subs r3, #1 bne 0b pop {r4, pc} spi_read_uid: push {r4, lr} ldr r4, =SPI0_BASE ldr r1, =13 str r1, [r4, #SPI_MBC] ldr r1, =1 str r1, [r4, #SPI_MTC] ldr r1, =1 str r1, [r4, #SPI_BCC] ldrb r1, =CMD_READ_UNIQUE_ID strb r1, [r4, #SPI_TXD] ldr r1, [r4, #SPI_TCR] orr r1, #(1 << 31) str r1, [r4, #SPI_TCR] 0: ldr r1, [r4, #SPI_TCR] tst r1, #(1 << 31) bne 0b ldr r2, =spi_uid ldr r3, =12 0: ldrb r1, [r4, #SPI_RXD] strb r1, [r2] add r2, #1 subs r3, #1 bne 0b pop {r4, pc} spi_read_data: push {r4, r5, lr} ldr r4, =SPI0_BASE mov r5, r1 add r1, #4 str r1, [r4, #SPI_MBC] ldr r1, =4 str r1, [r4, #SPI_MTC] ldr r1, =4 str r1, [r4, #SPI_BCC] ldrb r1, =CMD_READ_DATA strb r1, [r4, #SPI_TXD] mov r1, r0 lsr r0, #16 strb r0, [r4, #SPI_TXD] mov r0, r1 lsr r0, #8 strb r0, [r4, #SPI_TXD] mov r0, r1 strb r0, [r4, #SPI_TXD] ldr r1, [r4, #SPI_TCR] orr r1, #(1 << 31) str r1, [r4, #SPI_TCR] 0: ldr r1, [r4, #SPI_TCR] tst r1, #(1 << 31) bne 0b ldr r2, =spi_buf mov r3, r5 0: ldrb r1, [r4, #SPI_RXD] strb r1, [r2] add r2, #1 subs r3, #1 bne 0b pop {r4, r5, pc} spi_write_enable: push {r4, lr} ldr r4, =SPI0_BASE ldr r1, =1 str r1, [r4, #SPI_MBC] ldr r1, =1 str r1, [r4, #SPI_MTC] ldr r1, =1 str r1, [r4, #SPI_BCC] ldrb r1, =CMD_WRIRE_ENABLE strb r1, [r4, #SPI_TXD] ldr r1, [r4, #SPI_TCR] orr r1, #(1 << 31) str r1, [r4, #SPI_TCR] 0: ldr r1, [r4, #SPI_TCR] tst r1, #(1 << 31) bne 0b pop {r4, pc} spi_write_disable: push {r4, lr} ldr r4, =SPI0_BASE ldr r1, =1 str r1, [r4, #SPI_MBC] ldr r1, =1 str r1, [r4, #SPI_MTC] ldr r1, =1 str r1, [r4, #SPI_BCC] ldrb r1, =CMD_WRITE_DISABLE strb r1, [r4, #SPI_TXD] ldr r1, [r4, #SPI_TCR] orr r1, #(1 << 31) str r1, [r4, #SPI_TCR] 0: ldr r1, [r4, #SPI_TCR] tst r1, #(1 << 31) bne 0b pop {r4, pc} spi_is_busy: push {r4, lr} ldr r4, =SPI0_BASE ldr r1, =2 str r1, [r4, #SPI_MBC] ldr r1, =1 str r1, [r4, #SPI_MTC] ldr r1, =1 str r1, [r4, #SPI_BCC] ldrb r1, =CMD_READ_STATUS_R1 strb r1, [r4, #SPI_TXD] ldr r1, [r4, #SPI_TCR] orr r1, #(1 << 31) str r1, [r4, #SPI_TCR] 0: ldr r1, [r4, #SPI_TCR] tst r1, #(1 << 31) bne 0b ldrb r0, [r4, #SPI_RXD] and r0, #1 pop {r4, pc} spi_erase_sector: push {r4, lr} mov r4, r0 bl spi_write_enable mov r0, r4 ldr r4, =SPI0_BASE ldr r1, =4 str r1, [r4, #SPI_MBC] ldr r1, =4 str r1, [r4, #SPI_MTC] ldr r1, =4 str r1, [r4, #SPI_BCC] ldrb r1, =CMD_SECTOR_ERASE strb r1, [r4, #SPI_TXD] mov r1, r0 lsr r0, #16 strb r0, [r4, #SPI_TXD] mov r0, r1 lsr r0, #8 strb r0, [r4, #SPI_TXD] mov r0, r1 strb r0, [r4, #SPI_TXD] ldr r1, [r4, #SPI_TCR] orr r1, #(1 << 31) str r1, [r4, #SPI_TCR] 0: ldr r1, [r4, #SPI_TCR] tst r1, #(1 << 31) bne 0b 0: bl spi_is_busy cmp r0, #0 bne 0b pop {r4, pc} spi_erase_all: push {r4, lr} bl spi_write_enable ldr r4, =SPI0_BASE ldr r1, =1 str r1, [r4, #SPI_MBC] ldr r1, =1 str r1, [r4, #SPI_MTC] ldr r1, =1 str r1, [r4, #SPI_BCC] ldrb r1, =CMD_CHIP_ERASE strb r1, [r4, #SPI_TXD] ldr r1, [r4, #SPI_TCR] orr r1, #(1 << 31) str r1, [r4, #SPI_TCR] 0: ldr r1, [r4, #SPI_TCR] tst r1, #(1 << 31) bne 0b 0: bl spi_is_busy cmp r0, #0 bne 0b pop {r4, pc} spi_write_data: push {r4, r5, lr} mov r4, r0 mov r5, r1 bl spi_write_enable 0: bl spi_is_busy cmp r0, #0 bne 0b mov r0, r4 mov r1, r5 ldr r4, =SPI0_BASE add r1, #4 str r1, [r4, #SPI_MBC] str r1, [r4, #SPI_MTC] str r1, [r4, #SPI_BCC] ldrb r1, =CMD_PAGE_PROGRAM strb r1, [r4, #SPI_TXD] mov r1, r0 lsr r0, #16 strb r0, [r4, #SPI_TXD] mov r0, r1 lsr r0, #8 strb r0, [r4, #SPI_TXD] mov r0, r1 strb r0, [r4, #SPI_TXD] ldr r2, =spi_buf mov r3, r5 0: ldrb r1, [r2] strb r1, [r4, #SPI_TXD] add r2, #1 subs r3, #1 bne 0b ldr r1, [r4, #SPI_TCR] orr r1, #(1 << 31) str r1, [r4, #SPI_TCR] 0: ldr r1, [r4, #SPI_TCR] tst r1, #(1 << 31) bne 0b 0: bl spi_is_busy cmp r0, #0 bne 0b pop {r4, r5, pc} .data spi_jid: .skip 4 spi_uid: .skip 12 spi_buf: .skip 64 .end
完成