DSP 中断用法示例

转:注:内容为搬运
原网址
:http://processors.wiki.ti.com/index.php/Configuring_Interrupts_on_Keystone_Devices

关键概念
KeyStone体系结构具有许多外围设备和大量事件源。事件的使用完全取决于用户的特定应用程序,这驱使了对最大灵活性的需求。如何处理中断或事件完全取决于软件的控制。EDMA3通道控制器(EDMA3CC)和C66x CorePacs都可以直接接收事件。但是,每个EDMA3CC和C66x CorePac接受事件的数量是有限的。[1]
KeyStone设备可以包含数百个事件。因此,其中一些事件需要先通过芯片级中断控制器(也称为CIC或CpIntc)在芯片级进行汇总,然后再路由到EDMA3CC和C66x CorePacs。在此必须注意,CIC / CpIntc与C66x CorePac内部的中断控制器不同,后者以缩写INTC表示。为了实现聚合,将多个CIC添加到SoC。CIC接收芯片级事件(系统事件)并生成主机中断,这些主机中断通过组合和/或选择这些芯片级事件而充当EDMA3CC和C66x CorePac的事件输入。[1]
下图显示了6678中断拓扑以及CIC和中断路由[3]。有关CIC内部运行方式的更多信息,请参见参考资料[2]中所示的CIC用户指南。

在这里插入图片描述
C66x DSP提供两种类型的异步信令服务:中断和异常。由于存在外部或内部硬件信号,中断提供了重定向正常程序流的方法。异常的相似之处在于它们还会重定向程序流,但是它们通常与系统中的错误情况相关联。C66x DSP可以接收12个可屏蔽/可配置中断,1个可屏蔽异常和1个不可屏蔽中断/异常。C66x CorePac中断控制器INTC最多可将124个系统事件路由到DSP中断/异常输入。这124个事件可以直接连接到可屏蔽中断,也可以组合成中断或异常。[2]

下图显示了CorePac INTC [2]。EVT [127:4]代表124个事件ID,INTC [15:4]代表12个可屏蔽/可配置中断。
124个系统事件存储在称为事件标志寄存器的四个32位寄存器中,每个事件都映射到特定的标志位。当在INTC接收到系统事件时,相应的事件标志寄存器位将被相应设置。注意事件标志寄存器是只读的。事件设置寄存器和事件清除寄存器可用于手动设置或清除事件标志寄存器中的任何位。[2]
事件合并器允许将多个系统事件合并为一个事件。
在这里插入图片描述
下图显示了Keystone CorePac中事件组合器的逻辑表示。如下图所示,将124个系统事件分为4组。事件组合器逻辑具有将多个事件输入分组为4个可能的事件输出EVT [3:0]的能力。这些输出然后作为中断选择器的输入提供,并被视为其他系统事件。上图[2]对此进行了说明。
在这里插入图片描述
下图总结了Keystone设备上中断处理的关键处理流程
在这里插入图片描述
在这里插入图片描述
下图显示了一个高级框图,并标识了我们在深入研究软件实现和API使用的下一部分时应牢记的一些关键术语。
在这里插入图片描述
软件实施
有两个主要的软件组件提供了可用于在Keystone设备上配置中断的API。多核软件开发套件(MCSDK)包含两个软件包,即。SYS / BIOS和平台开发套件(PDK),使开发人员能够编写中断程序。可以从本文档结尾的参考中提供的Weblink下载MCSDK。[4]

程序员可以自由使用这两种方法,尽管在选择时可以记住一些通用准则:
如果应用程序开发人员计划在其设备上使用SYS / BIOS RTOS,则建议他们利用相关的SYS / BIOS中断API配置中断,并仅在SYS / BIOS API中不存在等效功能的情况下使用CSL API。 。但是,这里需要特别注意的是,如果应用程序开发人员同时使用SYS / BIOS和CSL API来映射中断并写入中断服务表指针(ISTP),则将产生冲突,因为CSL和SYS / BIOS都将假设他们拥有ISTP。
如果系统不使用SYS / BIOS RTOS,则可以使用CSL API映射和配置中断。

