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.
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: