Buscar este blog

miércoles, 26 de noviembre de 2014

PRACTICA # 3 INTERRUPCION GPIO CON AXI

  • En esta práctica se desarrollara la implementación del Bus AXI para comunicar la parte PS con la PL y poder tener acceso a los puertos GPIO. El esquema siguiente muestra en general lo que se realizara:
                                             


  • El sistema PL se encargara de controlar el display OLED y crear los módulos de interfaz I/O de 32 bits internos. Toda la descripción del hardware se hizo en DK Handel-C cuyo código principal se muestra a continuación:

par
    {
       while(1)
       {
           OledClear();
           OledSetCursor(0, 0);
           OledPutString("x[0-31]  = ");
           conv = b_itoab((signed 32)(LEDS_AXI_wrapper.salida_0_31_tri_o));
           OledPutString(conv);
          
           OledSetCursor(0, 2);
           OledPutString("x[31-63] = ");
           conv = b_itoab((signed 32)(LEDS_AXI_wrapper.salida_32_63_tri_o));
           OledPutString(conv);
           delay_ms(C_MHZ,1000);
       }
       while(1)
       {
           par
           {
                LEDS++;
                PS_OUT_0_31++;
                PS_OUT_32_63++;
           }
           delay_ms(C_MHZ,1000); //1000 ms
       }
    }


El primer While se encarga de recibir lo que está mandando la parte PS e imprimiéndola en el display OLED separando los 2 canales de 32 bits.

En el segundo While PL estará enviando hacia PS el valor de los 2 canales de salida de 32 bits. Para este demos solo se envía contadores incrementándose.

Nótese que los 2 whiles son independientes y se ejecutan en paralelo.

  • La metodología aplicada para la creación PL (VIVADO - DK Handel-C) de la interfaz es la mostrada en la figura siguiente:

  • La parte PS (VIVADO diagrama de bloques) queda de la siguiente manera:

A partir de este sistema se obtiene el archivo AXI_GPIO.dcp parte sintetizable de vivado que servirá para integrarlo en la PL (vivado y Dk Handel-C).

  • La configuración de ZYNQ se muestra en las siguientes imágenes:





  • La estructura de los archivos  para PL es:

El archivo final que contiene tanto PL como PS es AXI_GPIO.bit






  • El código para la parte de SDK eclipse C/C++ es el siguiente:

/*****************************************************************************/
/*                         I N C L U D E   F I L E S                         */
/*****************************************************************************/

#include <stdio.h>

#include "xparameters.h"
#include "xgpio.h"
#include "xuartps.h"
#include "xtime_l.h"
#include "xscugic.h"
#include "xil_exception.h"

/*****************************************************************************/
/*                           C O N S T A N T S                               */
/*****************************************************************************/

//The following constant maps to the name of the hardware instances that
// were created in the Vivado system.
#define INTC_DEVICE_ID                  XPAR_PS7_SCUGIC_0_DEVICE_ID
#define INTC_GPIO_INTERRUPT_ID          XPAR_FABRIC_AXI_GPIO_1_IP2INTC_IRPT_INTR
#define INTC                            XScuGic
#define INTC_HANDLER                    XScuGic_InterruptHandler
#define BUTTON_INTERRUPT                XGPIO_IR_MASK

#define CPU_CLOCK_FREQ                                             XPAR_PS7_CORTEXA9_0_CPU_CLK_FREQ_HZ
#define FPGA_CLOCK_FREQ                   100000000

#define GPIO_EXAMPLE_DEVICE_ID    XPAR_AXI_GPIO_0_DEVICE_ID
#define GPIO_EXAMPLE_DEVICE_ID_1  XPAR_AXI_GPIO_1_DEVICE_ID

// The following constant is used to determine which channel of the GPIO is
// used for the LED if there are 2 channels supported.

#define LED_CHANNEL_1 1
#define LED_CHANNEL_2 2

/*******************************************************************************/
/*                    F U N C T I O N   D E C L A R A T I O N S                */
/*******************************************************************************/
int          SetupInterruptSystem      ();
void         GpioIsr                   (void *InstancePtr);


/*****************************************************************************/
/*                            V A R I A B L E S                              */
/*****************************************************************************/
XUartPs Uart_Ps;                                          /* The instance of the UART Driver */
XGpio Gpio, Gpio1;        // The Instance of the GPIO Driver
static       INTC         Intc;



