• 0
TeslaCrytpo

Zynq Uart Interrupts Issue

Question

Hello All,

I have an issue getting the interrupts to work on a Uart placed in the FPGA fabric and connected to the Zynq processor on a Cora Z7-10 board. Also, thanks to the help from jpeyron to suggest the Zedboard example.

What I have discovered in implementing a uart in the FPGA fabric and connecting it to Zync is that the interrupts do not seem to work !!!

My code shown below functionally works, i.e. the basic command parser that I've implemented with a continuous loop (quasi-polling) does functionally work.However, the interrupts do not work whatsoever. I've seen other posts dealing with the same subject; however, it appears that there is not concrete resolution to the issue.I did make sure that my interrupt was rising edge triggered by configuring the interrupt controller in Vivado ... but to no avail.

If anyone has insight, help is most appreciated.

Kind Regards,

James

 


/******************************************************************************/
/**
*
* @file Take from - xuartlite_intr_example.c from Xilinx
*
* Modified to create a general command parser, so as to control some
* peripherals in the FPGA fabric (such as future ADC converter Verilog module.)
*
* VIVADO SETUP = The block diagram contains an interrupt controller and
*                axi uartlite module in conjunction with a Zynq module.
*                The purpose of this design is to validate the approach of
*                using a FPGA fabric UART connected to the PMOD port of the
*                Cora board (or any other PMOD port such as in Zeboard, etc.)
*                and sending data to the Zynq with a standard 115200 N81 conneciton.
*
******************************************************************************/

/***************************** Include Files *********************************/

#include "xparameters.h"
#include "xuartlite.h"
#include "xintc.h"
#include "xil_exception.h"
#include "sleep.h"
#include <stdio.h>
#include "string.h"
/************************** Constant Definitions *****************************/

/*
 * The following constants map to the XPAR parameters created in the
 * xparameters.h file. They are defined here such that a user can easily
 * change all the needed parameters in one place.
 */
#define UARTLITE_DEVICE_ID      XPAR_UARTLITE_0_DEVICE_ID
#define INTC_DEVICE_ID          XPAR_INTC_0_DEVICE_ID
#define UARTLITE_INT_IRQ_ID     XPAR_INTC_0_UARTLITE_0_VEC_ID

/*
 * The following constant controls the length of the buffers to be sent
 * and received with the UartLite device.
 */
#define TEST_BUFFER_SIZE        8

/************************** Function Prototypes ******************************/

int UartLiteIntrExample(u16 DeviceId);

int SetupInterruptSystem(XUartLite *UartLitePtr);

void SendHandler(void *CallBackRef, unsigned int EventData);

void RecvHandler(void *CallBackRef, unsigned int EventData);

/************************** Variable Definitions *****************************/

 XUartLite UartLite;            /* The instance of the UartLite Device */
 XIntc InterruptController;     /* The instance of the Interrupt Controller */

u8 SendBuffer[TEST_BUFFER_SIZE];
u8 ReceiveBuffer[TEST_BUFFER_SIZE];

static volatile int TotalReceivedCount;
static volatile int TotalSentCount;
int gBytesRecv;                    // Global:: bytes received in rx handler
int gCmdAdcRun = 1;             // Global:: command recv tor run adc (asserted low signal)
int gSentCount = 0;             // Global:: sent count , dispalyed in terminal

void Clear (u8 *RecieveBuffer){
    *ReceiveBuffer = 0;
}
/******************************************************************************/
/**
*
* Main function to call the UartLite interrupt example.
*
* @param    None
*
* @return    XST_SUCCESS if successful, XST_FAILURE if unsuccessful
*
* @note        None
*
*******************************************************************************/
int main(void)
{
    int Status;

    /*
     * Run the UartLite Interrupt example, specify the Device ID that is
     * generated in xparameters.h.
     */
    Status = UartLiteIntrExample(UARTLITE_DEVICE_ID);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }
    while(1) {

        /* Send */
        XUartLite_Send(&UartLite, SendBuffer, TEST_BUFFER_SIZE);
        xil_printf("Data Index = \t%d\r\n", gSentCount++);
        usleep(1000000);

        /* Receive */
        gBytesRecv = XUartLite_Recv(&UartLite, ReceiveBuffer, TEST_BUFFER_SIZE);
        gCmdAdcRun = strcmp((char*)ReceiveBuffer, (char*)"put adc\r");

        if(!gCmdAdcRun){
            printf("*** Now triggering the A/D converter.\r\n");
            Clear((u8*)&ReceiveBuffer);
        }

        //for(infiniteLoop = 0; infiniteLoop < 75000000; infiniteLoop++);
        usleep(1000000);
    }

    return XST_SUCCESS;
}

