You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Zynq Ultrascale+平台Core0触发Core1软件中断失败排查

Zynq Ultrascale+跨核软件中断无法送达问题解决

在Zynq Ultrascale+平台上,尝试从core0向core1触发软件生成中断,但中断始终无法送达core1。测试过多种方法(包括xscugic驱动示例),仅能实现core0自触发,无法完成跨核触发。

当前代码实现

GIC初始化通用函数

int ScuGicInit(XScuGic *IntcInstancePtr, u16 DeviceId) {
    XScuGic_Config *IntcConfig;
    int status;

    // 获取GIC配置
    IntcConfig = XScuGic_LookupConfig(XPAR_SCUGIC_SINGLE_DEVICE_ID);

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

    // 初始化GIC
    status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,
                                   IntcConfig->CpuBaseAddress);
    if (status != XST_SUCCESS) {
        return status;
    }

    // 向异常框架注册GIC
    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,
                                 (Xil_ExceptionHandler)XScuGic_InterruptHandler,
                                 IntcInstancePtr);

    // 使能ARM端中断
    Xil_ExceptionEnable();

    return XST_SUCCESS;
}

Core1中断处理与Core0触发代码

#define INTC_DEVICE_ID      XPAR_SCUGIC_0_DEVICE_ID
#define INTC_DEVICE_INT_ID  0x0E

void core1(void){
     int Status;
    XScuGic IntcInstance;

    // 初始化GIC
    Status = ScuGicInit(&IntcInstance, XPAR_SCUGIC_SINGLE_DEVICE_ID);
    if (Status != XST_SUCCESS) {
        // 错误处理
        //return XST_FAILURE;
    }

    // 关联Core1的SGI中断处理函数
    Status = XScuGic_Connect(&IntcInstance, INTC_DEVICE_INT_ID,
                             (Xil_InterruptHandler)DeviceDriverHandler, &IntcInstance);
    if (Status != XST_SUCCESS) {
        // 错误处理
        //return XST_FAILURE;
    }

    // 使能SGI中断
    XScuGic_Enable(&IntcInstance, INTC_DEVICE_INT_ID);

    // Core1主循环
    while (1) {
        // Core1任务或休眠
    }

    while (1);
}


int main() {
    int Status;
    XScuGic IntcInstance;

    // 初始化GIC
    Status = ScuGicInit(&IntcInstance, XPAR_SCUGIC_SINGLE_DEVICE_ID);
    if (Status != XST_SUCCESS) {
        // 错误处理
        return XST_FAILURE;
    }

    set_start_addr();
    release_acpus();

    sleep(1);

    // Core0主循环
    while (1) {
        // 向Core1触发SGI中断
        // 假设Core1已配置处理SGI ID 0
        XScuGic_SoftwareIntr(&IntcInstance, INTC_DEVICE_INT_ID, XSCUGIC_SPI_CPU1_MASK);
        sleep(1);

        // 添加延时或触发条件,避免持续触发
    }

    return XST_SUCCESS;
}

注:set_start_addr()和release_acpus()已验证可正常工作,main函数运行在core0,core1函数运行在core1。

问题根源与解决方案

问题核心在于EL3模式下的SCR_EL3寄存器配置:运行裸机(EL3)的所有CPU都需要设置IRQ位,才能正常接收IRQ中断。

在Core0中添加如下汇编代码初始化SCR_EL3寄存器后,core0即可成功向core1触发中断:

mov      w1, #0                 //; 寄存器初始值未知
    orr      w1, w1, #(1 << 11)     //; 设置ST位(安全EL1可访问CNTPS_TVAL_EL1、CNTPS_CTL_EL1和CNTPS_CVAL_EL1)
    orr      w1, w1, #(1 << 10)     //; 设置RW位(安全世界中EL1为AArch64模式)
    orr      w1, w1, #(1 << 3)      //; 设置EA位(SError路由到EL3)
    orr      w1, w1, #(1 << 2)      //; 设置FIQ位(FIQ路由到EL3)
    orr      w1, w1, #(1 << 1)      //; 设置IRQ位(IRQ路由到EL3)
    msr      SCR_EL3, x1

其中**IRQ位(寄存器第1位)**是关键,必须为core1配置该位,才能确保跨核中断正常送达。

内容的提问来源于stack exchange,提问作者CynFX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 17:01:21