使用CSL API
PDK中包含用于中断编程的相关API的特定模块是芯片支持库(CSL)。用于CorePac中断控制器(又称为INTC)的CSL API的格式为CSL_intcxxx,而用于芯片级中断控制器(又称为CIC)的CSL API 的格式为CSL_CPINTCxxx。我们将首先专注于配置CorePac的INTC,然后再深入研究用于配置CIC的API。
配置CorePac的INTC
如下代码片段所示,通用的CSL方法为INTC进行中断映射。在此示例中,事件ID 63映射到中断向量4。如果要更改触发中断的事件,请首先查找事件ID,该ID在设备特定的数据手册中列出(对于6678,在参考[3]中的表7-38)。一旦你已经确定的事件ID(我们代表这个由XX),修改下面的代码片段,以取代CSL_INTC_EVENTID_63与CSL_INTC_EVENTID_xx作为第二个参数CSL_intcOpen函数调用。同样,如果您想将中断向量从4更改为另一个向量ID号(4到15之间),则将由xx表示的新中断向量分配为将CSL_INTC_VECTID_xx 转换为以下代码中的变量vectId。

{
   CSL_IntcObj intcObj63p;
   CSL_IntcGlobalEnableState state;

   CSL_IntcContext context;

   CSL_Status intStat;
   CSL_IntcParam vectId;

   context.numEvtEntries = 0;
   context.eventhandlerRecord = NULL;

   CSL_intcInit(&context);

   CSL_intcGlobalNmiEnable();
   intStat = CSL_intcGlobalEnable(&state);

   vectId = CSL_INTC_VECTID_4;
   hIntc63 = CSL_intcOpen (&intcObj63, CSL_INTC_EVENTID_63, &vectId, NULL);

   EventRecord.handler = &event63Handler;
   EventRecord.arg = hIntc63;

   CSL_intcPlugEventHandler(hIntc63,&EventRecord);
   CSL_intcHwControl(hIntc63,CSL_INTC_CMD_EVTENABLE,NULL);
 
   CSL_IntcClose(hIntc63);
}

void event63Handler(CSL_IntcHandle hIntc){
  . . .
}

的CSL_IntcContext是用于存储当前的INTC上下文,并采用四个要素的结构:事件处理程序记录,事件分配掩码,事件条目的数量和偏移。事件处理程序记录包括事件处理程序,即发生特定事件时将调用的ISR函数,以及将传递给该ISR函数的相应参数。事件条目的数量与程序员计划映射的事件的数量相对应。事件分配掩码由4个32位值的数组组成,其中每个位代表128个事件之一。偏移量映射是一个由128个元素组成的数组,用于存储128个事件中的每个事件是否已映射到CPU中断以及关联的事件处理程序是否有效。

在示例的下一步中,我们使用CSL_intcGlobalEnable()和CSL_intcGlobalNmiEnable() API 启用全局中断和NMI中断。
使用CSL_intcOpen(…) API 将事件映射到中断。API保留一个中断事件以供使用,并且仅当当前未分配事件时才向该事件返回有效的句柄。在此示例中,我们将事件ID 63映射到CPU中断向量4。

要定义发生此事件时应运行的ISR,我们首先更新INTC上下文的事件处理程序记录。在此示例中,我们将事件处理程序指向“ test_isr_handler”,这是事件63发生时我们要执行的功能。该CSL_intcPlugEventHandler(…)然后API是用来绑一个事件处理程序的事件,这样当事件发生时,相关的事件处理程序被调用。该CSL_intcHwControl(…)然后API来实现的情况下,在这种情况下事件63。
最后,调用CSL_intcClose(…) API取消分配并释放事件。一旦称为INTC句柄,就不能再使用该事件了;仅在再次“打开”事件对象时,才可能进一步访问事件资源。

配置CIC
用于配置CIC的CSL API的格式为CSL_CPINTC_ xxx。以下代码段显示了一些典型的CSL API和CIC配置的一般流程。

/* Disable all host interrupts. */
CSL_CPINTC_disableAllHostInterrupt(hnd);

/* Configure no nesting support in the CPINTC Module. */
CSL_CPINTC_setNestingMode (hnd, CPINTC_NO_NESTING);

