krjdev 0 Posted June 6, 2020 Share Posted June 6, 2020 (edited) 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; } Edited June 6, 2020 by krjdev add missing current code; Link to post Share on other sites
0 elodg 47 Posted June 16, 2020 Share Posted June 16, 2020 (edited) 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. Edited June 17, 2020 by elodg Link to post Share on other sites
Question
krjdev 0
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.):
add missing current code;
Link to post
Share on other sites
1 answer to this question
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now