外部触发一个GPIO中断,在这个IO中断函数中调用了一个I2C写函数,但是这个I2C写函数是使用中断方式进行的,结果实现不了。
不用操作系统,请问 C6748可以进行可屏蔽中断之间的嵌套吗? 如果可以的话,怎么实现?如果不可以,请问有没有I2C查询方式的写函数?
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
外部触发一个GPIO中断,在这个IO中断函数中调用了一个I2C写函数,但是这个I2C写函数是使用中断方式进行的,结果实现不了。
不用操作系统,请问 C6748可以进行可屏蔽中断之间的嵌套吗? 如果可以的话,怎么实现?如果不可以,请问有没有I2C查询方式的写函数?
我在IO中断函数里调用stareware 库里的 IntGlobalEnable();// 使能 DSP 全局中断
来打开总中断,IIC每写一个字节都需要进一次中断的。
这样只用一次IntGlobalEnable() 可以吗? 另外需要考虑优先级的问题吗?
一般来说中断处理函数进入之前会把全局中断关掉,需要你在中断处理函数里显示的打开,才能重入。
需要测试一下,单独的能否分别进入中断?
在这基础上,观察一下中断相关的寄存器,全局的中断寄存器和I2C相关的中断寄存器,和单独的情况对比一下
我单步调试了下,确实会在中断处理函数进入之前会把全局中断关掉。单独的都可以正确执行中断处理函数。我已经在IO中断处理中我已经将全局中断又打开了,全局中断标志使能位已经置1了,我观察了一下I2C相关的寄存器和单独的情况一样,就是进不去I2C的中断处理函数。
可能是我没搞明白,怎样算显示的打开?有没有可屏蔽中断嵌套的例程可以参考一下?
实在搞不清楚自己哪里错了
如果全局中断打开了,应该是可以进去的。
你可以简化一下,看看两个GPIO中断能不能重入?
参考文档sprufe8b。(嵌套中断实现还是有点麻烦的,最好权衡一下是改一下程序结构,还是要实现中断嵌套)
5.6.2 Nested Interrupts
Generally, when the CPU enters an interrupt service routine, interrupts are disabled. However, when the
interrupt service routine is for one of the maskable interrupts (INT4-INT15), an NMI can interrupt
processing of the maskable interrupt. In other words, an NMI can interrupt a maskable interrupt, but
neither an NMI nor a maskable interrupt can interrupt an NMI.
Also, there may be times when you want to allow an interrupt service routine to be interrupted by another
(particularly higher priority) interrupt. Even though the processor by default does not allow interrupt service
routines to be interrupted unless the source is an NMI, it is possible to nest interrupts under software
control. To allow nested interrupts, the interrupt service routine must perform the following initial steps in
addition to its normal work of saving any registers (including control registers) that it modifies:
1. The contents of IRP (or NRP) must be saved
2. The contents of the PGIE bit must be saved
3. The contents of ITSR must be saved
4. The GIE bit must be set to 1
Prior to returning from the interrupt service routine, the code must restore the registers saved above as
follows:
1. The GIE bit must be first cleared to 0
2. The PGIE bit saved value must be restored
3. The contents of ITSR must be restored
4. The IRP (or NRP) saved value must be restored
Although steps 2, 3, and 4 above may be performed in any order, it is important that the GIE bit is cleared
first. This means that the GIE and PGIE bits must be restored with separate writes to CSR. If these bits
are not restored separately, then it is possible that the PGIE bit is overwritten by nested interrupt
processing just as interrupts are being disabled.
NOTE: When coding nested interrupts for the CPU, the ITSR should be saved and restored to
prevent corruption by the nested interrupt.
/**
* \file timerCounter.c
*
* \brief Sample application for timer.
*/
/*
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define SOC_TMR_0_REGS (0x01C20000)
#define SOC_TMR_1_REGS (0x01C21000)
#include "stdio.h"
#include "c6x.h"
#include "uart.h"
#include "hw_uart.h"
#include "interrupt.h"
#include "soc_OMAPL138.h"
#include "hw_syscfg0_OMAPL138.h"
#include "timer.h"
#include "lcdkOMAPL138.h"
#include "uartStdio.h"
#ifndef _TMS320C6X
#include "cpu.h"
#endif
/******************************************************************************
** INTERNAL MACRO DEFINITIONS
*******************************************************************************/
#define STR_LEN (13)
#define TMR_PERIOD_LSB32 (0x07FFFFFF)
#define TMR_PERIOD_MSB32 (0x0)
/******************************************************************************
** INTERNAL FUNCTION PROTOTYPES
*******************************************************************************/
static void TimerIsr(void);
static void TimerSetUp64Bit(void);
static void Timer3SetUp64Bit(void);
static void TimerIntrSetUp(void);
/******************************************************************************
** INTERNAL VARIABLE DEFINITIONS
*******************************************************************************/
static unsigned char cntArr[9] = {'8', '7', '6', '5', '4', '3', '2', '1', '0'};
static volatile unsigned int secCnt = 0;
static volatile unsigned int flagIsrCnt = 0;
/******************************************************************************
** FUNCTION DEFINITIONS
*******************************************************************************/
int main(void)
{
/* Set up the UART2 peripheral */
UARTStdioInit();
/* Set up the Timer2 peripheral */
TimerSetUp64Bit();
Timer3SetUp64Bit();
/* Set up the AINTC to generate Timer2 interrupts */
TimerIntrSetUp();
/* Enable the timer interrupt */
TimerIntEnable(SOC_TMR_2_REGS, TMR_INT_TMR12_NON_CAPT_MODE);
TimerIntEnable(SOC_TMR_3_REGS, TMR_INT_TMR12_NON_CAPT_MODE); // Add by Tony
#ifndef _TMS320C6X
/* Switch to non privileged mode; This is done for demonstration purpose */
CPUSwitchToUserMode();
#endif
/* Send the first String */
UARTPuts("Tencounter: 9", -1);
/* Start the timer. Characters from cntArr will be sent from the ISR */
TimerEnable(SOC_TMR_2_REGS, TMR_TIMER12, TMR_ENABLE_CONT);
TimerEnable(SOC_TMR_3_REGS, TMR_TIMER12, TMR_ENABLE_CONT); // add by Tony
/* make sure all the characters from cntArray from ISR */
while(secCnt < 9)
{
/* Replace previous number each time the timer interrupt occurs */
if(flagIsrCnt)
{
UARTPutc('\b');
UARTPutc(cntArr[secCnt]);
secCnt++;
flagIsrCnt = 0;
}
}
/* Disable the timer. No more timer interrupts */
// TimerDisable(SOC_TMR_2_REGS, TMR_TIMER12);
/* Halt the program */
while(1);
}
/*
** Timer Interrupt Service Routine
*/
static void TimerIsr(void)
{
/* Disable the timer interrupt */
// TimerIntDisable(SOC_TMR_2_REGS, TMR_INT_TMR12_NON_CAPT_MODE);
#ifdef _TMS320C6X
/* Clear interrupt status in DSPINTC */
// IntEventClear(SYS_INT_T64P2_TINTALL);
#else
/* Clear the interrupt status in AINTC */
IntSystemStatusClear(SYS_INT_TIMR2_ALL);
#endif
TimerIntStatusClear(SOC_TMR_2_REGS, TMR_INT_TMR12_NON_CAPT_MODE);
printf("timer 2.\n");
/* Signal application to print a new character */
flagIsrCnt = 1;
/* Enable the timer interrupt */
// TimerIntEnable(SOC_TMR_2_REGS, TMR_INT_TMR12_NON_CAPT_MODE);
}
// add by Tony for nested interrupt example
static void Timer3Isr(void)
{
unsigned int old_csr;
unsigned int old_irp;
/* Disable the timer interrupt */
TimerIntDisable(SOC_TMR_3_REGS, TMR_INT_TMR12_NON_CAPT_MODE);
#ifdef _TMS320C6X
/* Clear interrupt status in DSPINTC */
// IntEventClear(SYS_INT_T64P2_TINTALL); // not necessary to clear.
#else
/* Clear the interrupt status in AINTC */
IntSystemStatusClear(SYS_INT_TIMR2_ALL);
#endif
TimerIntStatusClear(SOC_TMR_3_REGS, TMR_INT_TMR12_NON_CAPT_MODE);
printf("Save INT context for nest.\n");
/*Protect context for interrupt nest */
old_irp=IRP;
old_csr = CSR;
CSR = (old_csr | 1);
while(!flagIsrCnt); //wait timer 2 interrupt.
/* Signal application to print a new character */
flagIsrCnt = 0;
CSR = old_csr;
IRP = old_irp;
printf("Restored INT context.\n");
/* Enable the timer interrupt */
TimerIntEnable(SOC_TMR_3_REGS, TMR_INT_TMR12_NON_CAPT_MODE);
}
/*
** Setup the timer for 64 bit mode
*/
static void TimerSetUp64Bit(void)
{
/* Configuration of Timer */
TimerConfigure(SOC_TMR_2_REGS, TMR_CFG_64BIT_CLK_INT);
/* Set the 64 bit timer period */
TimerPeriodSet(SOC_TMR_2_REGS, TMR_TIMER12, TMR_PERIOD_LSB32);
TimerPeriodSet(SOC_TMR_2_REGS, TMR_TIMER34, TMR_PERIOD_MSB32);
}
// Add by Tony to configure timer 3 for nested interrupt.
static void Timer3SetUp64Bit(void)
{
/* Configuration of Timer */
TimerConfigure(SOC_TMR_3_REGS, TMR_CFG_64BIT_CLK_INT);
/* Set the 64 bit timer period */
TimerPeriodSet(SOC_TMR_3_REGS, TMR_TIMER12, 0x05FFFFFF);
TimerPeriodSet(SOC_TMR_3_REGS, TMR_TIMER34, TMR_PERIOD_MSB32);
}
/*
** Set up the ARM Interrupt Controller for generating timer interrupt
*/
static void TimerIntrSetUp(void)
{
#ifdef _TMS320C6X
/* Initialize the DSPINTC */
IntDSPINTCInit();
/* Register the Timer ISR */
IntRegister(C674X_MASK_INT4, TimerIsr);
IntRegister(C674X_MASK_INT5, Timer3Isr); // Add by Tony for nested interrupt example.
/* Map Timer interrupts to DSP maskable interrupt */
IntEventMap(C674X_MASK_INT4, SYS_INT_T64P2_TINTALL);
IntEventMap(C674X_MASK_INT5, 86); // Add by Tony for nested interrupt example.
/* Enable DSP interrupt in DSPINTC */
IntEnable(C674X_MASK_INT4);
IntEnable(C674X_MASK_INT5); // Add by Tony for nested interrupt example.
/* Enable DSP interrupts */
IntGlobalEnable();
#else
/* Initialize AINTC and register timer interrupt */
IntAINTCInit();
/* Register the Timer ISR */
IntRegister(SYS_INT_TIMR2_ALL, TimerIsr);
/* Set the channel number for Timer interrupt, it will map to IRQ */
IntChannelSet(SYS_INT_TIMR2_ALL, 2);
/* Enable IRQ for ARM (in CPSR)*/
IntMasterIRQEnable();
/* Enable AINTC interrupts in GER */
IntGlobalEnable();
/* Enable IRQ in AINTC */
IntIRQEnable();
/* Enable timer interrupts in AINTC */
IntSystemEnable(SYS_INT_TIMR2_ALL);
#endif
}
/***************************** End Of File ***********************************/
这个也是TI的技术支持提供的程序,while(!flagIsrCnt); //wait timer 2 interrupt.这边感觉是“蓄谋已久等待”另外一个中断来打断他,然后立刻进行restore操作,我就是想问,如果中断服务程序A,被打断了,去执行B,等B执行完了,如何再回到A呢?
victor sun1 说:就是CSR = old_csr;IRP = old_irp;这两句话,需要在被打断的中断服务子程序的什么位置填上呢?
你不是看了这个贴子吗? 感觉你进入一个误区了。
实现情况时,在进入ISR A后,通过配置使能“高优先级B”的中断,放到GIE后,这里这个“高优先级中断B“如果来了就可以响应了,但是至于这个中断B是否每次都会在进入这个ISR A时来,是不确定的,这本来是随机的。所以这时ISR A该干嘛干嘛,处理完后,再恢复就好了。
如果这时中断B来了,那就跟正常响应中断一样进入B,退出B ISR后,回到 A ISR继续往下运行。
理一理吧,已经够清楚了, 所有人都是看的这同一段说明。
是的。
只是
这句话我没太懂。victor sun1 说:如果有其他可屏蔽中断来打断ISR A的话,
总之,是因为进入ISR后,全局中断自动关闭了。所以如果想要让别的中断可以打断当前中断,那么就必需把全局中断打开,又由于中断的返回地址是由IRP保存的,所以IRP里的返回地址也要另做保存,这时如果“高优先级“的中断来了,则跟正常响应中断一样,进入相应的ISR,处理完后,通过IRP返回到前一个中断内的代码继续往下运行,在退出中断前,恢复IRP的返回地址,以及中断使能情况。 当然在前面的中断配置完了,没有来”高优先级“的中断,那么处理完后,同样恢复前面保存的上下文,再退出ISR就好了。
嵌套配置是为了当有”优先级“中断来时,可以响应,如果没来,继续往下运行,退出,什么也不影响。