C6748_GPIO_KEY_TIMER_EventCombine
2019-07-13 20:30发布
生成海报
组合事件中断初始化
EventCombineInterruptInit();函数完成组合事件中断初始化,其中
//
使能定时器 /计数器中断TimerIntEnable(SOC_TMR_1_REGS,TMR_INT_TMR34_NON_CAPT_MODE);该函数使能了定时器中断。
SOC_TMR_1_REGS为(0x01C21000),即timer1的地址,如图所示:
(手册P22)
偏移44h,为定时器中断控制和状态寄存器INTCTLSTAT(Timer
Interrupt Control and Status Register)
(指南P1401)
(指南P1414)
TMR_INT_TMR34_NON_CAPT_MODE为((0x00010000u)),将PRDINTEN34位置1,使能了定时器中断。
#define C674X_MASK_INT4 4
#define ECM0_UNUSED -1
#define ECM1_UNUSED -1
#define ECM2_UNUSED -1
#define ECM3_UNUSED -1
IntEventCombineInit(ECM0_UNUSED, C674X_MASK_INT4, ECM2_UNUSED, ECM3_UNUSED);函数将event
combiner1的输出EVT1事件映射到了CPU可屏蔽中断4,因为所用到的事件中断GPIObank6中断和定时器1中断的中断号分别为62和48,都在32到63的范围,所以组合事件为EVT1。IntEventCombineInit函数中的这句语句
IntRegister(ecmINT1, IntEventCombineIsr1);将ECM1的中断服务函数IntEventCombineIsr1注册为了CPU可屏蔽中断4(ecmINT1传参为4)的中断服务函数(c674xISRtbl[cpuINT]
= userISR;)则当CPU可屏蔽中断4发生时,CPU将会执行函数指针c674xISRtbl[4]所指向的中断服务函数,这里是注册的函数IntEventCombineIsr1。IntEventMap(ecmINT1,
SYS_INT_EVT1);这句语句将事件中断1EVT1映射到CPU可屏蔽中断,中断号为参数ecmINT1.
(mega手册P166)
IntEventMap函数如下:
voidIntEventMap (unsignedint cpuINT, unsignedint sysINT)
{
unsignedint dspintcREG, restoreVal;
/* Check the CPU maskable interrupt number */
ASSERT(((cpuINT >= 4) && (cpuINT <= 15)));
/* Check the system event number */
ASSERT((sysINT <= 127));
/* Get the address of the correct interrupt mux register */
dspintcREG = SOC_INTC_0_REGS + DSPINTC_INTMUX((cpuINT >> 2));
/* Disable interrupts */
restoreVal = IntGlobalDisable();
/* Clear and set INTSELx with system event number */
HWREG(dspintcREG) = (HWREG(dspintcREG) &
~DSPINTC_INTMUX_INTSEL(cpuINT)) |
(sysINT << DSPINTC_INTMUX_INTSEL_SHIFT(cpuINT));
/* Clear any residual interrupt */
ICR = (1 << cpuINT);
/* Restore interrupts */
IntGlobalRestore(restoreVal);
}
程序中,dspintcREG赋值为中断复用寄存器INTMUX的地址,同时,将中断复用寄存器INTMUX中相应的INTSEL字段设置为要连接的中断事件源EVT。在这个程序中,是把中断事件1EVT1映射到了CPU可屏蔽中断4了。
IntEventCombineIsr1函数如下所示:
#define SYS_INT_EVT1 1
staticvoidIntEventCombineIsr1 (void)
{
IntEventCombinerDispatch(SYS_INT_EVT1);
}
IntEventCombinerDispatch(SYS_INT_EVT1);函数如下所示:
staticvoidIntEventCombinerDispatch (unsignedint evtReg)
{
unsignedint dspintcMEFREG, dspintcECREG, evtRcv, evtIndex, offset;
/* Get the address of the correct DSPINTC registers */
dspintcMEFREG = SOC_INTC_0_REGS + DSPINTC_MEVTFLAG(evtReg);
dspintcECREG = SOC_INTC_0_REGS + DSPINTC_EVTCLR(evtReg);
offset = evtReg * 32;
evtRcv = HWREG(dspintcMEFREG);
while(evtRcv)
{
/* Clear system events */
HWREG(dspintcECREG) = evtRcv;
/* Service system events */
do{
evtIndex = 31 - _lmbd(1, evtRcv);
evtRcv &= ~(1 << evtIndex);
c674xECMtbl[evtIndex + offset]();
}while(evtRcv);
/* Check for new system events */
evtRcv = HWREG(dspintcMEFREG);
}
}
dspintcMEFREG赋值为屏蔽事件标志寄存器1 MEVTFLAG1(masked
event flag register 1)的地址。
(mega手册P169)
dspintcECREG赋值为事件清除寄存器1 EVTCLR1(Event
clear register 1)的地址。
(mega手册P169)
_lmbd(1, evtRcv);为intrinsic函数,intrinsic函数为以下划线'_'号开头的一类特殊的函数,类似于内嵌的汇编指令,可以实现一些用汇编指令很容易实现而用CC++很难实现的功能。根据ccs帮助,lmbd函数定义如下:
这句语句搜索evtRcv变量最左边的1所在的位置,然后返回这个1左边的0的数目,例如,evtRcv=6(0000
0000 0000 0110b,evtRcv为unsigned int类型,故为32位数),最左边的1在第2位(下标从0开始),这个1左边一共有29个0,因此,_lmbd(1,
evtRcv)为29,其它情况分析类似。IntEventCombinerDispatch主要做的事情是,从evtRcv变量(赋值为屏蔽事件标志寄存器dspintcMEFREG)最左边的1开始(为1表示该为对应的事件发生),一直搜索到最右边的1,即搜索所有的被置位的中断事件标志,对相应的中断事件进行处理(运行中断服务程序c674xECMtbl[evtIndex
+ offset]();),直到所有的中断事件都得到处理。
(mega手册P167)
EVT1事件是EVT32到EVT63所有事件或的结果,EVT
MASK屏蔽相应的事件,让该事件不参与或运算。
(mega手册P160)
#define SYS_INT_GPIO_B6INT 62// GPIO bank6中断
#define SYS_INT_T64P1_TINT34 48// 定时器中断
// 添加事件
IntEventCombineAdd(SYS_INT_GPIO_B6INT);
IntEventCombineAdd(SYS_INT_T64P1_TINT34);
IntEventCombineAdd函数如下:
voidIntEventCombineAdd(unsignedint sysINT)
{
unsignedint dspintcREG, restoreValue;
/* Check the system event number */
ASSERT((sysINT <= 127));
/* Get the address of the correct event combiner register */
dspintcREG = SOC_INTC_0_REGS + DSPINTC_EVTMASK((sysINT >> 5));
/* Disable interrupts */
restoreValue = IntGlobalDisable();
/* Unmask system event number to be included in the combined event */
HWREG(dspintcREG) &= ~DSPINTC_EVTMASK_EM(sysINT);
/* Enable interrupts */
IntGlobalRestore(restoreValue);
}
这两句语句做的事是,根据要组合的事件,对事件屏蔽寄存器EVTMASKn(n=0~3)中相应的位清0,不屏蔽这些位所对应的事件,当这些事件中断发生时,发生组合事件中断。EVTMASK寄存器地址如下:
(mega手册P169)
(mega手册P174)
定时器初始化函数如下:
#define SOC_TMR_1_REGS (0x01C21000)
#define TMR_CFG_32BIT_UNCH_CLK_BOTH_INT (0x00000017u)
voidTimerInit(void)
{
// 配置定时器 / 计数器 1 为 32 位模式
TimerConfigure(SOC_TMR_1_REGS, TMR_CFG_32BIT_UNCH_CLK_BOTH_INT);
// 设置周期
TimerPeriodSet(SOC_TMR_1_REGS, TMR_TIMER34, TMR_PERIOD_32);
// 使能定时器 / 计数器 1
TimerEnable(SOC_TMR_1_REGS, TMR_TIMER34, TMR_ENABLE_CONT);
}
TimerConfigure函数如下:
voidTimerConfigure(unsignedint baseAddr, unsignedint config)
{
/*
** Set the timer control register. This will only affect the clock
** selection bits. All other fields will be reset and the timer counting
** will be disabled.
*/
HWREG(baseAddr + TMR_TCR) = (config & (TMR_TCR_CLKSRC12 | TMR_TCR_CLKSRC34));
/* Clear the Timer Counters */
HWREG(baseAddr + TMR_TIM12) = 0x0;
HWREG(baseAddr + TMR_TIM34) = 0x0;
/* Clear the TIMMODE bits and Reset bits */
HWREG(baseAddr + TMR_TGCR) &= ~( TMR_TGCR_TIMMODE | TMR_TGCR_TIM34RS |
TMR_TGCR_TIM12RS);
/*
** Select the timer mode and disable the timer module from Reset
** Timer Plus features are enabled.
*/
HWREG(baseAddr + TMR_TGCR) |= (config &
(TMR_TGCR_TIMMODE | TMR_TGCR_TIM34RS |
TMR_TGCR_TIM12RS | TMR_TGCR_PLUSEN));
}
C6748共有4个64位定时器timer0,timer1,timer2和timer3。ti叫做64-bit
timer plus,这个叫法也是挺有意思的,ti似乎想自夸一下自家dsp的外设模块,很多模块都喜欢在平常的名字的前面或后面加点东西,表示我这个东西是加强版,比如PWM模块,ti不叫PWM,他叫EPWM,什么意思?就是增强型PWM的意思(enhanced
pwm),这里,这个定时器也不例外,因为它比常见的定时器要大了一号,所以ti管他叫plus,就跟手机一样,iphone
plus就比iphone要大上一圈,而ti的这个定时器,不仅仅是位数增加,其功能也的确比普通单片机的定时器要强大得多,所以ti这个标新立异的叫法,虽然有点哗众取宠之嫌,终究还是令人信服的。Timer0和timer1的地址如图所示:
(手册P22)
程序中TimerConfigure设置了定时器控制器TCR(timer
control register)的CLKSRC12为0,将定时器的时钟源设置为内部时钟。定时器内部时钟时钟源为pll输出的AUXCLK。
(指南P1409)
(指南P130)
(指南P131)
设置了定时器1的定时器全局控制寄存器(TGCR),将timer1设置为dual
32-bit unchained mode,并禁止tim34rs和timer12rs复位。当定时器被使能的时候,定时器计数器就会开始计数。
TimerEnable(SOC_TMR_1_REGS, TMR_TIMER34, TMR_ENABLE_CONT);使能定时器1的time34部分,禁止timer12,模式为连续模式。
(指南P1410)
TimerPeriodSet(SOC_TMR_1_REGS,TMR_TIMER34,TMR_PERIOD_32);将timer1的timer34的周期设为TMR_PERIOD_32,即(5
* 24 * 1000 * 1000)。
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