4、BSP中中断控制器的初始化:中断控制器寄存器映射、初始化序列与使能操作

中断控制器是VxWorks BSP中连接CPU内核与外部中断源的桥梁。在PowerPC架构中,通常使用OpenPIC(Open Programmable Interrupt Controller)或MPIC(Multi-Processor Interrupt Controller);在ARM Cortex-A系列中,则使用GIC(Generic Interrupt Controller)v2/v3。本章以MPIC为例,详细阐述BSP中中断控制器的寄存器映射、初始化序列与使能操作。

4.1 中断控制器寄存器映射

中断控制器的寄存器映射是BSP初始化的第一步。BSP需要将中断控制器的物理地址空间映射到VxWorks的虚拟地址空间,以便后续通过内存访问指令操作寄存器。

寄存器组 偏移地址 位宽 功能描述
全局配置寄存器 0x0000 – 0x0FFF 32-bit 中断控制器全局使能、时序配置、处理器掩码
中断源配置寄存器 0x1000 – 0x1FFF 32-bit 每个中断源的优先级、向量号、触发方式
中断分发寄存器 0x2000 – 0x2FFF 32-bit 中断目标CPU分配、中断屏蔽
中断确认/结束寄存器 0x3000 – 0x3FFF 32-bit 中断响应(IACK)、中断结束(EOI)
定时器寄存器 0x4000 – 0x4FFF 32-bit 内部定时器计数、比较、状态
映射要点: BSP中通常使用sysPhysMemDesc[]数组或mmuMap接口完成物理地址到虚拟地址的映射。映射属性必须设置为非缓存(non-cacheable),以确保寄存器读写操作的顺序性和原子性。
MPIC中断控制器寄存器映射结构 CPU Core 全局配置 中断源配置 中断分发 IACK/EOI 外部设备1 外部设备2 外部设备N 图例 CPU MPIC寄存器 外部设备

4.2 初始化序列

中断控制器的初始化序列必须严格遵循硬件手册规定的时序。典型的MPIC初始化序列包含以下步骤:

  1. 全局复位与配置: 写入全局配置寄存器(GCR),设置处理器模式(混合/直通)、时序参数,并清除所有挂起中断。
  2. 处理器初始化寄存器配置: 为每个CPU核配置处理器初始化寄存器(PIR),设置当前CPU的中断向量基址和任务优先级阈值。
  3. 中断源配置: 遍历所有外部中断源,写入中断源配置寄存器(ISR),设置向量号、优先级(0-15)、触发方式(边沿/电平)和极性。
  4. 中断分发配置: 配置中断分发寄存器(IDR),将每个中断源绑定到目标CPU,并设置分发模式(轮询/固定)。
  5. 全局使能: 设置全局使能位(GCR[GIE]),允许中断控制器向CPU转发中断信号。
初始化顺序依赖: 必须在所有中断源配置完成之后,才能设置全局使能位。如果在配置过程中提前使能,可能导致未初始化的中断源产生虚假中断,造成系统异常。
MPIC初始化序列流程图 1. 全局复位与配置 2. 处理器初始化 3. 中断源配置 4. 中断分发配置 5. 全局使能 注意:步骤2-4可并行 但步骤5必须在最后

4.3 中断使能操作

中断使能操作分为三个层级:中断控制器全局使能、中断源使能、CPU内核中断使能。BSP必须协调这三个层级的使能状态,才能确保中断正常到达CPU。

4.3.1 中断源使能

每个中断源在MPIC中对应一个中断源配置寄存器(ISR)和一个中断掩码寄存器(IMR)。使能操作通过清除IMR中的对应掩码位实现。

/* 中断源使能示例代码 */
STATUS mpicIrqEnable (UINT32 vector)
{
    UINT32 regOffset;
    UINT32 imrValue;

    /* 计算中断源对应的IMR寄存器偏移 */
    regOffset = MPIC_IMR_BASE + (vector / 32) * 4;

    /* 读取当前掩码值 */
    imrValue = sysInReg (pMpicBase + regOffset);

    /* 清除对应位的掩码(使能中断) */
    imrValue &= ~(1 << (vector % 32));

    /* 写回寄存器 */
    sysOutReg (pMpicBase + regOffset, imrValue);

    return OK;
}

