krjdev Posted June 6, 2020 Share Posted June 6, 2020 Hi, I have noticed an issue in a bare-metal application when polling the register XUARTPS_ISR (Channel Interrupt Status Register). No issues when I use XUART_SR (Channel Status Register) instead. The issue: When I poll XUART_ISR for TX_FULL and RX_EMPTY the UART interface becomes an unstable state. No sending and receiving after a few bytes is possible. Has somebody noticed the same issue or can somebody explain whats happening? Edit: My current code for the UART interface (Here I use XUARTPS_SR instead. But when I poll XUARTPS_ISR (0x14) it doesn't work.): #include <string.h> #include <dev/io.h> #define UART0_BASE 0xE0000000 #define UART1_BASE 0xE0001000 #define UART_CR_OFFSET 0x0 #define UART_CR_RXRST 0 #define UART_CR_TXRST 1 #define UART_CR_RXEN 2 #define UART_CR_RXDIS 3 #define UART_CR_TXEN 4 #define UART_CR_TXDIS 5 #define UART_MR_OFFSET 0x4 #define UART_IER_OFFSET 0x8 #define UART_BGEN_OFFSET 0x18 #define UART_SR_OFFSET 0x2C #define UART_SR_RXEMPT 1 #define UART_SR_RXFULL 2 #define UART_SR_TXEMPT 3 #define UART_SR_TXFULL 4 #define UART_FIFO_OFFSET 0x30 #define UART_BDIV_OFFSET 0x34 struct uart_reg { unsigned int cr; unsigned int mr; unsigned int ier; unsigned int bgen; unsigned int sr; unsigned int fifo; unsigned int bdiv; }; static struct uart_reg regs; void uart_init(void) { unsigned int tmp; regs.cr = (UART1_BASE + UART_CR_OFFSET); regs.mr = (UART1_BASE + UART_MR_OFFSET); regs.ier = (UART1_BASE + UART_IER_OFFSET); regs.bgen = (UART1_BASE + UART_BGEN_OFFSET); regs.sr = (UART1_BASE + UART_SR_OFFSET); regs.fifo = (UART1_BASE + UART_FIFO_OFFSET); regs.bdiv = (UART1_BASE + UART_BDIV_OFFSET); /* Check if RX/TX is enabled */ tmp = io_rd32(regs.cr); /* Skip init if RX/TX enabled */ if (tmp & ((1 << UART_CR_TXEN) | (1 << UART_CR_RXEN))) return; /* Reset RX/TX paths */ tmp = io_rd32(regs.cr); tmp |= ((1 << UART_CR_TXRST) | (1 << UART_CR_RXRST)); io_wr32(regs.cr, tmp); do tmp = io_rd32(regs.cr); while (tmp & ((1 << UART_CR_TXRST) | (1 << UART_CR_RXRST))); /* Set baudrate to 115200; UART Reference Clock: 100MHz */ io_wr32(regs.bgen, 124); io_wr32(regs.bdiv, 6); /* Set mode: 8 Databit, 1 Stopbit, No Parity */ io_wr32(regs.mr, 0x20); /* Enable RX/TX */ tmp = io_rd32(regs.cr); tmp &= ~((1 << UART_CR_TXEN) | (1 << UART_CR_RXEN)); io_wr32(regs.cr, tmp); } int uart_send(unsigned char *buf, int len) { int i; unsigned int tmp; for (i = 0; i < len; i++) { do tmp = io_rd32(regs.sr); while (tmp & (1 << UART_SR_TXFULL)); io_wr08(regs.fifo, buf[i]); } return len; } int uart_recv(unsigned char *buf, int len) { int i; int ret = 0; unsigned int tmp; tmp = io_rd32(regs.sr); if (tmp & (1 << UART_SR_RXEMPT)) return 0; for (i = 0; i < len; i++) { buf[i] = io_rd08(regs.fifo); ret++; tmp = io_rd32(regs.sr); if (tmp & (1 << UART_SR_RXEMPT)) return ret; } return ret; } Link to comment Share on other sites More sharing options...
elodg Posted June 16, 2020 Share Posted June 16, 2020 Haven't seen low-level code in a while. Check the register reference in https://www.xilinx.com/support/documentation/user_guides/ug585-Zynq-7000-TRM.pdf. Page 1773 deals with these registers. The difference seems to be that SR is a read-only register reflecting real-time hardware status, while ISR is read and write-to-clear. ISR is used by the interrupt handler to handle the interrupt event and clear the status bits at the end then wait for it to be set again. If not cleared and the byte is consumed/produced, an erroneous interrupt will trigger again with no data to read/write. Xilinx's drivers are a good reference on how to use their peripherals programatically. Link to comment Share on other sites More sharing options...
Question
krjdev
Hi,
I have noticed an issue in a bare-metal application when polling the register XUARTPS_ISR (Channel Interrupt Status Register).
No issues when I use XUART_SR (Channel Status Register) instead.
The issue:
When I poll XUART_ISR for TX_FULL and RX_EMPTY the UART interface becomes an unstable state. No sending and receiving after a few bytes is possible.
Has somebody noticed the same issue or can somebody explain whats happening?
Edit:
My current code for the UART interface (Here I use XUARTPS_SR instead. But when I poll XUARTPS_ISR (0x14) it doesn't work.):
Link to comment
Share on other sites
1 answer to this question
Recommended Posts
Archived
This topic is now archived and is closed to further replies.