TMS320C6678 多核学习 中断分析 实例+解析
TMS320C6678
了解c66x内核
C66x corepac的位置
内部架构
可以看到66x corepac的
组成模块
-
一.首当其冲就是C66x DSP,这块的知识可以了解一下C66x DSP的结构图
========================= 66x dsp结构图==============================
1).两组寄存器文件组(A和B)
2)…L,.S,.M,.D功能单元
3).两个写入内存的数据通路 ST
4).两个数据地址通路DA
5).两个内存转载数据的数据通路LD
6).寄存器交叉通道1X,2X - 二.L1程序存储器控制器 (提供dsp与l1p内存之间的存储通道)L1 数据存储器控制器 (提供DSP与L1D内存的接口)
- 三.L2 存储器控制器
- 四.DMA (进行内部与外部数据的迁移)
- 五.EMC(外部内存控制器)提供与与其他设备的桥接,CFG(访问所有映射在memory的寄存器不能访问dsp或corepac的内部控制器)和sdma 与其他核之间的数据传输
- 六.XMC (扩展存储器控制器)与MSMC的管理
- 七.BWM (带宽管理)
- 八.中断控制器
- 九.存储器保护架构
- 十.下电控制器
这就是CorePac的组成
中断
事件
在文档中关于中断是这样描述的
大意就是C6678设备上的CPU中断是通过中断控制来控制的也就是所谓的INTC(上面的corepac可以看到)。中断控制器允许将最多128个系统事件编程为12个CPU中断输入(CPUINT4-CPUINT15)、也就是每个核中的中断控制器最对处理128个
系统事件
.
什么是系统事件,就是核上产生的事件和片级产生的事件。这128个系统事件由内部生成的事件(在CorePac内)和芯片级事件组成。
额外的系统事件被路由到每个 C66x CorePac,以提供不需要作为 CPU 中断/异常的芯片级事件作为仿真事件路由到中断控制器。 此外,错误类事件或不经常使用的事件也通过系统事件路由器路由,以卸载 C66x CorePac 中断选择器。 这是通过芯片中断控制器 (CIC) 块实现的。
这里涉及到了CIC(片级中断控制器),看了上面的解释还是有点懵,那就上图
可以看到这里面有四个CIC(0-4),这里主要讨论一下CIC0和1,根据上面的解释最起码明确了一点,一个中断控制器最多接受128个系统事件,那就得知道128个系统事件是谁给他的,这就是CIC的作用。根据图来看一个core会接受 98 + 17 + 5 +8 =128个事件。其中的17和8就是CIC分给他的.
上面解释了core是如何得到这128个系统事件的
接下来分析如何处理这128个系统事件
中断控制器
这128个系统事件最后都是要路由到合适的DSP中断中去的,所以接下来有一个过程就是如和从
事件到中断
记住2个概念
interrupt Selector
,
Event Combiner
Event Combiner
:负责事件打包组合
将4-127的事件通过上图的方法(也可以自己进行配置使用mask和flag)分成组合,然后通过MASK和FLAG生成新的事件0 – 3最终形成128事件
interrupt Selector
:负责路由
DSP有12个可屏蔽的中断,可以将128个事件路由到任意一个中断上。当然为了方便我们肯定是在事件打包之后进行路由
路径映射之后,就得设置中断触发源,可以通过设置中断选择寄存器设置。三个复用寄存器正好可以对应12个中断每个寄存器的(0-6,8-14,16-22,24-30)对应要生成的中断。
中断例程
了解了中断的大致原理,就可以上代码了。
我使用的板子是6678里面有8个核,所以用了一个核间通信(IPC)的例子来分析一下中断。
环境
CCS5.5
6678板卡
seed xds200仿真器
win 7
预期结果
core 0给core 1发送信息16,core 1收到后发送给 core 2 ,依次类推
运行结果
分析
main.c
#include <c6x.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ti/csl/csl_chip.h>
#include <ti/csl/src/intc/csl_intc.h>
#include <ti/csl/csl_cpintcAux.h>
#include "ipc_interrupt.h"
void main()
{
uint32_t i;
// 获取内核号
uint32_t coreID = CSL_chipReadReg (CSL_CHIP_DNUM);
TSCL = 0;
//初始化
intcInit(); //init the intc CSL global data structures, enable global ISR
//注册
registerInterrupt(); //register the Host interrupt with the event
for (i=0; i<1000; i++)
asm (" NOP 5");
//core 0开始发送信息给下一个核
if (0 == coreID)
{
IssueInterruptToNextCore();
}
while(1)
{
asm(" NOP 9");
};
}
ipc_interrupt.c
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ti/csl/csl_chip.h>
#include <ti/csl/src/intc/csl_intc.h>
#include <ti/csl/csl_cpintcAux.h>
#include "ipc_interrupt.h"
CSL_IntcGlobalEnableState state; //使能
CSL_IntcContext context; //上下文
CSL_IntcEventHandlerRecord Record[CSL_INTC_EVENTID_CNT]; //128个事件句柄
CSL_IntcEventHandlerRecord EventRecord; //当前事件句柄
uint32_t coreVector[MAX_CORE_NUM]; //内核表
CSL_IntcObj intcObj[16]; //中断控制器对象
CSL_IntcHandle hintc[16]; //中断控制器句柄
volatile Uint32 interruptNumber=0;
/* IPCGR Info */
int32_t iIPCGRInfo[CORENUM] = {
IPCGR0,
IPCGR1,
IPCGR2,
IPCGR3,
IPCGR4,
IPCGR5,
IPCGR6,
IPCGR7
};
/* IPCAR Info */
int32_t iIPCARInfo[CORENUM] = {
IPCAR0,
IPCAR1,
IPCAR2,
IPCAR3,
IPCAR4,
IPCAR5,
IPCAR6,
IPCAR7
};
interruptCfg intInfo[MAX_SYSTEM_VECTOR] =
{
/* core event vector*/
{ 0, 91, CSL_INTC_VECTID_4, &IPC_ISR},
{ 1, 91, CSL_INTC_VECTID_4, &IPC_ISR},
{ 2, 91, CSL_INTC_VECTID_4, &IPC_ISR},
{ 3, 91, CSL_INTC_VECTID_4, &IPC_ISR},
{ 4, 91, CSL_INTC_VECTID_4, &IPC_ISR},
{ 5, 91, CSL_INTC_VECTID_4, &IPC_ISR},
{ 6, 91, CSL_INTC_VECTID_4, &IPC_ISR},
{ 7, 91, CSL_INTC_VECTID_4, &IPC_ISR},
};
int32_t intcInit()
{
//初始化上下文环境
/* INTC module initialization */
context.eventhandlerRecord = Record;
context.numEvtEntries = CSL_INTC_EVENTID_CNT;
if (CSL_intcInit (&context) != CSL_SOK)
return -1;
/* Enable NMIs */
if (CSL_intcGlobalNmiEnable () != CSL_SOK)
return -1;
/* Enable global interrupts */
if (CSL_intcGlobalEnable (&state) != CSL_SOK)
return -1;
/* INTC has been initialized successfully. */
return 0;
}
//注册中断
int32_t registerInterrupt()
{
uint32_t i;
uint32_t event;
uint32_t vector;
uint32_t core;
uint32_t coreID = CSL_chipReadReg (CSL_CHIP_DNUM);
CSL_IntcEventHandler isr;
for (i=0; i<MAX_CORE_NUM; i++)
{
coreVector[i] = 0;
}
//只有为当前内核,将顶一的core信息与中断源绑定
for (i=0; i<MAX_SYSTEM_VECTOR; i++)
{
core = intInfo[i].core;
if (coreID == core)
{
event = intInfo[i].event;
vector = intInfo[i].vect;
isr = intInfo[i].isr;
if (MAX_CORE_VECTOR <= coreVector[core])
{
printf("Core %d Vector Number Exceed\n");
}
hintc[vector] = CSL_intcOpen (&intcObj[vector], event, (CSL_IntcParam*)&vector , NULL);
if (hintc[vector] == NULL)
{
printf("Error: GEM-INTC Open failed\n");
return -1;
}
/* Register an call-back handler which is invoked when the event occurs. */
EventRecord.handler = isr;
EventRecord.arg = 0;
if (CSL_intcPlugEventHandler(hintc[vector],&EventRecord) != CSL_SOK)
{
printf("Error: GEM-INTC Plug event handler failed\n");
return -1;
}
/* clear the events. */
if (CSL_intcHwControl(hintc[vector],CSL_INTC_CMD_EVTCLEAR, NULL) != CSL_SOK)
{
printf("Error: GEM-INTC CSL_INTC_CMD_EVTCLEAR command failed\n");
return -1;
}
/* Enabling the events. */
if (CSL_intcHwControl(hintc[vector],CSL_INTC_CMD_EVTENABLE, NULL) != CSL_SOK)
{
printf("Error: GEM-INTC CSL_INTC_CMD_EVTENABLE command failed\n");
return -1;
}
coreVector[core]++;
}
}
return 0;
}
// BOOT and CONFIG dsp system modules Definitions
#define CHIP_LEVEL_REG 0x02620000
// Boot cfg registers
#define KICK0 *(unsigned int*)(CHIP_LEVEL_REG + 0x0038)
#define KICK1 *(unsigned int*)(CHIP_LEVEL_REG + 0x003C)
#define KICK0_UNLOCK (0x83E70B13)
#define KICK1_UNLOCK (0x95A4F1E0)
#define KICK_LOCK 0
void IssueInterruptToNextCore()
{
uint32_t CoreNum;
uint32_t iNextCore;
static uint32_t interruptInfo=0;
CoreNum = CSL_chipReadReg (CSL_CHIP_DNUM);
iNextCore = (CoreNum + 1)%8; //
printf("Set interrupt from Core %x to Core %d, cycle = %d\n", CoreNum, iNextCore, TSCL);
interruptInfo +=16;
// Unlock Config
KICK0 = KICK0_UNLOCK;
KICK1 = KICK1_UNLOCK;
//向下一个核发送信息 ipc中断由两个寄存器ipcGR(生成核的中断)和IPCAR(确认)两个寄存器组成
*(volatile uint32_t *) iIPCGRInfo[iNextCore] = interruptInfo;
//使能
*(volatile uint32_t *) iIPCGRInfo[iNextCore] |= 1;
// lock Config
KICK0 = KICK_LOCK;
KICK1 = KICK_LOCK;
printf("Interrupt Info %d\n", interruptInfo);
}
void IPC_ISR()
{
volatile uint32_t read_ipcgr;
uint32_t CoreNum;
uint32_t iPrevCore;
CoreNum = CSL_chipReadReg (CSL_CHIP_DNUM);;
iPrevCore = (CoreNum - 1)%8;
//当前核接收到的信息
read_ipcgr = *(volatile Uint32 *) iIPCGRInfo[CoreNum];
//清除SRCS位
*(volatile uint32_t *) iIPCARInfo[CoreNum] = read_ipcgr; //clear the related source info
printf("Receive interrupt from Core %d with info 0x%x, cycle = %d\n", iPrevCore, read_ipcgr, TSCL);
interruptNumber++;
if(CoreNum!=0)//
{
IssueInterruptToNextCore();
}
else
{
printf("IPC test passed!\n");
}
}
如果各位需要源码的话可以私聊我…