cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Highlighted
Observer
Observer
356 Views
Registered: ‎05-10-2019

Access to UART Lite Registers in Linux

I built a system with a few APIs: UART Lite, UART 16550, GPIO AXI and BRAM AXI to run Linux (Petalinux or Ubuntu). I avoid using kernel modules and prefer mmap() to read-write peripheral registers directly. All of these IPs work as expected, except for UART Lite. I can read and write TX register(it sends data to the assigned pin without problems), control and status too but if I attempt to read RX FIFO my Linux application crashes with "Bus Error" message. I've seen high-level access examples via /dev/ttyXXX, is this the best way to do it? I still have not tried tty option, for me it seems to be too slow. So, the question is how to solve the bus error when reading mapped RX FIFO of UART Lite?

0 Kudos
5 Replies
Highlighted
Moderator
Moderator
335 Views
Registered: ‎09-12-2007

Is the RX FIFO a read only register?

0 Kudos
Highlighted
Observer
Observer
321 Views
Registered: ‎05-10-2019

Per PG142 "The RX FIFO is a read-only register. Issuing a write request to this register has no effect." In my case bus error happens when I try to read. I tried reading both when RXFIFO Valid Data bit is set and when the bit is 0, any read operation on RX FIFO results in bus error.

0 Kudos
Highlighted
Moderator
Moderator
314 Views
Registered: ‎09-12-2007

Can you share your code

0 Kudos
Highlighted
Observer
Observer
304 Views
Registered: ‎05-10-2019

Of course. The actual code is quite big, so I'll post pieces relatet to uart lite.

 

1. Acquire remapped address

mem_fd=open("/dev/mem", O_RDWR|O_SYNC);

off_t uli_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, uli_base_off);

'uli_base' now is pointing to UART Lite AXI registers. The argument uli_base_off is the UART Lite AXI address from Vivado project.

2. Simplest way send /receive:

void ul_put_char(uint8_t char_to_send){
*((volatile unsigned long *) (uli_base + ULT_OFFS_TXFIFO))=char_to_send;
}

uint8_t ul_get_char(){
uint8_t ret= *((volatile unsigned long *) (uli_base + ULT_OFFS_RXFIFO));

return ret;

}

The ULT_OFFS_TXFIFO and RXFIFO defined per pg142:

 

#define ULT_OFFS_RXFIFO 0x0
#define ULT_OFFS_TXFIFO 0x4
#define ULT_OFFS_STAT 0x8

 

3. To see if the RX buffer has data I use

uint8_t  get_ulite_status(){
uint8_t ret=(*((volatile unsigned long *) (uli_base + ULT_OFFS_STAT)))&0xFF;
return ret;
}

The functions get_ulite_status() and ul_put_char() work fine, i.e. status is either 4 (no communications) or 7 (a lot of data sent to UART, in particular GPS stream), but ul_get_char() only gives bus error and crashes the application.

0 Kudos
Highlighted
Observer
Observer
138 Views
Registered: ‎05-10-2019

Two more details:

- this way works fine with UART 16550 (just a little more mess with registers)

- I used Ultra96 BSP and did not touch device tree. To be more exact I tried to update it as described on the Xilinx drivers "Confluence" web page for UART Lite, but it did not have any effect and I reverted back to unedited system-user.dtsi

0 Kudos