Better way to write a few MMIO register bits in RISC-V assembly?

512 Views Asked by At

To configure UART tx, water mark (0 to 7) has to be written on memory mapped tx control register on bit position [18:16].

My RISC-V assembly function first reads the present control register value, perform a bitwise AND with mask to clear bits [18:16] and then OR with the shifted input value and write back.

Code below:

uart_set_txwmark:

    slli a0, 15;  /* shift input value by 15 */
    li t0, UART1_BASE;
    lw t1, UART_TXCTRL_OFFSET(t0); /* Read present value */

.equiv UART_MASK_WMARK, 0x0xFFF8FFFF /* [18:16] zero mask */

    li t2, UART_MASK_WMARK;   
    and t1, t1, t2;      /* clear/zero bits 18:16 */ 
    or t1, t1, a0;       /* OR with input value */
    sw t1, UART_TXCTRL_OFFSET(t0); /* Write back */

I am curious to know if there is any other better way of setting few bits in a memory mapped register in RISC-V.

1

There are 1 best solutions below

3
On

I am curious to know if there is any other better way of setting few bits in a memory mapped register in RISC-V.

Not really, I think you have the gist of it.


If you can use halfword reads/writes instead, that will happen to position the bits of interest at the low bit positions, so you can maybe do:

la t0, UART1_BASE
lhu t1, UART_TXCTRL_OFFSET+2(t0)  // fetch high order at offset +2
andi t1, t1, -8
or t1, t1, a0
sh t1, UART_TXCTRL_OFFSET+2(t0)