I'd just about give my left arm at this point for a working example of using the Xilinx XUartPs stuff with interrupts in a non-loopback, continuously receive data example. I desire to process every character one at a time as it is received. I normally send characters over a serial port connected to the Zybo with a simple C# app but for test purposes, TeraTerm works fine for sending characters.
I'm using Vivado and Vitis 2022.2 and a ZyboZ7-10. I have a very simple project based on the XUartPs interrupt example (which of course just uses the loopback mode and a fixed set of send/receive chars). I've attached the c file to this post (no header file needed) which I think could be executed by anyone with a ZyboZ7-10 with no additional work.
The program initializes the Gic, then initializes the Xuart, then initializes the GPIO (LED) of the Zybo so I could see in a run (not Debug) environment if the hander for the Uart 'event' is ever called (the LED just turns on and off when the Uart event occurs).
The Vitis debug environment isn't consistent. Sometimes the Uart handler is entered, sometimes not - which is why I stuck the LED on/off change in there). Since the debug environment isn't consistent, it's awfully difficult to step through the code to see what exactly is going on with the XUartPs software. And the XUartPS documentation, like most Xilinx documentation, is pretty sparse. At most, it seems the UartISR handler is entered four times - this ought to be a clue but I've haven't discovered what it means yet.
I've included the InitUart function below. Note the Fifo threshold is set to 1 in the InitUart function (which I guess means the Uart 'event' handler UartISR) would be entered with every received character. It is (very) unclear to me based on the comments in the Xilinx XuartPs software what the function XUartPs_Recv() is supposed to do. To quote the xuartps.c file in which the function is provided...
* In interrupt mode, this function will start the receiving, if not the entire
* buffer has been received, the interrupt handler will continue receiving data
* until the entire buffer has been received. A callback function, as specified
* by the application, will be called to indicate the completion of the
* receiving or error conditions.
For interrupt mode, it *seems* I need to call the XUartPs_Recv() function only once (that's why I did it at the end of the InitUart function) and the hander UartISR() would then be called whenever a single new character is received. That character would be available in the 'RecvBuffer' that was provided in the XUartPs_Recv() function call.
I know it's asking a lot but would greatly appreciate some help on this. It's critical to my Zybo use that I can faithfully receive and process characters. The Zybo is a *huge* (and much desired) upgrade over my previous use of AVR controllers for similar applications but no so much if I can't get this working.
int InitUart(XUartPs *ptrUart, u16 UartDeviceId, u16 UartInterruptId)
{
int Status;
u32 IntrMask;
XUartPs_Config *ptrConfig;
// Look-up the Uart config
ptrConfig = XUartPs_LookupConfig(UartDeviceId);
if (ptrConfig == NULL) {return XST_FAILURE;}
// Initialize Uart
Status = XUartPs_CfgInitialize(ptrUart, ptrConfig, ptrConfig->BaseAddress);
if (Status != XST_SUCCESS) {return XST_FAILURE;}
// Self-test Uart
Status = XUartPs_SelfTest(ptrUart);
if (Status != XST_SUCCESS) {return XST_FAILURE;}
// Setup Uart specific items
XUartPs_SetBaudRate(ptrUart, 115200);
IntrMask = XUARTPS_IXR_RXFULL | XUARTPS_IXR_RXEMPTY | XUARTPS_IXR_RXOVR;
XUartPs_SetInterruptMask(ptrUart, IntrMask);
XUartPs_SetOperMode(ptrUart, XUARTPS_OPER_MODE_NORMAL);
XUartPs_SetFifoThreshold(ptrUart, 1);
// Add Uart to Gic system (remember to always use XUartPs_InterruptHandler)
Status = XScuGic_Connect(ptrGic, UartInterruptId, (Xil_ExceptionHandler)XUartPs_InterruptHandler, (void *)ptrUart);
if (Status != XST_SUCCESS) {return Status;}
// Setup a handler for Uart raised 'events'
XUartPs_SetHandler(ptrUart, (XUartPs_Handler)UartISR, ptrUart);
// Enable Uart interrupts with the Gic
XScuGic_Enable(ptrGic, UartInterruptId);
// Enable the Uart
XUartPs_EnableUart(ptrUart);
// In interrupt mode, start receiving so receive events can occur?
XUartPs_Recv(ptrUart, RecvBuffer, TEST_BUFFER_SIZE);
return XST_SUCCESS;
}
Question
engrpetero
I'd just about give my left arm at this point for a working example of using the Xilinx XUartPs stuff with interrupts in a non-loopback, continuously receive data example. I desire to process every character one at a time as it is received. I normally send characters over a serial port connected to the Zybo with a simple C# app but for test purposes, TeraTerm works fine for sending characters.
I'm using Vivado and Vitis 2022.2 and a ZyboZ7-10. I have a very simple project based on the XUartPs interrupt example (which of course just uses the loopback mode and a fixed set of send/receive chars). I've attached the c file to this post (no header file needed) which I think could be executed by anyone with a ZyboZ7-10 with no additional work.
The program initializes the Gic, then initializes the Xuart, then initializes the GPIO (LED) of the Zybo so I could see in a run (not Debug) environment if the hander for the Uart 'event' is ever called (the LED just turns on and off when the Uart event occurs).
The Vitis debug environment isn't consistent. Sometimes the Uart handler is entered, sometimes not - which is why I stuck the LED on/off change in there). Since the debug environment isn't consistent, it's awfully difficult to step through the code to see what exactly is going on with the XUartPs software. And the XUartPS documentation, like most Xilinx documentation, is pretty sparse. At most, it seems the UartISR handler is entered four times - this ought to be a clue but I've haven't discovered what it means yet.
I've included the InitUart function below. Note the Fifo threshold is set to 1 in the InitUart function (which I guess means the Uart 'event' handler UartISR) would be entered with every received character. It is (very) unclear to me based on the comments in the Xilinx XuartPs software what the function XUartPs_Recv() is supposed to do. To quote the xuartps.c file in which the function is provided...
* In interrupt mode, this function will start the receiving, if not the entire
* buffer has been received, the interrupt handler will continue receiving data
* until the entire buffer has been received. A callback function, as specified
* by the application, will be called to indicate the completion of the
* receiving or error conditions.
For interrupt mode, it *seems* I need to call the XUartPs_Recv() function only once (that's why I did it at the end of the InitUart function) and the hander UartISR() would then be called whenever a single new character is received. That character would be available in the 'RecvBuffer' that was provided in the XUartPs_Recv() function call.
I know it's asking a lot but would greatly appreciate some help on this. It's critical to my Zybo use that I can faithfully receive and process characters. The Zybo is a *huge* (and much desired) upgrade over my previous use of AVR controllers for similar applications but no so much if I can't get this working.
int InitUart(XUartPs *ptrUart, u16 UartDeviceId, u16 UartInterruptId) { int Status; u32 IntrMask; XUartPs_Config *ptrConfig; // Look-up the Uart config ptrConfig = XUartPs_LookupConfig(UartDeviceId); if (ptrConfig == NULL) {return XST_FAILURE;} // Initialize Uart Status = XUartPs_CfgInitialize(ptrUart, ptrConfig, ptrConfig->BaseAddress); if (Status != XST_SUCCESS) {return XST_FAILURE;} // Self-test Uart Status = XUartPs_SelfTest(ptrUart); if (Status != XST_SUCCESS) {return XST_FAILURE;} // Setup Uart specific items XUartPs_SetBaudRate(ptrUart, 115200); IntrMask = XUARTPS_IXR_RXFULL | XUARTPS_IXR_RXEMPTY | XUARTPS_IXR_RXOVR; XUartPs_SetInterruptMask(ptrUart, IntrMask); XUartPs_SetOperMode(ptrUart, XUARTPS_OPER_MODE_NORMAL); XUartPs_SetFifoThreshold(ptrUart, 1); // Add Uart to Gic system (remember to always use XUartPs_InterruptHandler) Status = XScuGic_Connect(ptrGic, UartInterruptId, (Xil_ExceptionHandler)XUartPs_InterruptHandler, (void *)ptrUart); if (Status != XST_SUCCESS) {return Status;} // Setup a handler for Uart raised 'events' XUartPs_SetHandler(ptrUart, (XUartPs_Handler)UartISR, ptrUart); // Enable Uart interrupts with the Gic XScuGic_Enable(ptrGic, UartInterruptId); // Enable the Uart XUartPs_EnableUart(ptrUart); // In interrupt mode, start receiving so receive events can occur? XUartPs_Recv(ptrUart, RecvBuffer, TEST_BUFFER_SIZE); return XST_SUCCESS; }
UartTest.c
Edited by engrpeteroLink to comment
Share on other sites
12 answers to this question
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now