How to send data in UART continuously without interrupt?


Without enabling/using UART interrupt, how to keep transmitting data through UART, without data being lost/not sent. When I send the data by following way,

    li a0, 0xaa;
    li t0, UART0_BASE;
    sw a0, UART_TXDATA_OFFSET(t0); // memory mapped addr of txdata register
    j send_data;

the byte 0xaa is sent only once and tx pin stays high as long the loops executes. I understand that this is NOT right to send continuously as the tx buffer might not have space and the txfifo full bit might be set.

But I would expect the transmission to continue once the fifo has space instead of sending just once and never again. Coz, this loop though executed for 3-5s, it just sends once and don’t see any activity in tx pin after for more than 3secs.

Hi @bsvtgc There could be other bits of TXDATA which are reserved and not read-only that should not be changed. You might try doing a read-modify-write style of transaction and making sure only to effect change on bits TXDATA[7:0].

In place of your sw

    li t2, 0xff  # txdata[7:0]
    not t2, t2;
    lw t1, UART_TXDATA_OFFSET(t0);  # read
    and t1, t1, t2;  # out with the old ...
    or t1, t1, a0;  # ... in with the new
    sw t1, UART_TXDATA_OFFSET(t0);  # write

As you mentioned, you might also try first using a busy loop like wait_full below to stall until ready, before getting into the read-modify-write step.

    lw t1, UART_TXDATA_OFFSET(t0);
    slri t1, t1, 31  # TXDATA_FIFO_FULL;
    bnez t1, wait_full;

When interrupts or multiple threads are harts are used, the read-modify-write should be atomic – see amoxxx and lr/sc instructions.

1 Like

@pds Good to hear from you.

The UART response did NOT change much with suggested changes. Adjusting txcnt in txctrl register too didn’t alter the response.

A brief about my code:
I run the code from RAM loading at 0x8000_0000 at the very start after setting sp, startup code disables all interrupt.

csrw mstatus, zero;
 csrw mie, zero;

Later the m-timer interrupt alone is enabled

  li t0, MIE_MTIE;
    csrw mie, t0;

    li t0, MSTATUS_MIE;
    csrw mstatus, t0;

to switch (time multiplex) between led-blink and uart-tx ( without gpio/uart interrupts).

I recently realized that the initial PLIC settings have had an effect. I did NOT pay attention to initial PLIC settings (from reset to until flash boot and followed by opened/gdb loads my program in RAM 0x8000_0000).

When I programmed the same UART code on flash at 0x2000_0000, and boot from here, it works all the time. So all I could conclude is the PLIC settings have had an effect though I could n’t revert and find back exactly what was the cause as I had overwritten the code in flash with my new uart-tx code.