06-29-2018 06:56 AM
Is there a straightforward way to instantiate many UART cores in the fabric of a Zynq, and easily tie them into the linux system such that kernel drivers automagically handle their, and they'll simply appear as many /dev/tty.xyz devices?
The ultimate goal is that I would then use Python to actuate those as needsbe.
By "many", I mean 100+.
I have very little knowledge of FPGA's, but I thought that stuff like this was the kind of scenario that Zynq was meant to make easy.
I can see that there exists a 16550 IP core, and that I can fit 100 or more into this 53K LUT Zynq I have. But beyond that ... I would really like to get some input before sinking time into trying to do it.
If any Xilinx FAE's are reading, help me out with this and I'll write up the project into a really great applied tech blog post ;)
07-31-2018 01:54 PM
My first question would be: do you need all handshake lines, runtime configurable baudrate, etc.? Or would 100+ UARTlites work as well?
The second is: What version of petalinux are you planning to use? I believe that only 2018.x versions support multiple cascaded interrupt controllers.
And then there is the issue of identifying which /dev/ttySx is which UART that Xilinx doesn't want to solve properly and easy for us to use.
09-09-2018 08:28 PM
Whoa, I didn't even notice the reply.
Though a *bunch* of tinkering, I actually now have a project to build with 12 UartLite's, and the bitstream and DTS worked out (god it was not easy) so that it boots and enumerates all the /dev/ttyULxx's .
As for my linux version: I am presently using the kernel sources packaged into a repo by the designer of the dev board that I have (krtkl, snickerdoodle board), and an Ubuntu distribution provided as-is from them.
I found that I had to rebuild the kernel from source because the maximum number of UartLites had to be increased from 1.
I am unsure about the interrupts. According to some Xilinx page I landed on, I used a concat and an OR block to OR all of them together. I don't have the hardware on hand to actually test the UART output at the moment.
Which I assume means that I would not hit the issue of 16 PS interrupts as I scale up the number of UART's.
As for identifying the UART's ... that is not *super* important for my application. I just need a bunch of functioning UARTs.
Any suggestions (or insight, as I am still a total novice at this) you have, please let me know!
09-10-2018 01:40 AM
So you don't need full 16550's, but can work with the much smaller and fixed baudrate UartLite.
I would not recommend to OR all 100+ interrupts into one IRQ for the PS. The driver must poll them all to find out which one needs to be serviced.
If you use the device tree generator, getting a DTS should not be too difficult. I believe it even understands the OR nowadays.
Or you can go the petalinux way which uses the device tree generator and always builds the kernel from source.
The maximum number of UartLites is a kernel configuration parameter in the latest version. In older versions it was a locally defined macro. In the future it will probably disappear completely and allocate resources dynamically.
09-10-2018 10:32 AM
How should I handle the interrupts for > 16 UartLites? As far as I understand it, the PS only has 16 input interrupts.
I am coming from a microcontroller world, where the expected pattern would be to have a single interrupt and then have a register with flags to check for which interrupt probably caused the IRQ.
09-11-2018 12:29 AM
This is no different on a Zynq running linux. The UartLite has such a register with flags. And unless I am mistaken, so does the GIC in the ARM core. So when you OR the interrupt lines all thoses registers must be read to find the source of the interrupt. If instead you insert another interrupt controller like the AXI INTC only the relevant registers must be read.
But what I meant was: don't OR 100+ interrupts into just 1 of the 16 PS interrupt inputs, but instead spread them.
09-12-2018 12:57 PM
Super, thanks for the info. I owe you a beer next time you're in Palo Alto ...
I am coming from the embedded (microcontroller) world, where you just get whatever interrupts are designed into the chip.
And in cheap IC's, it's not uncommon for several sources to be tied together to a single IRQ line e.g. multiple DMA channels into a single handler, so exhaustively checking the source *and* then the interrupt reason/flag is needed.
You mentioned cascaded AXI INTC's ; for this topology, would I have concat up to 32 uartlites into one AXI INTC, and then concat the output of those together into another INTC, and then route the output of that final controller to the Zynq IRQ?
09-13-2018 03:16 AM
You seem afraid to use more than one PS IRQ line. Why would you insert a second level AXI INTC when you can have up to 16 PS interrupt lines. Just connect the second concat to the Zynq in the block design. This is already a cascade of two different interrupt controllers: AXI INTC and the Zynq native GIC.
Btw. I'm not going to download and install your complete project just to look at the block design. Make a PNG or PDF from it and paste it inline here if you want me to look at it.
09-13-2018 06:54 PM
Well, of course I'm afraid to use PS interrupts ... I don't really know how they are handled inside the PS.
Attached is my example block design that uses 4x hierarchy groups, where the detail of the group object is shown in the second attachment.