Additional RPi4 serial ports

Has anyone lurking in this forum managed to get additional PL011 UART’s working in a Raspberry Pi4B using QNX 7.1? There is the Miniuart that shows up as /dev/ser1. There are five PL011 UART’s the 3rd shows up as /dev/ser3 (because of the way the driver is started). I’d like to get at least two more serial ports but it doesn’t seem to be straight forward. The five UART’s have different base addresses but seem to share a common interrupt (IRQ 153). But no interrupts fire for me. So close…

Geoff.

Here after, I’m referring to the BCM2711 documentation.

At page 146, the documentation says : Each UART has one intra-chip interrupt UARTINTR generated as the OR-ed function of its five individual interrupts.

Great, one might think there is one interrupt per UART.
However, at page 87, one can read : | IRQ 57 | OR of all PL011 UART |

For reference the mapping is :

  • UART0: 0x7e201000
  • UART2: 0x7e201400
  • UART3: 0x7e201600
  • UART4: 0x7e201800
  • UART5: 0x7e201a00

The RPi4 BSP starts /dev/ser3 with this command line :
devc-serpl011 -b115200 -c48000000 -e -F -u3 0xfe201600,153

Int the RPi4 BSP, file src\hardware\startup\lib\public\aarch64\bcm2711.h :

/*
 * UART Controllers
 */
#define BCM2711_UART0_BASE                  0xfe201000
#define BCM2711_UART0_IRQ                   (96+57)
#define BCM2711_UART1_BASE                  0xfe215000
#define BCM2711_UART1_IRQ                   (96+29)
#define BCM2711_UART2_BASE                  0xfe201400
#define BCM2711_UART2_IRQ                   (96+57)
#define BCM2711_UART3_BASE                  0xfe201600
#define BCM2711_UART3_IRQ                   (96+57)
#define BCM2711_UART4_BASE                  0xfe201800
#define BCM2711_UART4_IRQ                   (96+57)
#define BCM2711_UART5_BASE                  0xfe201a00
#define BCM2711_UART5_IRQ                   (96+57)

This confirm there is one interrupt for all PL011 UARTs.

However, in intr.c of the PL011 driver, InterruptAttach() does not attach with exclusive access. So there is no reason using multiple drivers does not work.

When you say “no interrupts fire for me”, what do you mean exactly ?
/dev/ser3 does not work ?
Other UART drivers do not work ?

"At page 146, the documentation says : Each UART has one intra-chip interrupt UARTINTR generated as the OR-ed function of its five individual interrupts.

Great, one might think there is one interrupt per UART.
However, at page 87, one can read : | IRQ 57 | OR of all PL011 UART |"

Yes. I have read that document (a lot) and initially though that they were referring to one interrupt per UART but then realised that they were referring to one interrupt for the lot. As is typical you get an interrupt for a UART and then read various registers (like the IIR in a 16550) to figure out what to do. The PL011 has a different set of registers at different offset addresses but they fundamentally do the same thing. It is unclear to me how we get from IRQ 57 to the IRQ 153 used to start the devc-serpl011 driver. I am reasonably familiar with how the interrupt system works in the Xilinx ARM systems but have yet to come to grips with it on the Pi.

"For reference the mapping is :

UART0: 0x7e201000
UART2: 0x7e201400
UART3: 0x7e201600
UART4: 0x7e201800
UART5: 0x7e201a00

"
Yes. I concur. The BSP addresses UART3 at 0xfe201600. 0x7e201600 points to the same.

"
The RPi4 BSP starts /dev/ser3 with this command line :
devc-serpl011 -b115200 -c48000000 -e -F -u3 0xfe201600,153

Int the RPi4 BSP, file src\hardware\startup\lib\public\aarch64\bcm2711.h :

/*
 * UART Controllers
 */
#define BCM2711_UART0_BASE                  0xfe201000
#define BCM2711_UART0_IRQ                   (96+57)
#define BCM2711_UART1_BASE                  0xfe215000
#define BCM2711_UART1_IRQ                   (96+29)
#define BCM2711_UART2_BASE                  0xfe201400
#define BCM2711_UART2_IRQ                   (96+57)
#define BCM2711_UART3_BASE                  0xfe201600
#define BCM2711_UART3_IRQ                   (96+57)
#define BCM2711_UART4_BASE                  0xfe201800
#define BCM2711_UART4_IRQ                   (96+57)
#define BCM2711_UART5_BASE                  0xfe201a00
#define BCM2711_UART5_IRQ                   (96+57)

This confirms there is one interrupt for all PL011 UARTs.
"

Again, I concur. I also found this.

So I tried

devc-serpl011 -b115200 -c48000000 -e -F -u3 0xfe201800,153

