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
相关产品推荐
相关产品推荐

