Jump to content

    
ovn

Как запустить несколько програмных прерывания на Zynq?

Recommended Posts

Как запустить обработку одного програмного прерывания(SGI), понятно, а как нескольких на одном ядре, всего их 16, как установить приоритет прерываний?

простой код для одного програмного прерывания  

#include <stdio.h>
#include <stdlib.h>
#include "xil_io.h"
#include "xil_exception.h"
#include "xparameters.h"
#include "xil_cache.h"
#include "xil_printf.h"
#include "xil_types.h"
#include "xscugic.h"

#define INTC_DEVICE_ID        XPAR_SCUGIC_0_DEVICE_ID
#define INTC_DEVICE_INT_ID    0x0E


void DeviceDriverHandler(void *CallbackRef);

XScuGic InterruptController;          /* Instance of the Interrupt Controller Экземпляр контроллера прерываний */
static XScuGic_Config *GicConfig;    /* The configuration parameters of the

volatile static int InterruptProcessed = FALSE;

int main(void)
{
    //int Status;

    xil_printf("GIC Example Test\r\n");

    GicConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);


        XScuGic_CfgInitialize(&InterruptController, GicConfig,
                        GicConfig->CpuBaseAddress);


    XScuGic_SelfTest(&InterruptController);


    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
                (Xil_ExceptionHandler) XScuGic_InterruptHandler,
                &InterruptController);

    Xil_ExceptionEnable();


    XScuGic_Connect(&InterruptController, INTC_DEVICE_INT_ID,
                   (Xil_ExceptionHandler)DeviceDriverHandler,
                   (void *)&InterruptController);

    XScuGic_Enable(&InterruptController, INTC_DEVICE_INT_ID);


    XScuGic_SoftwareIntr(&InterruptController, //вызываем прерывание
                            INTC_DEVICE_INT_ID,
                            XSCUGIC_SPI_CPU0_MASK);

    while (1) {
        //    xil_printf("cycle \r\n");
        }


    xil_printf("Successfully ran GIC Example Test\r\n");
    return XST_SUCCESS;
}

void DeviceDriverHandler(void *CallbackRef) // обработчик прерывания
{
    xil_printf("interrupt \r\n");
    InterruptProcessed = TRUE;
}
 

 

Edited by ovn

Share this post


Link to post
Share on other sites
Guest vitzap

Когда к ядру прицеплено несколько прерываний, в файлах констант появляется несколько прерываний с индексами 0,1,2,3...

Инициализировать также - например,

Status = XScuGic_Connect(&intc, XPS_FPGA0_INT_ID,
                    (Xil_InterruptHandler)IntHandler0, NULL);

Status = XScuGic_Connect(&intc, XPS_FPGA1_INT_ID,
                    (Xil_InterruptHandler)IntHandler1, NULL);

XScuGic_Enable(&intc, XPS_FPGA0_INT_ID);
XScuGic_Enable(&intc, XPS_FPGA1_INT_ID);

 

Насчет приоритета - там вроде бы единый обработчик на все эти прерывания, и, в зависимости от индекса сработавшего прерывания, вызывается тот или иной пользовательский обработчик. Получается, прерывание с индексом 0 имеет наивысший приоритет. Это не точно - надо в исходниках покопаться, освежить в памяти.

 

 

 

Share this post


Link to post
Share on other sites

Пробовал, нулевое 0x0E прерывание обрабатывается, а 0x1E нет, в чём моя ошибка?

 

#include <stdio.h>
#include <stdlib.h>
#include "xil_io.h"
#include "xil_exception.h"
#include "xparameters.h"
#include "xil_cache.h"
#include "xil_printf.h"
#include "xil_types.h"
#include "xscugic.h"

#define INTC_DEVICE_ID        XPAR_SCUGIC_0_DEVICE_ID
#define INTC_DEVICE_INT_ID    0x0E
#define INTC_DEVICE_INT_ID1    0x1E


void DeviceDriverHandler(void *CallbackRef);
void DeviceDriverHandler1(void *CallbackRef);

 

XScuGic InterruptController;          /* Instance of the Interrupt Controller Экземпляр контроллера прерываний */
static XScuGic_Config *GicConfig;    /* The configuration parameters of the */

volatile static int InterruptProcessed = FALSE;

 

