Personally I'd look at the register definition for the UART and write a function to add bytes to the fifo.
You then have to make a concious decision about what to do when the tx fifo is full.
Either:
- spin waiting for space.
- tell caller how many bytes were written (who might ignore the error).
You might decide it is worth adding a software fifo, but a large hardware fifo has much the same effect.
If you do use a software fifo, you don't necessarily need to use interupts - provided the software can poll the hardware often enough.
The same is true of receive - make the hardware fifo big enough.
I don't know if the uart can share an internal memory block between its rx and tx sides.
It also ought to be possibly to design a multi-port uart that uses a single memory block.