honda4life
Posts: 75
Joined: Thu Mar 15, 2012 7:27 pm

Reading UART registers

Sun Mar 13, 2016 8:34 am

Hello,

I have a RPi2 and want to have access to the UART registers.
I've made my own PCB with as an interface board suited for my needs.
On this board there is a RS485 IC (MAX3485), but this needs an additional output to switch between RX/TX mode (half duplex communication).
So I have to check the TX buffer is empty AND the last byte is completely sent.
But I need some help to get it working and accessing the registers. I can not find the problem on my own.

So here is some python code, but at the end it reads 0.
I tested with /dev/mem instead of /dev/gpiomem to make it easy, I will change that afterwards.

As I understand RPi2 starts with base 0x3F000000.
I now need the offset towards the UART registers, there are 2 UART's. One is the mini UART and the other one the PL011 UART, from what I've read we are using the PL011.
I use the datasheet from the old pi: https://www.raspberrypi.org/documentati ... herals.pdf
On page 177 "The PL011 USRT is mapped on base adderss 0x7E20100."
So I think I need to add 0x3f000000 + 0x7E20100 and that is where the UART starts.
See also this thread: https://www.element14.com/community/thr ... hread=true
Since offset must be a multiple of the pagesize it will be 0x3F000000 + 0x7E20000 and we have 0x100 to do later.
This 0x100 I can do with seek with an additional offset of 0x18 to get into the flag register (32-bit) where I can find my data, so ending at 0x118 offset.

I read 4 bytes, little-endian and want this as unsigned integer but the value is 0.

I do not know what's wrong, or another good way to test the memory access is working as I think it should be.
While testing different offsets, ... data was not always 0 so something is read from the memory.

Thanks!

Code: Select all

mem = os.open('/dev/mem', os.O_RDWR | os.O_SYNC)
off = 0x3f000000 + 0x7e20000
mem_mmap = mmap.mmap(mem, mmap.PAGESIZE, mmap.MAP_SHARED, mmap.PROT_READ | mmap.PROT_WRITE, offset=off)
os.close(mem)
mem_mmap.seek(0x118)
print unpack('<I', mem_mmap.read(4))

User avatar
joan
Posts: 15256
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Reading UART registers

Sun Mar 13, 2016 9:43 am

The peripherals are mapped to different memory addresses. The GPIO peripheral memory is separate to the UART peripheral memory. You will need to use /dev/mem for access. /dev/gpiomem only gives access to the GPIO peripheral memory.

Perhaps have a look at http://abyz.co.uk/rpi/pigpio/examples.h ... nimal_gpio which is a C example of mapping in peripheral memory. Note that the single core Pis have a different memory map to the multi core Pis.

honda4life
Posts: 75
Joined: Thu Mar 15, 2012 7:27 pm

Re: Reading UART registers

Sun Mar 13, 2016 10:14 am

Thanks,

This is new to me, maybe try this offsets.

Code: Select all

#define UART0_BASE (piPeriphBase + 0x201000)
#define UART1_BASE (piPeriphBase + 0x215000)
Not sure if it is using UART0 or UART1.
I think we are using PL011.

Mini: offset = 0x7E215000
PL011: 0x7E20100, see page 177

Typo in the code or datasheet?

edo1
Posts: 169
Joined: Sun Jun 15, 2014 3:33 pm
Location: Russia

Re: Reading UART registers

Sun Mar 13, 2016 5:47 pm

honda4life wrote:So I have to check the TX buffer is empty AND the last byte is completely sent.
why do you want to bypass OS?
you could use tcdrain() function to wait until last byte is transmitted, TIOCOUTQ ioctl to check how many bytes are in output queue.

honda4life
Posts: 75
Joined: Thu Mar 15, 2012 7:27 pm

Re: Reading UART registers

Sun Mar 13, 2016 6:06 pm

I was not aware of that functio, will try it but i'm not sure it will work.

Return to “Interfacing (DSI, CSI, I2C, etc.)”