/*****************************************************************************/
/*                                M A I N                                    */
/*****************************************************************************/
int main(void)
{
    int Status,SentCount = 0;
    long int ust_limit = 83333323;
    long int delay, i;
    XUartPs_Config *Config;
    u8 HelloZynq[] = "Hello Zynq\n";
    long int a,b;

    XTime t1, t2;

    // Initialize the UART 1 driver
    Config = XUartPs_LookupConfig(XPAR_PS7_UART_1_DEVICE_ID);
    if (NULL == Config)
    {
                                                return XST_FAILURE;
    }

    Status = XUartPs_CfgInitialize(&Uart_Ps, Config, Config->BaseAddress);
    if (Status != XST_SUCCESS)
    {
                                                return XST_FAILURE;
    }

    // Initialize the GPIO driver

    Status = XGpio_Initialize(&Gpio, GPIO_EXAMPLE_DEVICE_ID);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    Status = XGpio_Initialize(&Gpio1, GPIO_EXAMPLE_DEVICE_ID_1);
        if (Status != XST_SUCCESS) {
            return XST_FAILURE;
        }


        Status = SetupInterruptSystem();
                        if (Status != XST_SUCCESS) {
                             return XST_FAILURE;
                        }

    // Clear the LEDs
    XGpio_DiscreteWrite(&Gpio, LED_CHANNEL_1, 0);
    XGpio_DiscreteWrite(&Gpio, LED_CHANNEL_2, 0);

    printf(Microcarsil, 2014\n");

    while (1)
    {
                        for(i=0;i<4294967295;i++)  // 32 bits = 0-4294967295
                        {
                                                  //a = XGpio_DiscreteRead(&Gpio1, LED_CHANNEL_1);
                                                  //b = XGpio_DiscreteRead(&Gpio1, LED_CHANNEL_2);
                                                  XGpio_DiscreteWrite(&Gpio, LED_CHANNEL_1, i);
                                                  XGpio_DiscreteWrite(&Gpio, LED_CHANNEL_2, i);

                                                  XTime_GetTime(&t1);                                                                                                        // Get time before delay
                                                  for(delay=0;delay<ust_limit;delay++){};
                                                  XTime_GetTime(&t2);                                                                                                        // Get time after delay

                                                  u32 clocks = 2 * (t2 - t1);                             // Compute time for memcpy (Note: ARM PERIPHCLK is twice period of CPU clock)
                                                  float dt = (float)clocks / (float)CPU_CLOCK_FREQ;  // Compute clock time
                                                  //printf("  CPU_CLOCK_FREQ   = %d MHz\n", CPU_CLOCK_FREQ);
                                                  //printf("  CPU clocks       = %d\n", clocks);
                                                  //printf("  CPU Time         = %f\n", dt);
                                                  //printf("  PS_OUT_0_31      = %d\n", a);
                                                  //printf("  PS_OUT_32_63     = %d\n", b);

                                                  //Send "Hello Zynq"

                                                 // while (SentCount < (sizeof(HelloZynq) - 1))
                                                  //{
                                                                        //SentCount += XUartPs_Send(&Uart_Ps, &HelloZynq[SentCount], 1);
                                                  //}
                                                  //SentCount = 0;
                                                  //while (!XUartPs_IsReceiveData(Config->BaseAddress));
                                                                                                                        //XUartPs_Recv(&Uart_Ps, &RecvBuf[RecvCount], 1);
                        }
    }

    return XST_SUCCESS;
}

/*******************************************************************************/
/*              I N T E R R U P T   S E R V I C E   R O U T I N E              */
/*******************************************************************************/


void GpioIsr(void *InstancePtr)
{
                        u32 a,b;

                        XGpio *GpioPtr = (XGpio *)InstancePtr;

                        // Disable the interrupt
                        XGpio_InterruptDisable(GpioPtr, BUTTON_INTERRUPT);

                        // There should not be any other interrupts occuring other than the the button changes
                        if ((XGpio_InterruptGetStatus(GpioPtr) & BUTTON_INTERRUPT)!= BUTTON_INTERRUPT) {
                                                return;
                        }

                        // Read state of push buttons and determine which ones changed
                        // states from the previous interrupt. Save a copy of the buttons
                        // for the next interrupt

                        a  = XGpio_DiscreteRead(&Gpio1, LED_CHANNEL_1);
                        b  = XGpio_DiscreteRead(&Gpio1, LED_CHANNEL_2);

                         printf("  PS_OUT_0_31      = %d\n", a);
                         printf("  PS_OUT_32_63     = %d\n\n", b);


                        // Clear the interrupt such that it is no longer pending in the GPIO
                        (void)XGpio_InterruptClear(GpioPtr, BUTTON_INTERRUPT);

                        // Enable the interrupt
                        XGpio_InterruptEnable(GpioPtr, BUTTON_INTERRUPT);

}


/*******************************************************************************/
/*              S E T U P   I N T E R R U P T   S Y S T E M                    */
/*******************************************************************************/
int SetupInterruptSystem()
{
                        int                   Result;
                        INTC               *IntcInstancePtr = &Intc;

                        XScuGic_Config *IntcConfig;

                        // Initialize the interrupt controller driver so that it is ready to use.

                        IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
                        if (NULL == IntcConfig) {
                                                return XST_FAILURE;
                        }

                        Result = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,
                                                                                                                        IntcConfig->CpuBaseAddress);
                        if (Result != XST_SUCCESS) {
                                                return XST_FAILURE;
                        }

                        XScuGic_SetPriorityTriggerType(IntcInstancePtr, INTC_GPIO_INTERRUPT_ID,
                                                                                                                        0xA0, 0x3);

                        // Connect the interrupt handler that will be called when an
                        // interrupt occurs for the device.

                        Result = XScuGic_Connect(IntcInstancePtr, INTC_GPIO_INTERRUPT_ID,
                                                                                                 (Xil_ExceptionHandler)GpioIsr, &Gpio1);
                        if (Result != XST_SUCCESS) {
                                                return Result;
                        }

                        // Enable the interrupt for the GPIO device.

                        XScuGic_Enable(IntcInstancePtr, INTC_GPIO_INTERRUPT_ID);

                        // Enable the GPIO channel interrupts so that push button can be
                        // detected and enable interrupts for the GPIO device

                        XGpio_InterruptEnable(&Gpio1, BUTTON_INTERRUPT);
                        XGpio_InterruptGlobalEnable(&Gpio1);

                        // Initialize the exception table and register the interrupt
                        // controller handler with the exception table

                        Xil_ExceptionInit();

                        Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
                                                                         (Xil_ExceptionHandler)INTC_HANDLER, IntcInstancePtr);

                        // Enable non-critical exceptions

                        Xil_ExceptionEnable();

                        return XST_SUCCESS;
}






  • En la siguiente imagen se muestra corriendo y funcionando la interfaz. 




No hay comentarios.:

Publicar un comentario