刚拿到C6678开发板时,面对厚达千页的技术手册和复杂的中断系统,很多开发者都会感到无从下手。本文将带你绕过繁琐的理论,直接通过TI提供的CSL(Chip Support Library)库快速实现中断配置。我们将以HyperLink通信中断为例,用5个步骤完成从事件映射到ISR绑定的全过程,并提供可直接移植的代码模板。
C6678采用双级中断控制器架构,这是理解所有配置的基础。第一级是芯片级中断控制器(CIC),负责将片上外设的中断请求转换为系统事件;第二级是每个CorePac内部的INTC,负责将事件映射到CPU可识别的中断向量。
关键概念速览:
特别注意:C6678的Host Interrupt与Channel存在固定映射关系,这在配置时容易出错。例如Host Interrupt 3固定对应Channel 3,这个映射关系不可更改。
开始前需要确保:
ti/pdk_C6678_x_x_x/packages)c复制#include <ti/csl/csl_intc.h>
#include <ti/csl/csl_cpIntcAux.h>
#include <ti/csl/cslr_cp_intc.h>
基础初始化代码框架:
c复制CSL_IntcContext intcContext;
CSL_IntcGlobalEnableState state;
// 初始化INTC
intcContext.numEvtEntries = 1;
intcContext.eventhandlerRecord = NULL;
CSL_intcInit(&intcContext);
// 使能全局中断
CSL_intcGlobalNmiEnable();
CSL_intcGlobalEnable(&state);
以配置HyperLink中断(System Interrupt 111)为例:
c复制CSL_CPINTC_Handle cpIntcHandle = CSL_CPINTC_open(0);
// 步骤1:禁用所有Host中断
CSL_CPINTC_disableAllHostInterrupt(cpIntcHandle);
// 步骤2:设置嵌套模式(C6678不支持嵌套)
CSL_CPINTC_setNestingMode(cpIntcHandle, CPINTC_NO_NESTING);
// 步骤3:映射System Interrupt到Channel
// 注意:Host Interrupt号=Channel号
CSL_CPINTC_mapSystemIntrToChannel(cpIntcHandle,
CSL_INTC0_VUSR_INT_O, // HyperLink系统中断号
11); // Channel号
// 步骤4:使能系统中断
CSL_CPINTC_enableSysInterrupt(cpIntcHandle, CSL_INTC0_VUSR_INT_O);
// 步骤5:使能Host中断
CSL_CPINTC_enableHostInterrupt(cpIntcHandle, 11);
常见坑点:
CSL_CPINTC_open()会导致后续API失败将CIC输出的Host Interrupt连接到CPU中断线:
c复制#define HYPERLINK_EVENT_ID 21 // HyperLink对应的事件ID
#define CPU_INT_NUM 4 // 使用CPU中断4
CSL_IntcObj intcObj;
CSL_IntcHandle intcHandle;
CSL_IntcEventHandlerRecord eventRecord;
// 步骤1:打开事件通道
CSL_IntcParam vectId = CPU_INT_NUM;
intcHandle = CSL_intcOpen(&intcObj,
HYPERLINK_EVENT_ID, // 事件ID
&vectId, // 目标CPU中断号
NULL);
// 步骤2:绑定ISR函数
eventRecord.handler = &hyperLinkIsr;
eventRecord.arg = (void*)HYPERLINK_EVENT_ID;
CSL_intcPlugEventHandler(intcHandle, &eventRecord);
// 步骤3:清除可能存在的pending状态
CSL_intcHwControl(intcHandle, CSL_INTC_CMD_EVTCLEAR, NULL);
// 步骤4:使能事件
CSL_intcHwControl(intcHandle, CSL_INTC_CMD_EVTENABLE, NULL);
ISR函数模板:
c复制void hyperLinkIsr(CSL_IntcHandle hIntc)
{
// 1. 禁用Host中断防止重复触发
CSL_CPINTC_disableHostInterrupt(cpIntcHandle, 11);
// 2. 清除CIC中的中断状态
CSL_CPINTC_clearSysInterrupt(cpIntcHandle, CSL_INTC0_VUSR_INT_O);
// 3. 实际中断处理代码
// ...处理HyperLink中断...
// 4. 重新使能Host中断
CSL_CPINTC_enableHostInterrupt(cpIntcHandle, 11);
}
整合后的完整配置代码:
c复制#include <stdio.h>
#include <ti/csl/csl.h>
#include <ti/csl/csl_intc.h>
#include <ti/csl/csl_cpIntcAux.h>
// 全局变量
CSL_CPINTC_Handle gCpIntcHandle;
void hyperLinkIsr(CSL_IntcHandle hIntc) {
CSL_CPINTC_disableHostInterrupt(gCpIntcHandle, 11);
CSL_CPINTC_clearSysInterrupt(gCpIntcHandle, CSL_INTC0_VUSR_INT_O);
// 实际中断处理逻辑
printf("HyperLink interrupt occurred!\n");
CSL_CPINTC_enableHostInterrupt(gCpIntcHandle, 11);
}
void initInterruptSystem(void) {
// INTC初始化
CSL_IntcContext intcContext;
CSL_IntcGlobalEnableState state;
intcContext.numEvtEntries = 1;
intcContext.eventhandlerRecord = NULL;
CSL_intcInit(&intcContext);
CSL_intcGlobalNmiEnable();
CSL_intcGlobalEnable(&state);
// CIC配置
gCpIntcHandle = CSL_CPINTC_open(0);
CSL_CPINTC_disableAllHostInterrupt(gCpIntcHandle);
CSL_CPINTC_setNestingMode(gCpIntcHandle, CPINTC_NO_NESTING);
CSL_CPINTC_mapSystemIntrToChannel(gCpIntcHandle, CSL_INTC0_VUSR_INT_O, 11);
CSL_CPINTC_enableSysInterrupt(gCpIntcHandle, CSL_INTC0_VUSR_INT_O);
CSL_CPINTC_enableHostInterrupt(gCpIntcHandle, 11);
// CorePac INTC配置
CSL_IntcObj intcObj;
CSL_IntcHandle intcHandle;
CSL_IntcEventHandlerRecord eventRecord;
CSL_IntcParam vectId = 4; // CPU中断4
intcHandle = CSL_intcOpen(&intcObj, 21, &vectId, NULL);
eventRecord.handler = &hyperLinkIsr;
eventRecord.arg = (void*)21;
CSL_intcPlugEventHandler(intcHandle, &eventRecord);
CSL_intcHwControl(intcHandle, CSL_INTC_CMD_EVTCLEAR, NULL);
CSL_intcHwControl(intcHandle, CSL_INTC_CMD_EVTENABLE, NULL);
}
int main(void) {
initInterruptSystem();
while(1);
return 0;
}
调试建议:
CSL_CPINTC_getPendingHostInterrupt()检查Host中断状态CSL_Status返回值对于需要更高效率的场景,可以考虑:
多事件合并技术:
c复制// 将多个System Interrupt映射到同一Channel
CSL_CPINTC_mapSystemIntrToChannel(hnd, 111, 10);
CSL_CPINTC_mapSystemIntrToChannel(hnd, 112, 10);
中断延迟优化技巧:
CSL_CPINTC_enableSysInterrupt()的时机控制错误处理最佳实践:
c复制CSL_Status status = CSL_intcOpen(...);
if(status != CSL_SOK) {
printf("INTC open failed with code %d\n", status);
while(1);
}
实际项目中,我们通常会封装这些操作为更易用的API。例如创建一个interruptManager模块,提供registerInterrupt()和unregisterInterrupt()等接口,隐藏底层细节。