因为TI官方给出的28335的例子中,对中断向量表的定义为
// Define Vector Table:
struct PIE_VECT_TABLE {
// Reset is never fetched from this table.
// It will always be fetched from 0x3FFFC0 in
// boot ROM
PINT PIE1_RESERVED;
PINT PIE2_RESERVED;
PINT PIE3_RESERVED;
PINT PIE4_RESERVED;
PINT PIE5_RESERVED;
PINT PIE6_RESERVED;
PINT PIE7_RESERVED;
PINT PIE8_RESERVED;
PINT PIE9_RESERVED;
PINT PIE10_RESERVED;
PINT PIE11_RESERVED;
PINT PIE12_RESERVED;
PINT PIE13_RESERVED;
// Non-Peripheral Interrupts:
PINT XINT13; // XINT13 / CPU-Timer1
PINT TINT2; // CPU-Timer2
PINT DATALOG; // Datalogging interrupt
PINT RTOSINT; // RTOS interrupt
PINT EMUINT; // Emulation interrupt
PINT XNMI; // Non-maskable interrupt
PINT ILLEGAL; // Illegal operation TRAP
PINT USER1; // User Defined trap 1
PINT USER2; // User Defined trap 2
PINT USER3; // User Defined trap 3
PINT USER4; // User Defined trap 4
PINT USER5; // User Defined trap 5
PINT USER6; // User Defined trap 6
PINT USER7; // User Defined trap 7
PINT USER8; // User Defined trap 8
PINT USER9; // User Defined trap 9
PINT USER10; // User Defined trap 10
PINT USER11; // User Defined trap 11
PINT USER12; // User Defined trap 12
// Group 1 PIE Peripheral Vectors:
PINT SEQ1INT;
PINT SEQ2INT;
PINT rsvd1_3;
PINT XINT1;
PINT XINT2;
PINT ADCINT; // ADC
PINT TINT0; // Timer 0
PINT WAKEINT; // WD
...}(只列出到了group1,到这里就够了)因为TI的官方手册中《TMS320x2833x, 2823x System Control and Interrupts Reference Guide》给出的中断向量排布是通过TI源码对TMS320f28335中断机制的进一步理解
就在这个地方需要注意的是Reset和INT1~INT12一共13个向量是没有使用的,这里只是作为一个32位无符号整数占据地址位置,而在代码中程序员没有这么写,直接是PIE1_RESERVED~PIE13_RESERVED,这让我一开始看代码的时候产生了很大困惑,因为文档中说Reset向量复位的时候是不从这个表中取的,是从boot ROM中取的,所以Reset向量这里就没写,但是CMD文件中PIE_VECT : origin = 0x000D00, length = 0x000100,中断向量表的起始地址是 0x000D00,如果不定义Reset向量,那所有后面的向量不就向前面移动了两个地址,后来我为了地址对应就在向量表定义中加入了一行 PINT Reset_RESERVED,结果编译报错,好像是CMD中分配的地址重叠了,因为多加了一项,我就把向量表中的最后一项注释掉了(group12的最后一项),编译过了,但是发现进不了指定中断(我这里用的是TI例程中看门狗中断的例子),只能进入中断向量表初始化时指定的默认中断(就是一个NOP空操作,这里多说一句,为什么一定要初始化中断向量表,因为一旦有中断发生,没有初始化中断向量表,中断向量表中的地址值是随机的,这样程序就跳转到一个随机地址,程序就跑飞了,所以开始给所有中断向量赋一个指定的地址值,一旦发生中断,程序就跳到那个地址去执行,这里TI给的代码中,这个初始化地址就是一个只包含一个NOP指令的函数不对程序产生影响),继续说我们的调试,我发现CPU是从0x0D4E这个地址中取出的中断函数(看PIECTRL Register的1~15位就知道了,第0位是PIE使能位),而手册上说WAKEINT这个中断也确实是在0x0D4E这个地址上,而我们指定的中断服务函数PieVectTable.WAKEINT = &wakeint_isr却在下一个地址0x0D50的位置上(中断向量表每条中断向量都是32位的)。这我就基本明白了,一旦发生某个中断,CPU是去某个固定地址取中断向量,这是CPU硬件自动完成的,不是软件可以改变的,比如这个例子,只要看门狗中断发生,CPU就去0x0D4E这个地址去取中断向量。
好吧现在我们继续批判TI偷懒的程序员给我们带来这么大的困扰,其实他并没有遗漏Reset这个向量,仔细数数代码中PIE1_RESERVED~PIE13_RESERVED一共13个占位地址,看手册中只用INT1~INT12是没有使用的,INT13是外部中断13或者CPU Timer1中断,好吧INT1~INT12+Reset中断一共13个未用中断,TI的程序员你赢了,正好和PIE1_RESERVED~PIE13_RESERVED对应,这样地址也是正好对应的,一切问题都没有。不过他这种坑爹写法,让我浪费了好几个小时调试,不过也让我进一步认清了中断机制的真面目。就算扯平了吧。