TMS320C6678 多核学习 中断分析 实例+解析

TMS320C6678 多核学习 中断分析 实例+解析

  • TMS320C6678
    • 了解c66x内核
      • C66x corepac的位置
      • 内部架构
    • 中断
      • 事件
      • 中断控制器
    • 中断例程
      • 环境
      • 预期结果
      • 运行结果
      • 分析

TMS320C6678

了解c66x内核

C66x corepac的位置

在这里插入图片描述

内部架构

在这里插入图片描述
可以看到66x corepac的组成模块

  • 一.首当其冲就是C66x DSP,这块的知识可以了解一下C66x DSP的结构图
    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 SelectorEvent 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");
    }
}




如果各位需要源码的话可以私聊我…

热门文章

暂无图片
编程学习 ·

Java输出数组的内容

Java输出数组的内容_一万个小时-CSDN博客_java打印数组内容1. 输出内容最常见的方式// List<String>类型的列表List<String> list new ArrayList<String>();list.add("First");list.add("Second");list.add("Third");list.ad…
暂无图片
编程学习 ·

母螳螂的“魅惑之术”

在它们对大蝗虫发起进攻的时候&#xff0c;我认认真真地观察了一次&#xff0c;因为它们突然像触电一样浑身痉挛起来&#xff0c;警觉地面对限前这个大家伙&#xff0c;然后放下自己优雅的身段和祈祷的双手&#xff0c;摆出了一个可怕的姿势。我被眼前的一幕吓到了&#xff0c;…
暂无图片
编程学习 ·

疯狂填词 mad_libs 第9章9.9.2

#win7 python3.7.0 import os,reos.chdir(d:\documents\program_language) file1open(.\疯狂填词_d9z9d2_r.txt) file2open(.\疯狂填词_d9z9d2_w.txt,w) words[ADJECTIVE,NOUN,VERB,NOUN] str1file1.read()#方法1 for word in words :word_replaceinput(fEnter a {word} :)str1…
暂无图片
编程学习 ·

HBASE 高可用

为了保证HBASE是高可用的,所依赖的HDFS和zookeeper也要是高可用的. 通过参数hbase.rootdir指定了连接到Hadoop的地址,mycluster表示为Hadoop的集群. HBASE本身的高可用很简单,只要在一个健康的集群其他节点通过命令 hbase-daemon.sh start master启动一个Hmaster进程,这个Hmast…
暂无图片
编程学习 ·

js事件操作语法

一、事件的绑定语法 语法形式1 事件监听 标签对象.addEventListener(click,function(){}); 语法形式2 on语法绑定 标签对象.onclick function(){} on语法是通过 等于赋值绑定的事件处理函数 , 等于赋值本质上执行的是覆盖赋值,后赋值的数据会覆盖之前存储的数据,也就是on…
暂无图片
编程学习 ·

Photoshop插件--晕影动态--选区--脚本开发--PS插件

文章目录1.插件界面2.关键代码2.1 选区2.2 动态晕影3.作者寄语PS是一款栅格图像编辑软件&#xff0c;具有许多强大的功能&#xff0c;本文演示如何通过脚本实现晕影动态和选区相关功能&#xff0c;展示从互联网收集而来的一个小插件&#xff0c;供大家学习交流&#xff0c;请勿…
暂无图片
编程学习 ·

vs LNK1104 无法打开文件“xxx.obj”

写在前面&#xff1a; 向大家推荐两本新书&#xff0c;《深度学习计算机视觉实战》和《学习OpenCV4&#xff1a;基于Python的算法实战》。 《深度学习计算机视觉实战》讲了计算机视觉理论基础&#xff0c;讲了案例项目&#xff0c;讲了模型部署&#xff0c;这些项目学会之后可以…
暂无图片
编程学习 ·

工业元宇宙的定义与实施路线图

工业元宇宙的定义与实施路线图 李正海 1 工业元宇宙 给大家做一个关于工业元宇宙的定义。对于工业&#xff0c;从设计的角度来讲&#xff0c;现在的设计人员已经做到了普遍的三维设计&#xff0c;但是进入元宇宙时代&#xff0c;就不仅仅只是三维设计了&#xff0c;我们的目…
暂无图片
编程学习 ·