/* We now map System Interrupt 0 - 3 to channel 3 */
CSL_CPINTC_mapSystemIntrToChannel (hnd, 0 , 2);
CSL_CPINTC_mapSystemIntrToChannel (hnd, 1 , 4);
CSL_CPINTC_mapSystemIntrToChannel (hnd, 2 , 5);
CSL_CPINTC_mapSystemIntrToChannel (hnd, 3 , 3);

/* Enable system interrupts 0 - 3 */
CSL_CPINTC_enableSysInterrupt (hnd, 0);
CSL_CPINTC_enableSysInterrupt (hnd, 1);
CSL_CPINTC_enableSysInterrupt (hnd, 2);
CSL_CPINTC_enableSysInterrupt (hnd, 3);

/* Enable Host interrupt 3 */
CSL_CPINTC_enableHostInterrupt (hnd, 3);

/* Enable all host interrupts also. */
CSL_CPINTC_enableAllHostInterrupt(hnd);

代码片段中的注释提供了大多数代码尝试实现的解释。请注意,使用第二个参数CPINTC_NO_NESTING调用函数CSL_CPINTC_setNestingMode 会将 “嵌套”配置为停用。术语“嵌套”是指使开发人员能够配置CIC的方法,以便在服务当前中断时,禁用某些指定的中断。典型用法是嵌套在当前中断上,并禁用优先级相同或较低的所有中断(或通道)。KeyStone设备不支持嵌套模式。因此该信息不在用户指南中,并且在上述代码段和CSL示例中已被禁用。
为了更详细地了解CIC for CIC配置,我们建议您下载MCSDK,并在MCSDK安装路径下的文件夹“ pdk_C6678_x_x_x_xx \ packages \ ti \ csl \ example \ cpintc”下导入并浏览Code Composer Studio项目。 ’

要更详细地了解CSL(包括与中断相关的API),请参阅计算机上MCSDK安装路径中的API文档,位于“ pdk_C6678_x_x_x_xx \ packages \ ti \ csl \ docs \ csldocs.chm”


在此示例中,我们尝试利用到目前为止所学的知识在TI 6678多核设备上为Hyperlink设置中断。

/*** --- INTC Initializations --- ***/

/* Note that hyplnk_EXAMPLE_COREPAC_VEC = 4, hyplnk_EXAMPLE_COREPAC_INT_INPUT = 0x15, */
/* CSL_INTC_CMD_EVTCLEAR = 3, CSL_INTC_CMD_EVTENABLE = 0 */

CSL_IntcParam vectId = hyplnk_EXAMPLE_COREPAC_VEC; 
Int16 eventId = hyplnk_EXAMPLE_COREPAC_INT_INPUT;
CSL_IntcGlobalEnableState   state;

/* INTC module initialization */
hyplnkExampleIntcContext.eventhandlerRecord = hyplnkExampleEvtHdlrRecord;
hyplnkExampleIntcContext.numEvtEntries      = 2;
CSL_intcInit(&hyplnkExampleIntcContext);  

/* Enable NMIs */
CSL_intcGlobalNmiEnable(); 

/* Enable global interrupts */
CSL_intcGlobalEnable(&state);

hyplnkExampleIntcHnd = CSL_intcOpen (&hyplnkExampleIntcObj, eventId, &vectId, NULL);
hyplnkExampleEvtHdlrRecord[0].handler = hyplnkExampleIsr;
hyplnkExampleEvtHdlrRecord[0].arg = (void *)eventId;
CSL_intcPlugEventHandler(hyplnkExampleIntcHnd, hyplnkExampleEvtHdlrRecord);

/* Clear the event in case it is pending */
CSL_intcHwControl(hyplnkExampleIntcHnd, CSL_INTC_CMD_EVTCLEAR, NULL);

/* Enable event */
CSL_intcHwControl(hyplnkExampleIntcHnd, CSL_INTC_CMD_EVTENABLE, NULL);

/*** --- CIC Initializations --- ***/

CSL_CPINTC_Handle hnd;
hnd = CSL_CPINTC_open (0);
  
/* Disable all host interrupts. */
CSL_CPINTC_disableAllHostInterrupt(hnd);
    
/* Configure no nesting support in the CPINTC Module */
CSL_CPINTC_setNestingMode (hnd, CPINTC_NO_NESTING);

