1.初始化
6747的GPIO模块初始化步骤如下:
1.1 执行必要的引脚复用设置,如将引脚设置为中断模式或GPIO模式(查阅具体的数据手册)
1.2 对电源与睡眠控制器(PSC,Power and Sleep Controller)进行编程以使能GPIO模块,关于PSC的细节,见“电源与睡眠控制器”一章。
1.3 对方向(direction),数据(data)和中断(interrupt)控制寄存器编程,对要用的引脚的配置进行设置。
完成上述步骤即可开始进行数据传输。6747的所有GPIO引脚均可配置用于产生中断,硬件复位以后要进行GPIO的初始化。
2.使能GPIO中断事件
通过设置GPIO中断组使能寄存器(GPIO interrupt per-bank enable register,BINTEN)的相应位(bit)可以使能相应的GPIO中断事件,中断组使能寄存器中的一位控制一组(bank)GPIO的中断事件,对应16个GPIO脚的中断事件。例如,要使能第0组(bank 0)的所有中断(来自GP0[15-0]引脚的事件),就设置BINTEN的第0位(0 bit);使能第3组(bank 3)的所有中断,就设置BINTEN的第3位(bit 3)。
3.配置GPIO中断边沿触发
每个GPIO中断源(interrupt source)都可以配置成上升沿(rising edge)触发,下降沿(falling edge)触发,上下边缘触发,或者上下边缘都不触发。当相应的信号边沿到达时,中断源产生中断信号。边沿检测(edge detection)同步到GPIO外设模块时钟。
以下4个寄存器控制GPIO中断边沿检测的配置:
1. GPIO上升沿中断置位寄存器(GPIO set rising edge interrupt register,SET_RIS_TRIG)使能上升沿触发。
2. GPIO上升沿中断清零寄存器(GPIO clear rising edge interrupt register,CLR_RIS_TRIG)关闭上升沿触发。
3. GPIO下降沿中断置位寄存器(GPIO set falling edge interrupt register,SET_FAL_TRIG)使能下降沿触发。
4. GPIO下降沿中断清零寄存器(GPIO clear rising edge interrupt register,CLR_FAL_TRIG)关闭下降沿触发。
设置GPIO上升沿触发,往SET_RIS_TRIG寄存器相应的位写1,CLR_FAL_TRIG写1.
设置GPIO下降沿触发,往SET_FAL_TRIG寄存器相应的位写1,CLR_RIS_TRIG写1.
设置GPIO上下边沿触发,往SET_RIS_TRIG寄存器相应的位写1,SET_FAL_TRIG写1.
关闭某个GPIO中断,往CLR_RIS_TRIG寄存器相应的位写1,CLR_FAL_TRIG写1.
注意GPIO信号的方向不一定要是输入才能产生中断事件。当中断信号配置为输出的时候,可以通过软件改变GPIO信号的状态,从而产生中断。这对调试中断信号连通性很有用。
4.GPIO中断状态(GPIO InterruptStatus)
可以通过读GPIO中断状态寄存器(interrupt status register,INTSTAT)来监控GPIO中断事件的状态。挂起的(Pending)GPIO中断会在相应的位显示1,不挂起的中断会在相应的位显示0。
对直接接到DSP子系统的GPIO中断,可以通过读CPU相应的中断标志(interrupt flag)来确定中断状态。对GPIO组中断(bank interrupts),INTSTAT可以用于确定哪个GPIO中断发生了。软件中应该要确保所有挂起的GPIO中断都得到适当的处理。
挂起的GPIO中断标志位可以通过往INTSTAT相应的位写1清除。
5.GPIO中断状态寄存器(GPIOInterrupt Status Registers,INTSTATn)
GPIO中断事件的状态可以通过读GPIO中断状态寄存器来进行监控。在相应的位,挂起的GPIO中断会显示1,不挂起的中断显示0。GPIO中断状态寄存器有INTSTAT01,INTSTAT23, INTSTAT45, INTSTAT67, INTSTAT8。如下所示:
(用户手册P855)
(数据手册P836)
程序中,当进入中断服务程序时,说明该中断已得到响应,中断挂起标志INSTAT应清除,否则当退出时又会重新执行此段程序。当执行Ex2INT中断服务程序时,说明GPIO bank2发生中断,具体是GPIO bank2的哪个引脚,需要通过GPIO中断状态寄存器INISTAT来判断。如果GPIO_INSTAT23(GPIO bank2和bank3的中断状态寄存器)的最低位为1,即GP2P0为1,说明中断是通过GPIO bank2的引脚0(pin0)发生的,则执行相应的操作,否则说明是GPIO bank2其他引脚发生了中断。
(数据手册P836)
(TMS320C674x DSP Megamodule Reference Guide P178)
(sprufk5a P178)
C6000家族DSP外设集可以有多达32个中断源,但是CPU可用的中断只有12个。中断选择器可以从这32个中断源中挑选12系统所需的中断源并进行设置其优先级。
(TMS320C6000 DSP Interrupt Selector ReferenceGuide P7)
中断选择器(interrupt selector)含有中断复用寄存器,6747共有3个中断复用寄存器,在中断复用寄存器(Interrupt Mux Registers,INTMUXn,n=1-3)中可以设置12个可用的CPU中断对应的中断源。程序中这句话,设置INTSEL4=0x31(49dec),INTSEL5=34(52dec),INTSEL6=36(54dec)。查找数据手册中断源对应的中断事件(event)的数字,如下:
(数据手册P76)
可见,这里设置了CPU中断4(INT4)的中断源为GPIO Bank2 Interrupt,中断5(INT5)的中断源为GPIO Bank 3 Interrupt,中断6(INT6)的中断源为GPIO Bank 4 Interrupt,
这里这样设置是要对应linkercmd文件中memory段vecs部分地址的设置,在链接文件linkercmd文件中,vecs定义了中断向量表放到以CPU逻辑地址0x80000000为起始地址(origin,o),长度为0x00000f00的区域中,所以ISTP也应该指向这个地址。见下图:
(注意linker.cmd链接文件中vecs的地址)
这是vector.asm这个汇编文件中所放的各中断服务程序的地址,注意67行定义了该段为vectors段,即上面链接文件中定义的0x80000000开始的那片区域。当某个中断事件发生,该中断源引发对应的CPU中断,例如假设将CPU中断4的中断源设置为GPIO_bank2的中断,当发生gpio_bank_2的中断时,CPU就会执行对应中断号为4的中断服务程序,在vectors段中可见,中断号为4的中断服务程序对应的入口(VEC_ENTRY)为Ex2INT,即CPU将执行函数名为Ex2int的程序。再细看一下,0x80000000地址处于空白部分,即不与6747其它任何外设的映射地址冲突,见下图:
(TMS320C6745/C6747Fixed/Floating-Point Digital Signal Processors (Rev. F)P25)
ISTP(Interrupt service table pointer,中断服务表指针)指向中断向量表的起始地址,当中断事件发生时,会寻找相应中断处理程序的首地址,该地址等于中断事件的偏移量加上ISTP。
(TMS320C674x DSP CPU and Instruction Set Reference Guide P706)
ISTP的作用简介:
(TMS320C674xDSP CPU and Instruction Set Reference Guide P45)
ICR(Interrupt Clear Register,中断清除寄存器)用于清除中断标志寄存器(interrupt flag register,IFR)中可屏蔽中断(INT15-INT4)的中断标志。
(TMS320C674x DSP CPU and InstructionSet Reference Guide P41)
ISR(Interrupt set register,中断置位寄存器)用于手动设置IFR中的可屏蔽中断(INT15-INT4),如下所示:
(TMS320C674x DSP CPU and InstructionSet Reference Guide P44)
IER(Interrupt Enable Register,中断使能寄存器)可以使能或禁止单个中断,功能如下:
(TMS320C674x DSP CPU and InstructionSet Reference Guide P42)
当*LED=0xfd时,LED从高位到低位依次为:
D9 D8 D7 D6 D5 D4 D3 D2
1 1 1 1 1 1 0 1;
则D3点亮,其它所有灯灭。
当*LED=0xfe时,LED从高位到低位依次为:
D9 D8 D7 D6 D5 D4 D3 D2
1 1 1 1 1 1 1 0;
则D2点亮,其它所有灯灭。
按下按键S6,则GP4_11发生中断,执行Ex4INT中断服务程序。
按下按键S3,则GP2_0发生中断,执行Ex2INT中断服务程序。
按下按键S4,则GP2_4发生中断,执行Ex2INT中断服务程序。
按下按键S5,则GP3_11发生中断,执行Ex3INT中断服务程序。
电路如图:
(研旭YXDSP-C6747开发板官方用户手册V4 P86)
使能GPIO中断事件
用户手册P832
代码如下:
/*
DSP6747 & FPGA
*/
#include "stdio.h"
#include "C6747.h"
Uint16 *LED = (Uint16 *)0x64000012; ///led add
Uint16 led0[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
Uint16 led1[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
Uint16 led2[8]={0x7f,0x3f,0x1f,0x0f,0x07,0x03,0x01,0x00};
Uint16 led3[8]={0x00,0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f};
Uint16 myled[4]={0xfe,0xfd,0xfb,0xf7};
Uint8 flag;
void delay(unsigned int t)
{
Uint32 i,j;
for(i=0;i<t;i++)
{
for(j=0;j<4000;j++);
}
}
/* ------------------------------------------------------------------------ *
* *
* Testing Function *
* *
* ------------------------------------------------------------------------ */
void interrupt Ex2INT() //AD采集完后的中断响应函数
{
asm(" DINT ");//CSR&=0xfffe; //关中断
asm(" NOP 2 ");
//打开读数标志
if(GPIO_INSTAT23 & 0x00000001 ) // 清除中断标志GPIOSTAT
{ flag=1;*LED=~(*LED^0xfd);}
else// if(GPIO_INSTAT23 & 0x00004000 )
{flag=2;*LED=~(*LED^0xfb);}
GPIO_INSTAT23=0xffffffff;
asm(" NOP 2 ");
asm(" RINT "); // CSR=CSR|0x1; // 开中断
}
void interrupt Ex3INT() //AD采集完后的中断响应函数
{
asm(" DINT ");//CSR&=0xfffe; //关中断
asm(" NOP 2 ");
flag=3;*LED=~(*LED^0xf7); //打开读数标志
GPIO_INSTAT23=0xffffffff; // 清除中断标志GPIOSTAT
asm(" NOP 2 ");
asm(" RINT "); // CSR=CSR|0x1; // 开中断
}
void interrupt Ex4INT() //AD采集完后的中断响应函数
{
asm(" DINT ");//CSR&=0xfffe; //关中断
asm(" NOP 2 ");
flag=4; //打开读数标志
*LED=~(*LED^0xfe);
GPIO_INSTAT45=0xffffffff; // 清除中断标志GPIOSTAT
asm(" NOP 2 ");
asm(" RINT "); // CSR=CSR|0x1; // 开中断
}
void initExint(void)
{
CSR&=0xfffe; //关中断
asm(" NOP 2 ");
// IENSET=0x3; // 使能中断源
GPIO_INSTAT23=0xFFFFFFFF; //清除第2 3 BANK的中断标志位
GPIO_INSTAT45=0xFFFFFFFF; //清除第4 BANK的中断标志位
GPIO_BINTEN=0x1c; //使能GPIO BANK 2 3 4外部中断功能
GPIO_CLR_RIS_TRIG23=0x08000011; //关闭上升沿中断
GPIO_SET_FAL_TRIG23=0x08000011; //设置下降沿中断
GPIO_CLR_RIS_TRIG45=0x00000800; //关闭上升沿中断
GPIO_SET_FAL_TRIG45=0x00000800; //设置下降沿中断
INTmux1=0x363431; // 指定exINT到外部中断4
asm(" NOP 2 "); // 关中断 GIE=0
ISTP=0x80000000; // 重置中断向量表到0C00h
asm(" NOP 2 ");
ICR=0xFFFF;
asm(" NOP 2 ");
ISR=0x0; // 清除等待的中断
asm(" NOP 2 ");
IER=0xffff;
}
void main( void )
{ Uint8 i=0;
/* Initialize OMAPL137*/
C6747_init(); //初始化6747核
initExint(); //中断配置
CSR=CSR|1; //开中断
flag=0;
*LED=0x00;
*LED=~*LED;//取反LED
while(1)
{
/* if(flag==0)
{
for(i=0;i<8;i++)
{*LED=led0[i];
delay(400);}
*LED=0xfe;
}
if(flag==1)
{
for(i=0;i<8;i++)
{ *LED=led1[i];
delay(400);}
}
if(flag==2)
{ for(i=0;i<8;i++)
{ *LED=led2[i];
delay(400);}
}
if(flag==3)
{ for(i=0;i<8;i++)
{ *LED=led3[i];
delay(400);}
}
if(flag==4)
flag=0;*/
}
}