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),以确保寄存器读写操作的顺序性和原子性。
4.2 初始化序列
中断控制器的初始化序列必须严格遵循硬件手册规定的时序。典型的MPIC初始化序列包含以下步骤:
- 全局复位与配置: 写入全局配置寄存器(GCR),设置处理器模式(混合/直通)、时序参数,并清除所有挂起中断。
- 处理器初始化寄存器配置: 为每个CPU核配置处理器初始化寄存器(PIR),设置当前CPU的中断向量基址和任务优先级阈值。
- 中断源配置: 遍历所有外部中断源,写入中断源配置寄存器(ISR),设置向量号、优先级(0-15)、触发方式(边沿/电平)和极性。
- 中断分发配置: 配置中断分发寄存器(IDR),将每个中断源绑定到目标CPU,并设置分发模式(轮询/固定)。
- 全局使能: 设置全局使能位(GCR[GIE]),允许中断控制器向CPU转发中断信号。
初始化顺序依赖: 必须在所有中断源配置完成之后,才能设置全局使能位。如果在配置过程中提前使能,可能导致未初始化的中断源产生虚假中断,造成系统异常。
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;
}
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[])管理,便于移植和调试。使能操作应遵循“先配置、后使能”的原则,避免虚假中断。