int main(void)
{
    //int Status;

    xil_printf("GIC Example Test\r\n");

    GicConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);


        XScuGic_CfgInitialize(&InterruptController, GicConfig,
                        GicConfig->CpuBaseAddress);


    XScuGic_SelfTest(&InterruptController);


    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
                (Xil_ExceptionHandler) XScuGic_InterruptHandler,
                &InterruptController);

    Xil_ExceptionEnable();


    XScuGic_Connect(&InterruptController, INTC_DEVICE_INT_ID,
                   (Xil_ExceptionHandler)DeviceDriverHandler,
                   (void *)&InterruptController);

    XScuGic_Enable(&InterruptController, INTC_DEVICE_INT_ID);


        XScuGic_Connect(&InterruptController, INTC_DEVICE_INT_ID1,
                   (Xil_ExceptionHandler)DeviceDriverHandler1,
                   (void *)&InterruptController);

    XScuGic_Enable(&InterruptController, INTC_DEVICE_INT_ID1);


    XScuGic_SoftwareIntr(&InterruptController, //прерывание
                            INTC_DEVICE_INT_ID,
                            XSCUGIC_SPI_CPU0_MASK);

         XScuGic_SoftwareIntr(&InterruptController, //прерывание1
                            INTC_DEVICE_INT_ID1,
                            XSCUGIC_SPI_CPU0_MASK);

    while (1) {
        //    xil_printf("cycle \r\n");
        }


    xil_printf("Successfully ran GIC Example Test\r\n");
    return XST_SUCCESS;
}

void DeviceDriverHandler(void *CallbackRef)
{
    xil_printf("interrupt \r\n");
    InterruptProcessed = TRUE;
}

void DeviceDriverHandler1(void *CallbackRef)
{
    xil_printf("interrupt1 \r\n");
    InterruptProcessed = TRUE;
}

Edited by ovn

Share this post


Link to post
Share on other sites

Нашёл ответ, заработало, помогли на форуме Xilinx

надо определять приоритет прерываний 

#define INTC_DEVICE_INT_ID            (0x00)    // SGI 0
#define SGI0_INTR_PRI                (0x90)    // Lowest Priority
#define SGI0_INTR_TRIG                (0x03)    // Rising-edge Sensitive


#define INTC_DEVICE_INT_ID1            (0x01)    // SGI 1
#define SGI1_INTR_PRI                (0x88)
#define SGI1_INTR_TRIG                (0x03)     // Rising-edge Sensitive

и т. д.

после Xil_ExceptionEnable();

    /* Set priority and trigger type for SGI 1 */
    XScuGic_SetPriorityTriggerType(&InterruptController, INTC_DEVICE_INT_ID, SGI0_INTR_PRI, SGI0_INTR_TRIG);

    /* Set priority and trigger type for SGI 2 */
    XScuGic_SetPriorityTriggerType(&InterruptController, INTC_DEVICE_INT_ID1, SGI1_INTR_PRI, SGI1_INTR_TRIG);

Share this post


Link to post
Share on other sites
On 1/20/2021 at 4:30 PM, ovn said:

Нашёл ответ, заработало, помогли на форуме Xilinx

Что-то не взлетело у меня вообще никак. Можно ссылку на форум Xilinx, где помогли?

Сигналы заведены на IRQ_F2P порт PS. Скопипастил, подставил в код ID 61,62

В анализаторе сигналы вижу, а в обработчики не попадаю. ЧЯДНТ?

Share this post


Link to post
Share on other sites
12.02.2021 в 17:51, v-oz сказал:

Что-то не взлетело у меня вообще никак. Можно ссылку на форум Xilinx, где помогли?

Сигналы заведены на IRQ_F2P порт PS. Скопипастил, подставил в код ID 61,62

В анализаторе сигналы вижу, а в обработчики не попадаю. ЧЯДНТ?


Код с софтовыми привёл выше, с аппаратными так же. Нужно разобраться с GICом. 

Edited by ovn

Share this post


Link to post
Share on other sites

Спасибо, что напомнили. Прошу прощения,  что не закрыл вопрос сам. 

У меня после инициализации прерывания стояла функция настройки echo- сервера .

Похоже,  в ней где-то сидит настройка прерывания сетевого порта и она гасила мои настройки. 

На чистом вашем примере все заработало.

Спасибо большое

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.