TMS320C6748EDMA_GPIO_中断学习笔记

// 申请 EDMA3 通道
EDMA3RequestChannel(SOC_EDMA30CC_0_REGS, chType, chNum, tccNum, evtQ);

    这句函数中,chNum指的是所申请的通道的number,cc0和cc1各有32个DMA通道,每个通道对应一个特定的事件(event),如cc0的channel6对应GPIObank0的中断

(指南P439)

(手册P102)

    evtQ是事件队列,chNum对应的事件发生后,会将该事件缓存入事件队列中,等待处理,cc0有2个队列,每个队列最大深度为16,即最多只能存放16个事件,队列0的优先级比队列1的优先级高,如果Q1和Q2同时有至少1个事件,则Q1的事件会先出队,提交TR(transfer request)给TR0,然后Q2的事件才出队,给TR1。当数据转移完成后,TC(transfer controller)会返回TCC(transfer completion code)给CC(channel controller),TCC在与channel关联的Param Set中设置。TCC决定了IPR(interrupt pending register)中的那位被置位,如果在IER(interrupt enable register)中相应的位也为1,使能了该中断,就会产生相应的中断给CPU。

(指南P522)

    转移(transfer)完成所产生具体的中断事件以下公式决定。

(指南P523)

/** \brief Base address of GPIO memory mapped registers */
#define SOC_GPIO_0_REGS (0x01E26000)    
void GPIOBankIntDisable(unsigned int baseAdd, unsigned int bankNumber)
GPIOBankIntDisable(SOC_GPIO_0_REGS, 0);

该句清除BINTEN中相应位,禁止GPIObank0中断。

(手册P254)

#define SYS_INT_GPIO_B0INT 65
IntEventClear(SYS_INT_GPIO_B0INT);

该句清除DSP中断控制器中的系统中断状态位,系统中断状态位在中断控制器的事件标志寄存器EVTFLAGn中(n=1~4),每个EVTFLAG寄存器存放32个系统中断状态,每一位对应一个中断事件,如EVTFLAG3的1位对应的是标号为65的中断事件,即GPIObank0中断,当GPIObank0中断事件发生时,该位就会置为1。

(手册P22)

(手册P96)

(mega手册P170)

在中断处理程序(interrupt service routine)中,需要清除事件标志寄存器中断事件标志位,则需要往事件清除寄存器相应的位写1。如GPIObank0中断事件发生时,因为该中断事件的标号为65,所以EVTFLAG2寄存器的1位会置1,要清除该位,需要往EVTCLR3寄存器的1位写1.

(mega手册P169)

(mega手册P173)

void GPIOPinIntClear(unsigned int baseAdd, unsigned int pinNumber)
GPIOPinIntClear(SOC_GPIO_0_REGS, 7);

该句清除GPIObank0pin6所对应的GPIO中断状态位。GPIO中断状态寄存器INTSTAT为标志GPIO引脚发生中断的寄存器,当某个GPIO引脚发生中断时,相应的INTSTATn寄存器中的位会被置1。如GPIObank0的pin6发生下降沿触发中断时,INTSTAT01寄存器的6位会被置1.软件需要往INTSTAT01寄存器的6位写1才能将其清除。

(指南P867)

// 注册中断服务函数
IntRegister(C674X_MASK_INT6, USER0KEYIsr);
void IntRegister (unsigned int cpuINT, void (*userISR)(void))
{
  /* Check the CPU maskable interrupt number */
  ASSERT(((cpuINT >= 1) && (cpuINT <= 15)));

  /* Assign the user's ISR to the CPU maskable interrupt */
  c674xISRtbl[cpuINT] = userISR;
}

static c674xISR c674xISRtbl[C674X_INT_COUNT];
typedef void (*c674xISR)(void);

c674xISRtbl为定义的一个函数指针数组,存放的函数指针指向参数列表为void,返回值为void的函数。其实c674xISRtbl就是存放中断服务程序地址的指针数组,各指针分别指向对应INT4到INT15的中断服务程序(interrupt service routine)。IntRegister(C674X_MASK_INT6, USER0KEYIsr);这句函数将该c674xISRtbl函数指针数组的第6个指针指向了USER0KEYIsr函数。

// 映射中断到DSP可屏蔽中断
IntEventMap(C674X_MASK_INT6, SYS_INT_GPIO_B0INT);

该句函数将中断复用器INTMUX1的INTSEL6字段设为GPIObank0中断事件号65,即将标号为65的中断源映射到标号为6的CPU中断。INTMUXn寄存器地址及字段如下图所示:

(手册P96)

(mega手册P178)

