LiteXにおけるUARTの書き込みについて、そのフローを確認しておく。
litex/litex/soc/software/libc/stdio.c
static int litex_putc(char c, FILE *file) { (void) file; /* Not used in this function */ #ifdef CSR_UART_BASE uart_write(c); if (c == '\n') litex_putc('\r', NULL); #endif return c; }
uart_write()
を呼び出す。
litex/litex/soc/software/libbase/uart.c
ポイントは、IRQにおけるUART_INTERRUPT
をDisableにして、tx_buf
に文字を書き込んでいく。
書き込んだ後に、irqmask
を書き込み直して、割り込みを発生させる。
書き込みバッファにすでに値が入ってれば、バッファを更新する。そうでなければ、uart_rxtx_write(c)
を直接書き込む。
void uart_write(char c) { unsigned int oldmask; unsigned int tx_produce_next = (tx_produce + 1) & UART_RINGBUFFER_MASK_TX; if(irq_getie()) { while(tx_produce_next == tx_consume); } else if(tx_produce_next == tx_consume) { return; } oldmask = irq_getmask(); irq_setmask(oldmask & ~(1 << UART_INTERRUPT)); if((tx_consume != tx_produce) || uart_txfull_read()) { tx_buf[tx_produce] = c; tx_produce = tx_produce_next; } else { uart_rxtx_write(c); } irq_setmask(oldmask); }
このuart_rxtx_write()
が実際にUARTのモジュールに書き込みを行う。
static inline void uart_rxtx_write(uint32_t v) { csr_write_simple(v, (CSR_BASE + 0x3000L)); }