/* Clear Hyperlink system interrupt number 111 */
/* We get the interrupt number from Table 7-39 in the 6678 */
/* data manual at http://www.ti.com/lit/ds/sprs691c/sprs691c.pdf */
CSL_CPINTC_clearSysInterrupt (hnd, CSL_INTC0_VUSR_INT_O);

/* Enable Hyperlink system interrupt number 111 on CIC0 */
CSL_CPINTC_enableSysInterrupt (hnd, CSL_INTC0_VUSR_INT_O);

/* Map System Interrupt to Channel. */
/* Note that hyplnk_EXAMPLE_INTC_OUTPUT = 32 + (11 * CoreNumber) = 43 for Core0*/
CSL_CPINTC_mapSystemIntrToChannel (hnd, CSL_INTC0_VUSR_INT_O, hyplnk_EXAMPLE_INTC_OUTPUT);  

/* Enable the Host Interrupt */
CSL_CPINTC_enableHostInterrupt (hnd, hyplnk_EXAMPLE_INTC_OUTPUT);

CSL_CPINTC_enableAllHostInterrupt(hnd);

使用SYS / BIOS
SYS / BIOS是MCSDK安装的一部分。SYS / BIOS中的三个API模块特别适合中断处理:HWI,EventCombiner和CpIntc。HWI模块用于配置CorePac的INTC。EventCombiner模块用于配置事件组合器;CpIntc模块用于配置CIC以将系统中断映射到主机中断。在本节中,我们将深入研究每个模块。

硬件
该模块提供用于管理硬件中断的API。所述ti.sysbios.family.c64p.Hwi模块提供了实现功能HWI特定于C64x的+和的C66x设备的API。
下面的代码段显示了创建HWI实例的示例。在此示例中,事件ID 10映射到中断向量5。如果要更改触发中断的事件,请首先查找事件ID,该ID在设备特定的数据手册中列出(对于6678,在参考[3]中的表7-38)。确定事件ID后,请修改下面的代码片段,以将相关的HWI params元素(hwiParams.eventId)分配给新的事件ID。如果要将中断向量从5更改为另一个向量ID号(4到15之间),请使用新的中断向量号作为Hwi_create函数调用的第一个参数。

#include <xdc/runtime/Error.h>
#include <ti/sysbios/hal/Hwi.h>
  
Hwi_Handle myHwi;
  
Int main(Int argc, char* argv[])
{
    Hwi_Params hwiParams;
    Error_Block eb;
   
    Hwi_Params_init(&hwiParams);
    Error_init(&eb);
  
    // set the argument you want passed to your ISR function
    hwiParams.arg = 1;        
 
    // set the event id of the peripheral assigned to this interrupt
    hwiParams.eventId = 10;   
 
    // don't allow this interrupt to nest itself
    hwiParams.maskSetting = Hwi_MaskingOption_SELF;
 
    // 
    // Configure interrupt 5 to invoke "myIsr".
    // Automatically enables interrupt 5 by default
    // set params.enableInt = FALSE if you want to control
    // when the interrupt is enabled using Hwi_enableInterrupt()
    //
   
    myHwi = Hwi_create(5, myIsr, &hwiParams, &eb);
   
    if (Error_check(&eb)) {
        // handle the error
    }
}
   
Void myIsr(UArg arg)
{
    // this runs when interrupt #5 goes off
}

EventCombiner
事件组合器允许用户将多达32个系统事件组合为一个组合事件。事件0、1、2和3是与事件组合器关联的事件。通过将EventCombiner模块与Hwi模块一起使用,用户可以将组合事件路由到GEM上可用的12个可屏蔽CPU中断中的任何一个。EventCombiner支持多达128个系统事件。用户可以为每个系统事件指定一个函数和一个参数,并可以选择启用他们想要的任何系统事件。
您可以通过两种方式设置EventCombiner。一种方法是在CCS项目的RTSC配置文件(.cfg)中静态执行此操作。另一种方法是在C代码中执行此操作。下面的代码段中说明了这两种方法。
方法1:在.cfg文件中
此代码段合并事件15和16,并使用中断向量4

var EventCombiner = xdc.useModule('ti.sysbios.family.c64p.EventCombiner');
EventCombiner.events[15].unmask = true;
EventCombiner.events[15].fxn = '&event15Fxn';
EventCombiner.events[15].arg = 0x15;
EventCombiner.events[16].unmask = true;
EventCombiner.events[16].fxn = '&event16Fxn';
EventCombiner.events[16].arg = 0x16;