那么,当发生65号中断(GPIObank0中断时),CPU又为什么能够执行c674xISRtbl[C674X_MASK_INT6]函数指针所指向的函数呢?这个问题背后的实现机制有点绕,我也是想了很久才明白。

首先,在DSP中断控制器初始化的时候,IntDSPINTCInit();函数将中断服务表指针ISTP(Interrupt Service Table Pointer)指向了中断向量表_intcVectorTable,函数部分如下:

/* Set interrupt service table pointer to the vector table */
#ifdef__TI_EABI__
ISTP = (unsigned int)_intcVectorTable;
#else
ISTP = (unsigned int)intcVectorTable;
#endif

intcVectorTable中断向量表在starterware的systerm_config工程的intvecs.asm文件中定义了,代码如下:

1.	;  
2.	; File: intvecs.asm  
3.	;  
4.	; Brief: Contains interrupt vector table and fetch packets  
5.	;  
6.	; Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/  
7.	; ALL RIGHTS RESERVED  
8.	  
9.	;**********************************************************  
10.	;               Global Symbols  
11.	;**********************************************************  
12.	    .global _intcVectorTable  
13.	    .global _c_int00  
14.	    .global _c674x_nmi_isr  
15.	    .global _c674x_rsvd_int2_isr  
16.	    .global _c674x_rsvd_int3_isr  
17.	    .global _c674x_mask_int4_isr  
18.	    .global _c674x_mask_int5_isr  
19.	    .global _c674x_mask_int6_isr  
20.	    .global _c674x_mask_int7_isr  
21.	    .global _c674x_mask_int8_isr  
22.	    .global _c674x_mask_int9_isr  
23.	    .global _c674x_mask_int10_isr  
24.	    .global _c674x_mask_int11_isr  
25.	    .global _c674x_mask_int12_isr  
26.	    .global _c674x_mask_int13_isr  
27.	    .global _c674x_mask_int14_isr  
28.	    .global _c674x_mask_int15_isr  
29.	  
30.	;**********************************************************  
31.	;               Interrupt Fetch Packet  
32.	;**********************************************************  
33.	VEC_ENTRY .macro addr  
34.	    STW B0,*--B15  
35.	    MVKL addr,B0  
36.	    MVKH addr,B0  
37.	    B B0  
38.	    LDW *B15++,B0  
39.	    NOP 2  
40.	    NOP  
41.	    NOP  
42.	    .endm  
43.	  
44.	;**********************************************************  
45.	;               Interrupt Vector Table  
46.	;**********************************************************  
47.	    .align 1024  
48.	_intcVectorTable:  
49.	    VEC_ENTRY _c_int00  
50.	    VEC_ENTRY _c674x_nmi_isr  
51.	    VEC_ENTRY _c674x_rsvd_int2_isr  
52.	    VEC_ENTRY _c674x_rsvd_int3_isr  
53.	    VEC_ENTRY _c674x_mask_int4_isr  
54.	    VEC_ENTRY _c674x_mask_int5_isr  
55.	    VEC_ENTRY _c674x_mask_int6_isr  
56.	    VEC_ENTRY _c674x_mask_int7_isr  
57.	    VEC_ENTRY _c674x_mask_int8_isr  
58.	    VEC_ENTRY _c674x_mask_int9_isr  
59.	    VEC_ENTRY _c674x_mask_int10_isr  
60.	    VEC_ENTRY _c674x_mask_int11_isr  
61.	    VEC_ENTRY _c674x_mask_int12_isr  
62.	    VEC_ENTRY _c674x_mask_int13_isr  
63.	    VEC_ENTRY _c674x_mask_int14_isr  
64.	    VEC_ENTRY _c674x_mask_int15_isr  

但是intvecs.asm文件中,中断向量的名字是c674x_rsvd_intn_isr(n=2~15),与c674xISRtbl函数指针数组并没有直观的联系,这两者是如何对应上的呢?比如,当发生65号中断时,根据上面的映射,CPU会执行6号可屏蔽CPU中断服务程序_c674x_mask_int6_isr,但是c674x_mask_int6_isr程序的入口又在哪里?这里我找了很久,终于在interrupt.c文件中找到了该函数的定义,如下:

#ifdef __TI_EABI__
interrupt void _c674x_mask_int6_isr (void)
#else
interrupt voidc674x_mask_int6_isr (void)
#endif
{
c674xISRtbl[6]();
}

注意这句话c674xISRtbl[6]();,原来在中断服务程序c674x_mask_int6_isr中,程序直接跳转到了c674xISRtbl[6]函数指针所指的函数了,即上面所注册的用户函数userISR了,这就解释了中断发生后,程序怎么能够执行到用户所注册的函数的,技术路线有点绕。

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值