//****************************************************************************
//
// This function intializes the UART.
//
//***************************************************************************

int UartLiteIntrExample(u16 DeviceId)
{
    int Status;
    int Index;

    Status = XUartLite_Initialize(&UartLite, DeviceId);
    if (Status != XST_SUCCESS) {
        xil_printf("Uart initialization failed!\r\n");
    } else {
        xil_printf("Uart initialization successful!\r\n");
    }

    Status = XUartLite_SelfTest(&UartLite);
    if (Status != XST_SUCCESS) {
        xil_printf("Uart selftest failed!\r\n");
    } else {
        xil_printf("Uart selftest successful!\r\n");
    }

    Status = SetupInterruptSystem(&UartLite);
    if (Status != XST_SUCCESS) {
        xil_printf("Uart interrupt setup failed!\r\n");
    } else {
        xil_printf("Uart interrupt setup successful!\r\n");
    }

    XUartLite_SetSendHandler(&UartLite, SendHandler, &UartLite);
    XUartLite_SetRecvHandler(&UartLite, RecvHandler, &UartLite);

    xil_printf("Uart interrupt handler setup done!\r\n");

    XUartLite_EnableInterrupt(&UartLite);
    xil_printf("Uart interrupts enabled!\r\n");


    for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) {
        SendBuffer[Index] = Index;
        ReceiveBuffer[Index] = 0;
    }

    return XST_SUCCESS;
}

/*****************************************************************************/
/**
*
* This function SHOULD handle the interrupt generated when uart TX data.
*
****************************************************************************/
void SendHandler(void *CallBackRef, unsigned int EventData)
{
    xil_printf("Interrupt thrown!\r\n");

    TotalSentCount = EventData;
}

/****************************************************************************/
/**
*
* This function SHOULD handle the interrupt generated when uart RX data.
*
****************************************************************************/
void RecvHandler(void *CallBackRef, unsigned int EventData)
{
    printf("Interrupt catched!\r\n");

    TotalReceivedCount = EventData;
}

/****************************************************************************/
/**
*
* This function configures the Interrupt Handler to point to UartInterrupt.
* Evidently, it is NOT Working.
*
****************************************************************************/
int SetupInterruptSystem(XUartLite *UartLitePtr)
{

    int Status;

    /*
     * Initialize the interrupt controller driver so that it is ready to
     * use.
     */
    Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    XIntc_Enable(&InterruptController, INTC_DEVICE_ID);

    /*
     * Connect a device driver handler that will be called when an interrupt
     * for the device occurs, the device driver handler performs the
     * specific interrupt processing for the device.
     */
    Status = XIntc_Connect(&InterruptController, UARTLITE_INT_IRQ_ID,
               (XInterruptHandler)XUartLite_InterruptHandler,
               (void *)UartLitePtr);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    //XScuGic_SetPriorityTriggerType(&InterruptController, UARTLITE_INT_IRQ_ID, 0, 3);
    Status = XIntc_SelfTest(&InterruptController);
    if (Status != XST_SUCCESS){
        return XST_FAILURE;
    }
    xil_printf("Trigger set to rising edge.\n\r");


    /*
     * Start the interrupt controller such that interrupts are enabled for
     * all devices that cause interrupts, specific real mode so that
     * the UartLite can cause interrupts through the interrupt controller.
     */
    Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    /*
     * Enable the interrupt for the UartLite device.
     */
    XIntc_Enable(&InterruptController, UARTLITE_INT_IRQ_ID);

    /*
     * Initialize the exception table.
     */
    Xil_ExceptionInit();

    /*
     * Register the interrupt controller handler with the exception table.
     */
    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
             (Xil_ExceptionHandler)XIntc_InterruptHandler,
             &InterruptController);

    /*
     * Enable exceptions.
     */
    Xil_ExceptionEnable();

    return XST_SUCCESS;
}

Vivado_UART.png

parser.png

Share this post


Link to post
Share on other sites

3 answers to this question

Recommended Posts

  • 0

Additionally, I have drawn some insight from these posts:

1) The question is raised as to whether an interrupt controller is necessary in the fabric at all as detailed in this link:

https://forums.xilinx.com/t5/Embedded-Processor-System-Design/running-the-AXI-UART-Lite-irq-examples-on-Zynq-AXI-intc-vs-PS/td-p/867810

2) The same question that I raised was also raised previously but without a definitive answer.

https://forums.xilinx.com/t5/Embedded-Processor-System-Design/UARTLite-Interrupts-Not-Working-on-Zynq/td-p/651594

I was just wondering if anyone at Digilent has setup a UART on the PMOD of the Cora board, and sent data to the Zynq in bare metal mode with interrupts enabled.

Thanks.

 