【leectode 2022.1.15】完成一半题目

有 N 位扣友参加了微软与力扣举办了「以扣会友」线下活动。主办方提供了 2*N 道题目&#xff0c;整型数组 questions 中每个数字对应了每道题目所涉及的知识点类型。 若每位扣友选择不同的一题&#xff0c;请返回被选的 N 道题目至少包含多少种知识点类型。 示例 1&#xff1a…
暂无图片
编程学习 ·

js 面试题总结

一、js原型与原型链 1. prototype 每个函数都有一个prototype属性&#xff0c;被称为显示原型 2._ _proto_ _ 每个实例对象都会有_ _proto_ _属性,其被称为隐式原型 每一个实例对象的隐式原型_ _proto_ _属性指向自身构造函数的显式原型prototype 3. constructor 每个prot…
暂无图片
编程学习 ·

java练习代码

打印自定义行数的空心菱形练习代码如下 import java.util.Scanner; public class daYinLengXing{public static void main(String[] args) {System.out.println("请输入行数");Scanner myScanner new Scanner(System.in);int g myScanner.nextInt();int num g%2;//…
暂无图片
编程学习 ·

RocketMQ-什么是死信队列?怎么解决

目录 什么是死信队列 死信队列的特征 死信消息的处理 什么是死信队列 当一条消息初次消费失败&#xff0c;消息队列会自动进行消费重试&#xff1b;达到最大重试次数后&#xff0c;若消费依然失败&#xff0c;则表明消费者在正常情况下无法正确地消费该消息&#xff0c;此时…
暂无图片
编程学习 ·

项目 cg day04

第4章 lua、Canal实现广告缓存 学习目标 Lua介绍 Lua语法 输出、变量定义、数据类型、流程控制(if..)、循环操作、函数、表(数组)、模块OpenResty介绍(理解配置) 封装了Nginx&#xff0c;并且提供了Lua扩展&#xff0c;大大提升了Nginx对并发处理的能&#xff0c;10K-1000K Lu…
暂无图片
编程学习 ·

输出三角形

#include <stdio.h> int main() { int i,j; for(i0;i<5;i) { for(j0;j<i;j) { printf("*"); } printf("\n"); } }
暂无图片
编程学习 ·

stm32的BOOTLOADER学习1

序言 最近计划学习stm32的BOOTLOADER学习,把学习过程记录下来 因为现在网上STM32C8T6还是比较贵的,根据我的需求flash空间小一些也可以,所以我决定使用stm32c6t6.这个芯片的空间是32kb的。 #熟悉芯片内部的空间地址 1、flash ROM&#xff1a; 大小32KB&#xff0c;范围&#xf…
暂无图片
编程学习 ·

通过awk和shell来限制IP多次访问之学不会你打死我

学不会你打死我 今天我们用shell脚本&#xff0c;awk工具来分析日志来判断是否存在扫描器来进行破解网站密码——限制访问次数过多的IP地址&#xff0c;通过Iptables来进行限制。代码在末尾 首先我们要先查看日志的格式&#xff0c;分析出我们需要筛选的内容&#xff0c;日志…
暂无图片
编程学习 ·

Python - 如何像程序员一样思考

在为计算机编写程序之前&#xff0c;您必须学会如何像程序员一样思考。学习像程序员一样思考对任何学生都很有价值。以下步骤可帮助任何人学习编码并了解计算机科学的价值——即使他们不打算成为计算机科学家。 顾名思义&#xff0c;Python经常被想要学习编程的人用作第一语言…
暂无图片
编程学习 ·

蓝桥杯python-数字三角形

问题描述 虽然我前后用了三种做法&#xff0c;但是我发现只有“优化思路_1”可以通过蓝桥杯官网中的测评&#xff0c;但是如果用c/c的话&#xff0c;每个都通得过&#xff0c;足以可见python的效率之低&#xff08;但耐不住人家好用啊&#xff08;哭笑&#xff09;&#xff09…