and it sent it into fairy land when the InterruptAttach() call is made. If I comment it out this doesn’t happen - but of course this doesn’t help me! :slight_smile:

So I tried changing the IRQ’s to (93+96) etc and unsurprisingly this didn’t work either. But at least the system doesn’t stop!

"When you say “no interrupts fire for me”, what do you mean exactly ?
/dev/ser3 does not work ?
Other UART drivers do not work ?
"

/dev/ser3 works fine with the base address stated as 0xfe201600. Any other of the base addresses with the IRQ as 153 does not. I try this as single instances of devc-serpl011 - I am not stringing all the address/IRQ’s along in the same instance of the driver. Although I tried…

I want to have another look at the way InterruptAttach() is being used. But right now I’m at a loss.

I have the various GPIO’s wired to provide me with Tx/Rx/GND and use a pulsed laser ranger device that works fine with /dev/ser3 at 460800,n,8,1. Unfortunately the rate is fixed. When powered up it simply starts spewing out small (4 byte) packets at a rate of 1 khz. As I said, it works fine on /dev/ser3 (devc-serpl011 … 0xfe201600,153) but not with any other base address. As I said also, it kills the entire system at the InterruptAttach() call. After a few seconds it reboots - presumably the watchdog kicks in and resets it. So something drastic is happening.

Thanks for replying so quickly Nico. I wasn’t expecting anything so fast! :slight_smile: I put something up on the Blackberry (qnx.com) forum and didn’t get any response at all. If I can’t figure this out using informal processes I guess I will have to annoy someone at Blackberry as I do have a support plan with them. But I do try to sort these kinds of things out before I call on them!

Geoff.

However, at page 87, one can read : | IRQ 57 | OR of all PL011 UART |"

Yes. I have read that document (a lot) and initially though that they were referring to one interrupt per UART but then realised that they were referring to one interrupt for the lot.

The way to know which UART has triggered the interrupt is explained at page 88.
It seems it is not used in the BSP sources.

It is unclear to me how we get from IRQ 57 to the IRQ 153 used to start the devc-serpl011 driver.

IRQ 57 is an offset in the “VC peripheral IRQs” table (page 86 and 87).
At page 89, one can see that these interrupts are routed to the GIC-400 at offset 96 :
VC peripheral IRQsSPI IDs 96-159

/dev/ser3 works fine with the base address stated as 0xfe201600. Any other of the base addresses with the IRQ as 153 does not. I try this as single instances of devc-serpl011 - I am not stringing all the address/IRQ’s along in the same instance of the driver. Although I tried…

I didn’t had a deep look at the PL011 driver sources but from what you report, the driver delivered in the BSP has been coded for UART3 and has not been tested on other UART instances.
You say taht when launching the driver for another UART, the system hangs then reboots. This certainly means a problem with an interrupt not being acknowledged correctly and firing forever.
Or this is a DMA problem (out of control writing of data “killing” system vital data). Is the driver compiled with DMA support ?

It would be nice to solve this but I’m out of time. I will have to use two Pi’s to get my 3 or 4 serial ports. Using the magic of QNET and QNX resource managers this is not too difficult. Just an extra piece of scarce hardware and weight.

I can’t see why the base address has anything to do with whether or not an IRQ can be successfully attached to. When I get a chance I will start stripping things back to see where or if this behaviour stops. For example, look at and perhaps disable the UART initialisation in the devc driver. Whatever, it would be nice to have a Pi with a few serial ports.

I also suspect that there is something inside the Pi system such as the multiple usage of the GPIO lines that could be causing this. Apparently in Linux to use UART0 you have to disable the bluetooth as it shares the same GPIO lines as UART0. It seems to me that under QNX the config.txt file is not read - or honoured. Changing it doesn’t seem to have any effect on anything. Sigh…

The driver is not being built with DMA support.

Geoff.

Yes, QNET is kind of magic.
Two remarks about QNET :

  • You have to be on a closed network when security is of importance.
  • I’ve found it to be quite network bandwidth hungry.

The problem might be less with base address than with correct IRQ management. Managing a shared IRQ might require specific actions to be done.

I don’t know the Pi BSP but from my experience with other BSPs pin muxing is coded in the BSP sources, no configuration file is read (how and where to read the file from during the boot process ?).
On non x86 targets, QNX BSPs use to implement an IPL (Initial Program Loader) which is kind of minimalist BIOS to load and run the IFS (Image File System). On some targets u-boot is used instead of an IPL.
Using u-boot or an IPL, there is some pin muxing done at this level too. As u-boot is a more complete boot process than an IPL, the chip might be completely configured by u-boot.

The driver is not being built with DMA support.

That’s a good point. Simpler is (often) better.

Nicolas