在上一篇文章中介绍了软件中断管理与硬件中断管理,但是硬件中断的内容遗漏了一部分:iLLD下的硬件中断管理,在此进行补充。
首先说明一下中断管理代码的位置,以明确整体架构。
iLLD
| - - - IfxCpu_Irq.c + CompilerGnuc.h 软件中断管理
| - - - CompilerGnuc.h 硬件中断管理
no iLLD
| - - - cint_tc29x.c 硬件中断管理(没有软件中断管理)
直接看代码(删除了部分无关代码):
/** * \file CompilerGnuc.h */ #ifndef COMPILERGNUC_H #define COMPILERGNUC_H 1 /******************************************************************************/ #include <stddef.h> /*Linker definitions which are specific to Gnuc */ /* IFX_CFG_USE_COMPILER_DEFAULT_LINKER shall be defined in Ifx_Cfg.h * to use the default compiler linker varaibles and startup */ #ifndef IFX_CFG_USE_COMPILER_DEFAULT_LINKER /*End: Common definitions ************************************************ */ /*Start: Core 0 definitions ********************************************** */ /*C extern defintions */ #define IFXCOMPILER_CORE_LINKER_SYMBOLS(cpu) \ extern unsigned int __USTACK##cpu[]; /**< user stack end */ \ extern unsigned int __ISTACK##cpu[]; /**< interrupt stack end */ \ extern unsigned int __INTTAB_CPU##cpu[]; /**< Interrupt vector table */ \ //refer to the Label defined in linker script(.lsl) extern unsigned int __TRAPTAB_CPU##cpu[]; /**< trap table */ \ extern unsigned int __CSA##cpu[]; /**< context save area 1 begin */ \ extern unsigned int __CSA##cpu##_END[]; /**< context save area 1 begin */ #define __USTACK(cpu) __USTACK##cpu #define __ISTACK(cpu) __ISTACK##cpu #define __INTTAB_CPU(cpu) __INTTAB_CPU##cpu #define __TRAPTAB_CPU(cpu) __TRAPTAB_CPU##cpu #define __CSA(cpu) __CSA##cpu #define __CSA_END(cpu) __CSA##cpu##_END /*Wrapper macros for the tool specific definitions */ #if defined(IFX_USE_SW_MANAGED_INT) //select software or hardware management #define __INTTAB(cpu) ((unsigned int)__INTTAB_CPU##cpu | (unsigned int)0x1FE0) //software mode sets BIV to the value of int vector table's base address(defined in .lsl) + 0x1FE0(mask the PIPN's effect) and locate the single vector at intvec_255 in linker script(.lsl file).(see also the last article to know more)
#else // #define __INTTAB(cpu) __INTTAB_CPU##cpu //hardware mode sets the BIV to the int vector table's base address, which is the vector_0's address.
//these 2 different macros are used in 2 different kind of interrupt management respectly. see the BIV's assigment in CPU startup program: IfxCpu_Cstart0.c
#endif /*defined(IFX_USE_SW_MANAGED_INT) */ #define __TRAPTAB(cpu) __TRAPTAB_CPU##cpu #endif /*IFX_CFG_USE_COMPILER_DEFAULT_LINKER*/ /******************************************************************************/ #define IFX_INTERRUPT_FAST IFX_INTERRUPT #if defined(IFX_USE_SW_MANAGED_INT) #ifndef IFX_INTERRUPT #define IFX_INTERRUPT(isr, vectabNum, prio) void isr(void) //in software mode, macro IFX_INTERRUPT is just used to define a normal function. #endif #else /* *INDENT-OFF* */ #ifndef IFX_INTERRUPT #define IFX_INTERRUPT(isr, vectabNum, prio) IFX_INTERRUPT_INTERNAL(isr, vectabNum, prio) //in hardware mode, IFX_INTERRUPT is used to define a section .intvec_tc0_<prio> and a int handler, the code in this section will call the handler.refer to the example below
#endif /*defined(IFX_USE_SW_MANAGED_INT)*/
#ifndef IFX_INTERRUPT_INTERNAL
#define IFX_INTERRUPT_INTERNAL(isr, vectabNum, prio) \
__asm__ (".ifndef .intr.entry.include \n"\
".altmacro \n"\
".macro .int_entry.2 intEntryLabel, name # define the section and inttab entry code \n"\
" .pushsection .\\intEntryLabel,\"ax\",@progbits \n"\
" __\\intEntryLabel : \n"\
" svlcx \n"\
" movh.a %a14, hi:\\name \n"\
" lea %a14, [%a14]lo:\\name \n"\
" ji %a14 \n"\
" .popsection \n"\
".endm \n"\
".macro .int_entry.1 prio,vectabNum,u,name \n"\
" .int_entry.2 intvec_tc\\vectabNum\\u\\prio,(name) # build the unique name \n"\
".endm \n"\
" \n"\
".macro .intr.entry name,vectabNum,prio \n"\
" .int_entry.1 %(prio),%(vectabNum),_,name # evaluate the priority and the cpu number \n"\
".endm \n"\
".intr.entry.include: \n"\
".endif \n"\
".intr.entry "#isr","#vectabNum","#prio );\
IFX_EXTERN void __attribute__ ((interrupt_handler)) isr(); \
void isr (void)
//example of interrupt handler's installing in hardware mode:
/* IFX_INTERRUPT( IsrStm, 0, 3 )
{
//clear int flag
//increase compare value
//...
}*/
/*
||
||
\|| /
\/
*/
/*
.pushsection .intvec_tc0_3, "ax", @progbits
__intvec_tc0_3 :
svlcx movh.a %a14, hi:IsrStm
lea %a14, [%a14]lo:IsrStm
ji %a14
.popsection
extern void __attribute__ ((interrupt_handler)) IsrStm(); \
void IsrStm (void)
{
//clear int flag
//increase compare value
//...
} */
// sections predefined in linker script(.lsl):
// .inttab_tc0_000 (LCF_INTVEC0_START + 0x0) : { . = ALIGN(8) ; KEEP (*(.intvec_tc0_0)); } > pfls0
// .inttab_tc0_001 (LCF_INTVEC0_START + 0x20) : { . = ALIGN(8) ; KEEP (*(.intvec_tc0_1)); } > pfls0
// .inttab_tc0_002 (LCF_INTVEC0_START + 0x40) : { . = ALIGN(8) ; KEEP (*(.intvec_tc0_2)); } > pfls0
// .inttab_tc0_003 (LCF_INTVEC0_START + 0x60) : { . = ALIGN(8) ; KEEP (*(.intvec_tc0_3)); } > pfls0
// .inttab_tc0_004 (LCF_INTVEC0_START + 0x80) : { . = ALIGN(8) ; KEEP (*(.intvec_tc0_4)); } > pfls0
// ......
#endif
/* IFX_INTERRUPT_INTERNAL */
/* *INDENT-ON* */
#endif
/* COMPILERGNUC_H */
/* software mode VS hardware mode in installing int handler:
1.software:
(1)define isr:
IFX_INTERRUPT( IsrFunc, 0, ISR_PRIO )
{
int handle...
}
or:
void IsrFunc(void)
{
int handle...
}
(2)install isr
IfxCpu_Irq_installInterruptHandler( IsrFunc, ISR_PRIO );
2.hardware:
(1)define isr:
IFX_INTERRUPT( IsrFunc, 0, ISR_PRIO )
{
int handle...
}
needn't to install manually, built in ASM. */
至此,中断系统的管理就已经分析完了。
-----------------------------------------------------
本来想总结一下Trap的使用,不过由于Trap和中断在原理和向量表等方面非常相近,所以就不想另起一篇了,这里只大概总结一下:
1.cint_tc29x.c和IfxCpu_Trap.h/.c中都用汇编语言定义并安装了trap向量表;
2.向量表的入口地址存入了BTV寄存器中(Base Address of Trap Vector Table),BTV寄存器类似于BIV寄存器;
3.trap处理函数中都开放了钩子函数接口(Extend Hook)供开发者使用。
关于Trap的具体使用方法,参考IfxCpu_Trap.h中的使用说明。具体应用实例参考FreeRTOS移植工程。