Xilinx / embeddedsw

Xilinx Embedded Software (embeddedsw) Development
Other
949 stars 1.07k forks source link

Typo in uartps_intr_example.c #143

Open jgriffitts opened 4 years ago

jgriffitts commented 4 years ago

The interrupt example for UART PS does not work on Zynq7000. In lines 66-69 it muddles the device definition constants: the UART device is UARTPS_0 but the interrupt ID uses UARTPS_1:

#define INTC        XScuGic
#define UART_DEVICE_ID      XPAR_XUARTPS_0_DEVICE_ID
#define INTC_DEVICE_ID      XPAR_SCUGIC_SINGLE_DEVICE_ID
#define UART_INT_IRQ_ID     XPAR_XUARTPS_1_INTR

When the example is executed, the interrupt handler is never called and the program hangs in the while loop at line 285. Changing the last line above to use XPAR_XUARTPS_0_INTR makes it work.

There are more references to XUARTPS_1 in line183-184, that I don't understand but I don't think they apply to my situation.

Ryaninthegame commented 9 months ago

I am using the Zynq UltraScale+ MPSoC, and the board is ZCU102. I am attempting to port UARTPS on the PMU, but I have not been able to make it work. Similar to your case, I am stuck at line 285. Has this issue been resolved? Thank you.

jgriffitts commented 9 months ago

I dug back into my dev notes from Oct 2020, and it looks like I resolved this, though I don't remember it. This is what I wrote:

The problem with the UART interrupt handler was that the INTC was set up using UART_1 instead of UART_0. This typo came from Xilinx's example source file. I wasted a couple of days pondering work-arounds for this, when it was solved with less than an hour of ordinary debugging!

I submitted the issue to https://github.com/Xilinx/embeddedsw/issues/143

. . . a few days later, I wrote:

Xilinx's xuartps_intr.c module is misdesigned, as far as I can tell. It isn't possible to queue up more Tx data in the Tx empty interrupt handler. I could rewrite this, but instead I think I'll just run the console output off of the timer interrupt. The UART console is only temporary anyway, used on the ARTYZ7 board. I have wasted way too much time on this.

. . . a few days later yet:

Got rid of calls to XScuGic_CfgInitialize and Xil_ExceptionInit() in Timer.cpp, and the console Tx now seems to work. Console Rx has a funny symptom: keystroke characters are delayed by one event, as if there's an extra 1-character FIFO in the line, but RxRdy is not signalled until the next character is pressed. Turns out there is a FIFO, and I can call XUartPs_SetFifoThreshold() to set the interrupt threshold.

The interrupt UART driver still seems to be buggy -- there are multiple Rx interrupts for each keystroke -- but I think I'll move on, since this will only be used for the Arty board. If there are more problems with the UART, it may be necessary to rewrite the whole UART driver, and put the Tx ring buffer directly into the interrupt-level driver.

Is this helpful? I can dig around some more in my old notes if needed, but a quick look didn't find anything relevant. It looks like I spent a lot of time fighting with this, but it didn't stick in my memory.

Ryaninthegame commented 9 months ago

First of all, thank you very much for your willingness to respond. I want to know the difference between XIntc and XScuGic. Based on my understanding of the code, XIntc is suitable for the MicroBlaze architecture, and XScuGic is suitable for the ARM architecture. Did you choose to use XScuGic because your architecture is ARM? Thank you.

jgriffitts commented 9 months ago

I don't recall making any decision about this, and my notes don't mention it. I assume that I just used the default interrupt control for the ARM that we were using. Sorry, no help for you.

anirudha1977 commented 9 months ago

XIntc is for Xilinx AXI Interrupt Controller. It is a Soft Controller that is designed to work with Soft CPU cores (e.g. Microblaze, Microblaze-V (RISC-V version of MB). XScuGIC as rightly said is for ARM GIC that is for ARM Cores. Any soft peripheral can be connected to a Soft CPU core (e.g. MB) or to a ARM Core (through PS-PL interface). If it is for Soft core, the interrupts will be processed through AXI INTC (XIntc), if it is for ARM CPU (then XScuGiC). A hardened PS peripheral can also be routed to a Soft Microblaze, in which case, the interrupts from this PS peripheral will be processed by XIntc.

Regarding other comments, will request my colleagues (who know more about this UART driver to respond back) in this thread.

Just curious, which release are you using? Is it some recent release or an old one?

Ryaninthegame commented 9 months ago

@anirudha1977 Thank you for your response. I have 2 questions to inquire about:

  1. My board is ZCU102. If I am running on the PMU, using XIntc should be correct, right (since PMU is MicroBlaze)?
  2. XIntc and XScuGIC refer to the GIC Proxy inside the red box in the diagram, correct? image
anirudha1977 commented 9 months ago

No, you cant use INTC with PMU. The PMU processor is connected to a version of hardened IOModule (https://docs.xilinx.com/v/u/en-US/pg111-iomodule) and not the standard AXI INTC. And though PMU is microblaze based, it is not a soft microblaze core. INTC can be used with soft microblaze core.

GIC Proxy is not something that is truly GIC. It cannot be handled through GIC driver. GIC proxy is used for scenarios when both APU and RPU are down, but we want peripheral interrupts to reach PMU. As an example, Wake On LAN. For such scenarios, typically APU and RPU are down. And you want the system to go up based on certain ethernet packets. In such scenarios, upon receiving such packets, GIC Proxy interrupts PMU which then starts the system wake up process by waking up APU/RPU and other power deomains.

Ryaninthegame commented 9 months ago

As shown in your link, I see the diagram of the MicroBlaze IOModule, and I have highlighted the portion with INTC circuitry. Could you clarify if the INTC here is the same as the INTC you mentioned earlier, which you said MicroBlaze cannot use? Thank you very much for your assistance.

image

Ryaninthegame commented 9 months ago

I contacted the FAE, and the FAE replied that this UART driver's interrupt is suitable for the APU but not for the PMU. The reason is that the architecture of the PMU is different from the APU. Thanks a lot for the help from both of you.