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的進步,真是感動流淚~


返回上一頁