4.3.2 CPU内核中断使能

在PowerPC架构中,CPU内核中断使能通过操作MSR(Machine State Register)的EE位实现。VxWorks提供intLock/intUnlock宏来管理CPU级中断使能。

层级 控制方式 作用范围 典型寄存器/宏
中断控制器全局 GCR[GIE]位 所有中断源 MPIC_GCR
中断源级 IMR掩码位 单个中断源 MPIC_IMR
CPU内核级 MSR[EE]位 当前CPU所有中断 intLock/intUnlock
常见陷阱: 在BSP初始化阶段,CPU内核级中断默认是关闭的(MSR[EE]=0)。如果仅配置了中断控制器和中断源使能,但未在启动CPU时设置MSR[EE]位,中断将永远不会被CPU响应。BSP的sysHwInit2函数中必须显式调用intUnlock来打开CPU级中断。

4.4 中断向量表与中断服务例程注册

中断使能的最后一步是将中断向量与中断服务例程(ISR)关联。VxWorks使用intConnect函数将中断向量号与ISR绑定,并设置中断栈。

/* 中断服务例程注册示例 */
VOID myIsr (void)
{
    /* 中断处理逻辑 */
    /* ... */
}

STATUS sysIntInit (void)
{
    /* 注册中断服务例程 */
    if (intConnect (INUM_TO_IVEC (INT_VEC_TIMER), myIsr, 0) != OK)
    {
        return ERROR;
    }

    /* 使能中断源 */
    mpicIrqEnable (INT_VEC_TIMER);

    return OK;
}
中断使能三层级协作关系 CPU内核级 MSR[EE] = 1 中断控制器级 GCR[GIE] = 1 中断源级 IMR[bit] = 0 & & 中断到达CPU = 三级使能的逻辑与

4.5 中断控制器初始化代码框架

以下是一个完整的MPIC初始化代码框架,展示了寄存器映射、初始化序列和使能操作的整合:

/* MPIC初始化完整框架 */
LOCAL UINT32 *pMpicBase = NULL;

STATUS sysMpicInit (void)
{
    /* 1. 寄存器映射 */
    pMpicBase = (UINT32 *)sysMmuMap (MPIC_PHYS_BASE, MPIC_SIZE,
                                     MMU_ATTR_NON_CACHE);
    if (pMpicBase == NULL)
    {
        return ERROR;
    }

    /* 2. 全局复位 */
    sysOutReg (pMpicBase + MPIC_GCR, MPIC_GCR_RESET);
    while (sysInReg (pMpicBase + MPIC_GCR) & MPIC_GCR_RESET)
    {
        /* 等待复位完成 */
    }

    /* 3. 配置全局模式 */
    sysOutReg (pMpicBase + MPIC_GCR, MPIC_GCR_MIXED_MODE);

    /* 4. 配置处理器初始化寄存器 */
    sysOutReg (pMpicBase + MPIC_PIR(cpuIndex),
               (VEC_BASE << 16) | TASK_PRIORITY_DEFAULT);

    /* 5. 配置所有中断源 */
    for (int i = 0; i < NUM_INT_SOURCES; i++)
    {
        sysOutReg (pMpicBase + MPIC_ISR(i),
                   (intSourceCfg[i].vector << 16) |
                   (intSourceCfg[i].priority << 8) |
                   intSourceCfg[i].trigger);
    }

    /* 6. 配置中断分发 */
    for (int i = 0; i < NUM_INT_SOURCES; i++)
    {
        sysOutReg (pMpicBase + MPIC_IDR(i), intSourceCfg[i].targetCpu);
    }

    /* 7. 全局使能 */
    sysOutReg (pMpicBase + MPIC_GCR,
               sysInReg (pMpicBase + MPIC_GCR) | MPIC_GCR_GIE);

    return OK;
}
关键设计原则: 中断控制器的初始化必须在系统启动早期完成,通常在sysHwInit函数中调用。所有中断源配置应使用静态表格(intSourceCfg[])管理,便于移植和调试。使能操作应遵循“先配置、后使能”的原则,避免虚假中断。