方法2:在C文件中
此代码段合并事件4和5,并使用中断向量8

eventId = 4; 
EventCombiner_dispatchPlug(eventId,&event4Fxn,arg,TRUE); 
EventCombiner_dispatchPlug(eventId + 1,&event5Fxn,arg,TRUE); 

Hwi_Params_init(&params); 
params.arg =(eventId / 32; 
params.eventId =(eventId / 32; 
params.enableInt = TRUE; 

intVector = 8; 

Hwi_create(intVector,&EventCombiner_dispatch,&params,NULL;

CpIntc
该模块管理CIC硬件。该模块支持启用和禁用系统和主机中断。该模块还支持将系统中断映射到主机中断,并将主机中断映射到Hwis或EventCombiner。连接到GEM中断控制器的CIC在运行期间静态支持这些功能,但在其他CIC运行期间仅静态支持这些功能。有一个调度功能,用于处理由系统中断触发的GEM硬件中断。默认情况下,模块启动功能中启用了全局启用寄存器。

系统中断是由系统中的硬件模块生成的那些中断。这些中断是CIC的输入。主机中断是CIC的输出中断。通道与主机中断之间存在一对一的映射,因此,术语“主机中断”也用于通道。请注意,此模块不支持优先级划分,嵌套和向量化。
提供CpIntc API的SYS / BIOS模块为“ ti.sysbios.family.c66.tci66xx.CpIntc”。
以下代码段提供了使用CpIntc API的示例实现。每行代码之前的注释说明了代码实现的目的。

// Map system interrupt 15 to host interrupt 8
CpIntc_mapSysIntToHostInt(0, 15, 8); 

// Plug the function for event #15
CpIntc_dispatchPlug(15, &event15Fxn, 15, TRUE); 

// Enable host interrupt #8
CpIntc_enableHostInt(0, 8); // enable host interrupt 8


在这里,我们整理了本节的学习内容,并介绍了SYS / BIOS示例。

/* Map the System Interrupt i.e. the Interrupt Destination 0 interrupt to the DIO ISR Handler. */
CpIntc_dispatchPlug(CSL_INTC0_INTDST0, (CpIntc_FuncPtr)myDioTxCompletionIsr, (UArg)hSrioDrv, TRUE);

/* The configuration is for CPINTC0. We map system interrupt 112 to Host Interrupt 8. */
CpIntc_mapSysIntToHostInt(0, CSL_INTC0_INTDST0, 8);

/* Enable the Host Interrupt. */
CpIntc_enableHostInt(0, 8);

/* Enable the System Interrupt */
CpIntc_enableSysInt(0, CSL_INTC0_INTDST0);

/* Get the event id associated with the host interrupt. */
eventId = CpIntc_getEventId(8);

Hwi_Params_init(&params);

/* Host interrupt value*/
params.arg = 8;                            

/* Event id for your host interrupt */
params.eventId = eventId;          

/* Enable the Hwi */
params.enableInt = TRUE;       

/* This plugs the interrupt vector 4 and the ISR function. */
/* When using CpIntc, you must plug the Hwi fxn with CpIntc_dispatch */
/* so it knows how to process the CpIntc interrupts.*/
Hwi_create(4, &CpIntc_dispatch, &params, NULL);  

References
[1] CorePac User Guide http://www.ti.com/litv/pdf/sprugw0b
[2] CIC User Guide http://www.ti.com/litv/pdf/sprugw4a
[3] C6678 Data Manual http://www.ti.com/lit/ds/symlink/tms320c6678.pdf
[4] MCSDK Download Page http://www.ti.com/tool/bioslinuxmcsdk
[5] SYS/BIOS & HWI e2e Forum Post http://e2e.ti.com/support/embedded/bios/f/355/t/94262.aspx
[6] Nesting e2e Forum Post http://e2e.ti.com/support/dsp/c6000_multi-core_dsps/f/639/t/189559.aspx
[7] CpIntc e2e Forum Post http://e2e.ti.com/support/embedded/bios/f/355/p/203249/724263.aspx#724263

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值