Forum Discussion
Hi Balerion,
The trick is figuring out the same register address FIFO is used for input AND output.
I did it like this:
#define REG(addr) (*((volatile uint32_t * const)(addr)))
#define ADDR_UART0 0xFFC02000
#define ADDR_UART0_RBR ((ADDR_UART0) + 0x0 ) // RO 0x00000000 Receive Buffer Register, LCR->DLAB=0
#define ADDR_UART0_THR ((ADDR_UART0) + 0x0 ) // WO 0x00000000 Transmit Holding Register, LCR->DLAB=1
#define ADDR_UART0_IER ((ADDR_UART0) + 0x4 ) // RW 0x00000000 Interrupt Enable Register
#define ADDR_UART0_IIR ((ADDR_UART0) + 0x8 ) // RO 0x00000001 Interrupt Identification Register
#define ADDR_UART0_LCR ((ADDR_UART0) + 0xC ) // RW 0x00000000 Line Control Register
#define ADDR_UART0_MCR ((ADDR_UART0) + 0x10) // RW 0x00000000 Modem Control Register
#define ADDR_UART0_LSR ((ADDR_UART0) + 0x14) // RO 0x00000060 Line Status Register
#define ADDR_UART0_MSR ((ADDR_UART0) + 0x18) // RO 0x00000000 Modem Status Register
#define ADDR_UART0_SCR ((ADDR_UART0) + 0x1C) // RW 0x00000000 Scratchpad Register
#define ADDR_UART0_SRBR0 ((ADDR_UART0) + 0x30) // RO 0x00000000 Shadow Receive Buffer Register
#define ADDR_UART0_SRBR1 ((ADDR_UART0) + 0x34) // RO 0x00000000 Shadow Receive Buffer Register 1
#define ADDR_UART0_SRBR2 ((ADDR_UART0) + 0x38) // RO 0x00000000 Shadow Receive Buffer Register 2
#define ADDR_UART0_SRBR3 ((ADDR_UART0) + 0x3C) // RO 0x00000000 Shadow Receive Buffer Register 3
#define ADDR_UART0_SRBR4 ((ADDR_UART0) + 0x40) // RO 0x00000000 Shadow Receive Buffer Register 4
#define ADDR_UART0_SRBR5 ((ADDR_UART0) + 0x44) // RO 0x00000000 Shadow Receive Buffer Register 5
#define ADDR_UART0_SRBR6 ((ADDR_UART0) + 0x48) // RO 0x00000000 Shadow Receive Buffer Register 6
#define ADDR_UART0_SRBR7 ((ADDR_UART0) + 0x4C) // RO 0x00000000 Shadow Receive Buffer Register 7
#define ADDR_UART0_SRBR8 ((ADDR_UART0) + 0x50) // RO 0x00000000 Shadow Receive Buffer Register 8
#define ADDR_UART0_SRBR9 ((ADDR_UART0) + 0x54) // RO 0x00000000 Shadow Receive Buffer Register 9
#define ADDR_UART0_SRBR10 ((ADDR_UART0) + 0x58) // RO 0x00000000 Shadow Receive Buffer Register 10
#define ADDR_UART0_SRBR11 ((ADDR_UART0) + 0x5C) // RO 0x00000000 Shadow Receive Buffer Register 11
#define ADDR_UART0_SRBR12 ((ADDR_UART0) + 0x60) // RO 0x00000000 Shadow Receive Buffer Register 12
#define ADDR_UART0_SRBR13 ((ADDR_UART0) + 0x64) // RO 0x00000000 Shadow Receive Buffer Register 13
#define ADDR_UART0_SRBR14 ((ADDR_UART0) + 0x68) // RO 0x00000000 Shadow Receive Buffer Register 14
#define ADDR_UART0_SRBR15 ((ADDR_UART0) + 0x6C) // RO 0x00000000 Shadow Receive Buffer Register 15
#define ADDR_UART0_FAR ((ADDR_UART0) + 0x70) // RW 0x00000000 FIFO Access Register
#define ADDR_UART0_TFR ((ADDR_UART0) + 0x74) // RO 0x00000000 Transmit FIFO Read
#define ADDR_UART0_RFW ((ADDR_UART0) + 0x78) // RW 0x00000000 Receive FIFO Write
#define ADDR_UART0_USR ((ADDR_UART0) + 0x7C) // RO 0x00000006 UART Status register
#define ADDR_UART0_TFL ((ADDR_UART0) + 0x80) // RO 0x00000000 Transmit FIFO Level
#define ADDR_UART0_RFL ((ADDR_UART0) + 0x84) // RO 0x00000000 Receive FIFO Level
#define ADDR_UART0_SRR ((ADDR_UART0) + 0x88) // RW 0x00000000 Software Reset Register
#define ADDR_UART0_SRTS ((ADDR_UART0) + 0x8C) // RW 0x0000000 Shadow Request to Send
#define ADDR_UART0_SBCR ((ADDR_UART0) + 0x90) // RW 0x00000000 Shadow Break Control Register
#define ADDR_UART0_SDMAM ((ADDR_UART0) + 0x94) // RW 0x00000000 Shadow DMA Mode
#define ADDR_UART0_SFE ((ADDR_UART0) + 0x98) // RW 0x00000000 Shadow FIFO Enable
#define ADDR_UART0_SRT ((ADDR_UART0) + 0x9C) // RW 0x00000000 Shadow RCVR Trigger
#define ADDR_UART0_STET ((ADDR_UART0) + 0xA0) // RW 0x00000000 Shadow TX Empty Trigger
#define ADDR_UART0_HTX ((ADDR_UART0) + 0xA4) // RW 0x00000000 Halt TX
#define ADDR_UART0_DMASA ((ADDR_UART0) + 0xA8) // RW 0x00000000 DMA Software Acknowledge
#define ADDR_UART0_CPR ((ADDR_UART0) + 0xF4) // RO 0x00083F32 Component Parameter Register
#define ADDR_UART0_UCV ((ADDR_UART0) + 0xF8) // RO 0x3331352A Component Version
#define ADDR_UART0_CTR ((ADDR_UART0) + 0xFC) // RO 0x44570110 Component Type Register
#define UART_USR_BUSY 0x01
#define UART_USR_TFNF 0x02 // tx fifo not full
#define UART_USR_TFE 0x04 // tx fifo empty
#define UART_USR_RFNE 0x08 // rx fifo not empty
#define UART_USR_RFF 0x10 // rx fifo full
#define UART_LSR_DR 0x01 // rx data ready
#define uart_IsTransmitFull() ((REG(ADDR_UART0_USR) & (uint32_t)UART_USR_TFNF) != (uint32_t)UART_USR_TFNF)
#define uart_IsTransmitEmpty() ((REG(ADDR_UART0_USR) & (uint32_t)UART_USR_TFE) == (uint32_t)UART_USR_TFE)
#define uart_IsReceiveData() ((REG(ADDR_UART0_USR) & (uint32_t)UART_USR_RFNE) == (uint32_t)UART_USR_RFNE)
//#define uart_IsReceiveData() ((REG(ADDR_UART0_LSR) & (uint32_t)UART_LSR_DR) == (uint32_t)UART_LSR_DR)
#define uart_rx_byte() REG(ADDR_UART0_RBR)
#define uart_tx_byte() REG(ADDR_UART0_THR)
void uart0_init(void)
{
uint32_t reg;
// disable the FIFO's
reg = REG(ADDR_UART0_IIR);
reg &= ~0xC0;
REG(ADDR_UART0_IIR) = reg;
// enable the FIFO's
reg = REG(ADDR_UART0_IIR);
reg |= 0xC0;
REG(ADDR_UART0_IIR) = reg;
}
void outbyte(uint8_t data)
{
// wait until tx fifo is not full
while (uart_IsTransmitFull());
uart_tx_byte() = ((uint32_t)data);
}
void printz(const char *str)
{
//while (*str != (uint32_t)NULL)
while (*str != '\0')
{
if (*str == '\n')
{
outbyte((uint8_t)('\r'));
}
outbyte((uint8_t)(*str));
str ++;
}
return;
}
Be mindful of the WDT if you code an inbyte(). You have to clear it before it triggers or reset occurs.
Kiebach
Hi Kiebach,
I’m currently working on developing a bare-metal application for the Agilex 7 FPGA and would greatly appreciate your insights on the process. Specifically, I’m interested in understanding how you’ve approached this in a bare-metal environment.
Could you share the steps you followed, the tools you used, and any reference materials that were particularly helpful during development? Any advice or resources you could provide would be invaluable.
Thank you in advance for your time and assistance!
Best regards,
Samyakth