Hi,
I’m writing some code that directly interfaces the UART. In the U540 documentation it mentions that:
A RISC‑V amoswap instruction
can be used to both read the full status and attempt to enqueue data, with a non-zero return
value indicating the character was not accepted.
When I try this approach I see some characters duplicated in the output.
Reading the FSBL source code I notice that rather than amoswap an amoor instruction is used. (https://github.com/sifive/freedom-u540-c000-bootloader/blob/master/uart/uart.c#L15). When I switch to using amoor rather than amoswap everything works as expected and I don’t get any duplicated characters.
I’m new to RISC-V so it’s very possible my code using amoswap is wrong in some way, so I’ve got two questions:
- Is it possible to use amoswap to write to txdata while checking the full bit?
- Why does the FSBL source use amoor rather than amoswap
Note: I’m seeing this behavior on the Unleashed platform (haven’t tried on any simulator).
amoswap source code
.equ UART_BASE_ADDRESS, 0x10010000
.text
.globl _start
_start:
csrrs t0, mhartid, x0 /* get hartid */
bnez t0, busy_loop /* got to busy loop if not hart0 */
la t0, message /* load pointer to hello world message */
li t1, UART_BASE_ADDRESS /* load address of UART txdata register */
next_byte:
lbu t2, (t0) /* load byte from message */
beqz t2, busy_loop /* null terminated, so finish */
addi t0, t0, 1 /* increment message pointer */
retry:
amoswap.w t3, t2, (t1) /* atomically read txdata into t3 and write t2 (message char) to txdata */
bnez t3, retry /* if t3 != 0 then full bit was set, so have to retry */
j next_byte /* current byte successfully written to FIFO, get next byte */
busy_loop:
j busy_loop
.data
message:
.asciz "Hello World\r\n"
amowap output:
SiFive FSBL: 2018-03-20
HiFive-U serial #: 00000313
Helllo Woorlld
Note: the actual duplicated characters are not deterministic
amoor source code
.equ UART_BASE_ADDRESS, 0x10010000
.text
.globl _start
_start:
csrrs t0, mhartid, x0 /* get hartid */
bnez t0, busy_loop /* got to busy loop if not hart0 */
la t0, message /* load pointer to hello world message */
li t1, UART_BASE_ADDRESS /* load address of UART txdata register */
next_byte:
lbu t2, (t0) /* load byte from message */
beqz t2, busy_loop /* null terminated, so finish */
addi t0, t0, 1 /* increment message pointer */
retry:
amoor.w t3, t2, (t1) /* atomically read txdata into t3 and write t3 | t2 to tx data*/
bnez t3, retry /* if t3 != 0 then full bit was set, so have to retry */
j next_byte /* current byte successfully written to FIFO, get next byte */
busy_loop:
j busy_loop
.data
message:
.asciz "Hello World\r\n"
amoor output:
SiFive FSBL: 2018-03-20
HiFive-U serial #: 00000313
Hello World
Thanks,
Ben