dsPIC33C系列的中断向量表(IVT)位于程序存储器中,起始单元地址是0x000004h(0x000000~0x000002是复位入口地址)。IVT包含6个不可屏蔽陷阱向量和最多246个中断源。一般来说,每个中断源都有自己的中断向量。每个中断向量都包含一个24位宽的地址。每个中断向量单元中编程的值是其相关的中断服务程序(ISR)的起始地址。如下图所示。
6个不可屏蔽中断向量表,它们的CPU优先级不可设置,优先级分别为9-15。
中断向量根据其自然优先级区分优先顺序(在没有分配优先级的情况下,优先级0-7可设置),自然优先级与中断向量在向量表中的位置有关。一般来说,较低地址的中断向量具有较高的自然优先级。例如在下列向量表中,与向量编号为8(外部中断0)相关的中断比其他向量地址的中断具有更高的自然优先级。
中断向量表的重映射
dsPIC33C共有256个中断源,每一个中断源对应一个中断向量地址,且每个中断向量地址是固定不能改变的。通常,我们在BootLoader中不使用中断,只在应用程序中使用中断功能。当禁用CodeGuard时,大多数dsPIC33器件只有一个IVT表。对于具有单个IVT表的MCU ,需要在中断向量表中设置跳转偏移量(也就是重映射,在应用程序空间中复制IVT表),让中断产生后能跳转到应用程序中。
在用户应用程序空间中的固定地址处创建预定义的应用程序中断重映射表。该表中的每个条目都包含一个GOTO指令,该指令跳至该中断的实际应用程序中断服务程序(ISR)。发生中断时,这些中断将自动跳到中断处理函数。
下面是中断的流程以及它在应用程序中断服务程序中的结束方式
(1)发生UART1中断;
(2)PC指针跳转到硬件中断向量表中指定的地址(此处地址假设为0x4000),这是应用程序中断重映射表中的固定位置;
(3)应用程序中断重映射有一个指向实际应用程序中断服务程序函数的GOTO指令。
上述中断跳转的方法有一定缺点,就程序存储空间而言,其成本可能更高。每个中断在dsPIC33器件上需要2条指令(6个字节,GOTO占两个指令)。在dsPIC33C器件上有256个中断。如果每个中断都需要跳转,则可能需要超过1KB的内存。此外,大多数应用程序代码仅使用几个中断源,在这种情况下,应用程序中断重映射表中未使用的中断入口只是浪费空间。
一种“压缩”或“减小”此表大小的方法是确定将在此设计产品系列中使用或可能使用哪些中断。然后仅在“应用程序中断重映射表”中创建入口,并将这些入口放置在“应用程序中断重映射表”的开头开始的连续位置。有了此应用程序可以支持的中断“列表”,Bootloader就可以获取该列表,并针对识别出的中断,使用简化的应用程序中断重映射表中相应入口的地址在IVT中编程其中断。此外,对于未使用的中断,我们可以在应用程序空间中创建一个“默认中断服务程序”,并在应用程序中断重映射表中创建一个入口,同时为默认值创建一个ISR。这将通过默认的中断服务程序将所有其他中断跳转到应用程序。这样,如果应用程序稍后决定需要一个以前不需要的新中断,则它仍然可以通过重新映射的默认处理程序访问该中断。
选择哪些中断跳转到它们自己的ISR,哪些跳转到默认ISR可能是一项困难的任务,因为Bootloader可能不知道哪些中断正在使用或可以使用。此外,由于产品的生命周期以年为单位,产品功能可能会随着时间而改变。 因此,如果闪存空间不是主要考虑因素,那么即使应用程序的外设具有独立ISR的可能性很小,Bootloaer区也应将其跳转给独立的ISR,只有当外设在项目开发中完全确定不会使用,或者不需要使用中断,或者可以使用默认的ISR中断时,才将外设跳转到默认的ISR。
使用上述方法,最终中断跳转方案如下所示。 在此示例中,应用程序仅需要两个专用的ISR(例如UART1和SPI1)。 因此,这两个外设中的每一个在应用程序中断重映射表中都有一个专用入口,而应用程序中断重映射表中的其他入口都采用默认中断ISR。 所有可以共享一个公共ISR的“未使用的”或外设,其IVT入口都指向应用程序中断重新映射表中的这个入口,这也是重新映射表中的第一个地址。 通过使用默认的中断入口,可以大大减小应用程序中断重映射表的大小。
在上面的示例中,应用程序未使用外设A,B和C,但是将它们的中断转发给应用程序默认处理程序,以防万一以后需要它们时使用。
在boot区需要中断的情况下,IVT不必将该中断跳转至应用程序(注意:在具有备用中断表的设备-AIVT上,这不是必需的)。 在这种情况下,Bootloader将使用来自IVT的中断。 在下面的示例中,比如Bootloader需要在中断模式下使用UART2。 在这种情况下,IVT不会将中断转发给应用程序,而是决定将中断保留在Bootloader。