Share this post


Link to post
Share on other sites
  • 0

I have performed an experiment, where I've disabled the interrupt controller C code functions as shown below and re-run the system.

I tested by very basic two command parser and it responds correctly! From this test, it appears that configuring the interrupts has no value, as I've disabled them and the system works.

Apparently, creating an interrupt controller in the fpga fabric is unnecessary.

Thanks. James


/******************************************************************************/
/**
 *
 * @file Take from - xuartlite_intr_example.c from Xilinx
 *
 * Modified to create a general command parser, so as to control some
 * peripherals in the FPGA fabric (such as future ADC converter Verilog module.)
 *
 * VIVADO SETUP = The block diagram contains an interrupt controller and
 *                axi uartlite module in conjunction with a Zynq module.
 *                The purpose of this design is to validate the approach of
 *                using a FPGA fabric UART connected to the PMOD port of the
 *                Cora board (or any other PMOD port such as in Zeboard, etc.)
 *                and sending data to the Zynq with a standard 115200 N81 connection.
 *
 *
 ******************************************************************************/

/***************************** Include Files *********************************/

#include "xparameters.h"
#include "xuartlite.h"
#include "xintc.h"
#include "xil_exception.h"
#include "sleep.h"
#include <stdio.h>
#include "string.h"
/************************** Constant Definitions *****************************/

/*
 * The following constants map to the XPAR parameters created in the
 * xparameters.h file. They are defined here such that a user can easily
 * change all the needed parameters in one place.
 */
#define UARTLITE_DEVICE_ID      XPAR_UARTLITE_0_DEVICE_ID
#define INTC_DEVICE_ID          XPAR_INTC_0_DEVICE_ID
#define UARTLITE_INT_IRQ_ID     XPAR_INTC_0_UARTLITE_0_VEC_ID

/*
 * The following constant controls the length of the buffers to be sent
 * and received with the UartLite device.
 */
#define TEST_BUFFER_SIZE        8

/************************** Function Prototypes ******************************/

int UartLiteIntrExample(u16 DeviceId);

//int SetupInterruptSystem(XUartLite *UartLitePtr);

void SendHandler(void *CallBackRef, unsigned int EventData);

void RecvHandler(void *CallBackRef, unsigned int EventData);

/************************** Variable Definitions *****************************/

XUartLite UartLite; /* The instance of the UartLite Device */
//XIntc InterruptController; /* The instance of the Interrupt Controller */

u8 SendBuffer[TEST_BUFFER_SIZE];
u8 RecvBuffer[TEST_BUFFER_SIZE];

static volatile int TotalReceivedCount;
static volatile int TotalSentCount;
int gBytesRecv;                    // Global:: bytes received in rx handler
int gParser_CmdRun = 1; // Global:: command recv tor run adc (asserted low signal)
int gParser_CmdRst = 1;
int gSentCount = 0;             // Global:: sent count , dispalyed in terminal


//----------------------------------------------------
//  Helper Functions::  Clear and Parse for RecvBuffer
//----------------------------------------------------
void Clear(u8 *RecvBuffer) {
    *RecvBuffer = 0;
}

void Parse(u8 *RecvBuffer) {
    gParser_CmdRun = strcmp((char*) RecvBuffer, (char*) "put adc\r");

    if (!gParser_CmdRun) {
        printf("*** Now triggering the A/D converter.\r\n");
        Clear((u8*) RecvBuffer);
    }

    gParser_CmdRst = strcmp((char*) RecvBuffer, (char*) "put rst\r");

    if (!gParser_CmdRst) {
        printf("*** Reset/Flushing buffer of A/D converter.\r\n");
        Clear((u8*) RecvBuffer);
    }
}
/******************************************************************************/
/**
 *
 * Main function to call the UartLite interrupt example.
 *
 * @param    None
 *
 * @return    XST_SUCCESS if successful, XST_FAILURE if unsuccessful
 *
 * @note        None
 *
 *******************************************************************************/
int main(void) {
    int Status;

    /*
     * Run the UartLite Interrupt example, specify the Device ID that is
     * generated in xparameters.h.
     */
    Status = UartLiteIntrExample(UARTLITE_DEVICE_ID);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }
    while (1) {

        /* Send */
        XUartLite_Send(&UartLite, SendBuffer, TEST_BUFFER_SIZE);
        xil_printf("Data Index = \t%d\r\n", gSentCount++);
        usleep(1000000);

        /* Receive */
        gBytesRecv = XUartLite_Recv(&UartLite, RecvBuffer, TEST_BUFFER_SIZE);
        Parse((u8*)RecvBuffer);

        //for(infiniteLoop = 0; infiniteLoop < 75000000; infiniteLoop++);
        usleep(1000000);
    }

    return XST_SUCCESS;
}

