Gaviar (小志掌機) >> Assembly
LED
參考資訊:
1. ws2812c
2. Delay_slot
3. FlatHeadBro
PE5用來控制LED,不過這顆LED是WS2812C,它需要透過串列訊號控制
WS2812C裡面有R、G、B三顆LED,每顆LED用一個Byte來代表亮度,傳送的串列訊號如下:
因為只有一隻DI腳位,因此,對於時序有一些要求,如果要傳送0,需要的時序是T0H(300ns)+T0L(850ns),而傳送1則是T1H(800ns)+T1L(400ns),結尾需要傳送RET(>280us)
GPIO位址
PE_CFG0
PE_DAT
main.s
.global _start .equ GPIO_BASE, 0x02000000 .equ PE_CFG0, 0x00c0 .equ PE_DAT, 0x00d0 .equ _50NS, 10 .equ _100NS, 20 .equ _200NS, 40 .equ _300NS, 60 .equ _400NS, 80 .equ _450NS, 90 .equ _800NS, 160 .equ _850NS, 170 .equ _1US, 200 .equ _1S, 200000000 .text .long 0x4000006f .byte 'e','G','O','N','.','B','T','0' .long 0x5F0A6C39 .long 0x8000 .long 0, 0 .long 0, 0, 0, 0, 0, 0, 0, 0 .long 0, 0, 0, 0, 0, 0, 0, 0 .org 0x0400 _start: li t0, 0x100000 li a0, GPIO_BASE + PE_CFG0 sw t0, 0(a0) li a0, GPIO_BASE + PE_DAT 0: li t0, (1 << 12) jal b24 li t0, _1S jal delay li t0, (0 << 0) jal b24 li t0, _1S jal delay j 0b b24: move t2, ra move t3, t0 li t4, 24 0: and t0, t3, 1 srl t3, t3, 1 beqz t0, 1f jal b1 j 2f 1: jal b0 2: addi t4, t4, -1 bgtz t4, 0b jr t2 b0: move t1, ra li t0, (1 << 5) sw t0, 0(a0) li t0, _300NS jal delay li t0, (0 << 5) sw t0, 0(a0) li t0, _850NS jal delay jr t1 b1: move t1, ra li t0, (1 << 5) sw t0, 0(a0) li t0, _800NS jal delay li t0, (0 << 5) sw t0, 0(a0) li t0, _400NS jal delay jr t1 delay: addi t0, t0, -1 bgtz t0, delay jr ra .end
main.ld
MEMORY { FLASH : ORIGIN = 0, LENGTH = 32M } SECTIONS { .text : { *(.text*) } > FLASH .rodata : { *(.rodata*) } > FLASH .bss : { *(.bss*) } > FLASH }
Makefile
all: riscv64-unknown-linux-gnu-as -o main.o main.s riscv64-unknown-linux-gnu-ld -T main.ld -o main.elf main.o riscv64-unknown-linux-gnu-objcopy -O binary main.elf tmp.bin python3 gen_checksum.py tmp.bin main.bin run: xfel ddr f133 && xfel write 0x40000000 main.bin && xfel exec 0x40000000 clean: rm -rf main.bin main.o main.elf tmp.bin
連接USB到PC
$ lsusb Bus 002 Device 064: ID 1f3a:efe8 Onda (unverified) V972 tablet in flashing mode
編譯
$ make riscv64-unknown-linux-gnu-as -o main.o main.s riscv64-unknown-linux-gnu-ld -T main.ld -o main.elf main.o riscv64-unknown-linux-gnu-objcopy -O binary main.elf tmp.bin python3 gen_checksum.py tmp.bin main.bin
下載
$ make run xfel ddr f133 && xfel write 0x40000000 main.bin && xfel exec 0x40000000 100% [================================================] 16.000 KB, 383.004 KB/s
完成
開頭使用0x4000006f,它是一個跳躍指令,因為第4個Byte後的資料會由BROM使用,至於司徒為何要保留長度1024(0x400)?因為F133的中斷向量總共有223個,中斷向量位址達到0x380,因此,司徒就從0x400開始執行,至於BROM使用的資料格式,可以參考https://github.com/Ouyancheng/FlatHeadBro/blob/master/boot0/boot0-header.c
$ /opt/f133/bin/riscv64-unknown-linux-gnu-objdump -bbinary -mriscv:rv64 -D main.bin | head -n20 main.bin: file format binary Disassembly of section .data: 0000000000000000 <.data>: 0: 4000006f j 0x400 4: 4765 li a4,25 6: 422e4e4f fnmadd.d ft8,ft8,ft2,fs0,rmm a: 3054 fld fa3,160(s0) c: 8c78 0x8c78 e: 9a24 0x9a24 10: 4000 lw s0,0(s0) ... 3fe: 0000 unimp 400: 001002b7 lui t0,0x100 404: 02000537 lui a0,0x2000 408: 0c05051b addiw a0,a0,192 40c: 00552023 sw t0,0(a0) # 0x2000000
仔細的玩家應該可以發現,RISC-V沒有MIPS的Delay Slot,不需要在跳躍指令後面塞一個nop或者做指令排序,在開發PSP模擬器踩到的坑洞,看來RISC-V應該解決了,而所謂的Delay Slot指的就是如下狀況:
lw v0,4(v1) # load word from address v1+4 into v0 nop # wasted load delay slot jr v0 # jump to the address specified by v0 nop # wasted branch delay slot
如果jr後面沒有插入nop,則會跑飛,因為jr慢了一步執行(提取、解碼、執行),這種Delay Slot狀況是跟架構設計有關係,不過,司徒可以看到RISC-V的進步,真是感動流淚~