//****************************************************************************
//
// This function intializes the UART.
//
//***************************************************************************

int UartLiteIntrExample(u16 DeviceId) {
    int Status;
    int Index;

    Status = XUartLite_Initialize(&UartLite, DeviceId);
    if (Status != XST_SUCCESS) {
        xil_printf("Uart initialization failed!\r\n");
    } else {
        xil_printf("Uart initialization successful!\r\n");
    }

    Status = XUartLite_SelfTest(&UartLite);
    if (Status != XST_SUCCESS) {
        xil_printf("Uart selftest failed!\r\n");
    } else {
        xil_printf("Uart selftest successful!\r\n");
    }

    //Status = SetupInterruptSystem(&UartLite);
    //if (Status != XST_SUCCESS) {
    //    xil_printf("Uart interrupt setup failed!\r\n");
    //} else {
    //    xil_printf("Uart interrupt setup successful!\r\n");
    //}

    //XUartLite_SetSendHandler(&UartLite, SendHandler, &UartLite);
    //XUartLite_SetRecvHandler(&UartLite, RecvHandler, &UartLite);

    //xil_printf("Uart interrupt handler setup done!\r\n");

    XUartLite_EnableInterrupt(&UartLite);
    xil_printf("Uart interrupts enabled!\r\n");

    for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) {
        SendBuffer[Index] = Index;
        RecvBuffer[Index] = 0;
    }

    return XST_SUCCESS;
}

/*****************************************************************************/
/**
 *
 * This function SHOULD handle the interrupt generated when uart TX data.
 *
 ****************************************************************************/
//void SendHandler(void *CallBackRef, unsigned int EventData) {
//    xil_printf("Interrupt thrown!\r\n");
//
//    TotalSentCount = EventData;
//}

/****************************************************************************/
/**
 *
 * This function SHOULD handle the interrupt generated when uart RX data.
 *
 ****************************************************************************/
//void RecvHandler(void *CallBackRef, unsigned int EventData) {
//    printf("Interrupt catched!\r\n");
//
//    TotalReceivedCount = EventData;
//}

/****************************************************************************/
/**
 *
 * This function configures the Interrupt Handler to point to UartInterrupt.
 * Evidently, it is NOT Working.
 *
 ****************************************************************************/
//int SetupInterruptSystem(XUartLite *UartLitePtr) {
//
//    int Status;
//
//    /*
//     * Initialize the interrupt controller driver so that it is ready to
//     * use.
//     */
//    Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
//    if (Status != XST_SUCCESS) {
//        return XST_FAILURE;
//    }
//
//    XIntc_Enable(&InterruptController, INTC_DEVICE_ID);
//
//    /*
//     * Connect a device driver handler that will be called when an interrupt
//     * for the device occurs, the device driver handler performs the
//     * specific interrupt processing for the device.
//     */
//    Status = XIntc_Connect(&InterruptController, UARTLITE_INT_IRQ_ID,
//            (XInterruptHandler) XUartLite_InterruptHandler,
//            (void *) UartLitePtr);
//    if (Status != XST_SUCCESS) {
//        return XST_FAILURE;
//    }
//
//    //XScuGic_SetPriorityTriggerType(&InterruptController, UARTLITE_INT_IRQ_ID, 0, 3);
//    Status = XIntc_SelfTest(&InterruptController);
//    if (Status != XST_SUCCESS) {
//        return XST_FAILURE;
//    }
//    xil_printf("Trigger set to rising edge.\n\r");
//
//    /*
//     * Start the interrupt controller such that interrupts are enabled for
//     * all devices that cause interrupts, specific real mode so that
//     * the UartLite can cause interrupts through the interrupt controller.
//     */
//    Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
//    if (Status != XST_SUCCESS) {
//        return XST_FAILURE;
//    }
//
//    /*
//     * Enable the interrupt for the UartLite device.
//     */
//    XIntc_Enable(&InterruptController, UARTLITE_INT_IRQ_ID);
//
//    /*
//     * Initialize the exception table.
//     */
//    Xil_ExceptionInit();
//
//    /*
//     * Register the interrupt controller handler with the exception table.
//     */
//    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
//            (Xil_ExceptionHandler) XIntc_InterruptHandler,
//            &InterruptController);
//
//    /*
//     * Enable exceptions.
//     */
//    Xil_ExceptionEnable();
//
//    return XST_SUCCESS;
//}

CommandParser.png

Share this post


Link to post
Share on other sites
  • 0

Hi @TeslaCrytpo,

Here is a xilinx forum thread that discussed altering the loop back uart zynq interrupt example that looks like it would be useful for your project.

best regards,

Jon

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now