- 简介
在PBL与APP程序中各有一套中断向量表,但芯片中某一时刻只会运用一个中断向量表,其原理是,在内存中,PBL向量表一般存在内存开始的位置,APP向量表存在RAM中(AT)。
当PBL运行时,把中断地址寄存器(Vector Table Offset Register)的指指向向量表PBL的地址,当PBL转到APP时,把中断地址寄存器(Vector Table Offset Register)的值指向向量表APP的地址。
NVIC(Nested Vectored interrupt controller) 嵌套向量中断控制器,用于控制功能功能。
在内核上搭载了一个异常响应系统,支持系统异常( 编号 0 ~ 15 )与外部中断( 编号 > 16 )。
- 系统异常:
中断固定前15个是系统异常,系统异常表明内核其列表如下:
介绍几个重要的系统异常
2.1. Reset
当复位后,硬件会自动把堆栈的栈顶位置放到第0个系统中断的位置并该值设置MSP,
并把reset函数的地址赋给PC指针,工程代码是从Reset函数开始执行的。
Reset函数会执行如下功能:
(待完善)
2.2. 总线异常
当总线接口传输数据时,如果回复了一个错误信号,则会产生总线异常。
可能在取指,读写数据时,及中断函数执行时的出入栈产生。
具体工况:
a. 访问地址没有存储器。
b. 设备还没有做好传输数据的准备。
对应寄存器:BusFault Address Register,指出出问题的具体地址。
BusFault Status Register:指出具体是那种总线
2.3. 内存使用异常:
常见于触犯了MPU设置的保护策略以及内存非法访问。
.访问了MPU设置范围外的地址
. 只读空间写入数据
. 用户权限下读写特权级才能访问的地址
2.4. 用法异常
.执行未定义的指令
. 无效的中断返回
2.5. Hard fault:
Hard fault会在bus,mem,usage产生且中断函数无法执行时(没有使能中断服务或者被更高优先级抢占)产生。
- 中断特性
3.1. 中断优先级:
除了reset(-3 最高), NMI(-2) 与Hard fault(-1)的优先级的固定的外,其余优先级是可编程(不能为负)的。
优先级的数值越小,其优先级越高。优先级用于中断嵌套,高优先级的中断可以打断低优先级的中断程序。
中断嵌套是当前正在执行中断例程时,系统检测到一个更高优先级的中端,这时候要立刻停止当前的中断例程,转而执行更高优先级的中断例程。
支持多层中断嵌套。
支持256级优先级,通过设置Interrupt Priority Registers该设置中段优先级(外部中断)。
3.2. 中断向量表:
中断向量表本质是一个一维数组,元素内容存储的是中断服务函数的函数地址,每个元素占4个字节,
默认情况下,中断向量表位于零地址处,如下图所示:
中断向量表偏移:
中断偏移,即是把中断向量表放到一个地址不能0的内存空间(RAM or 代码区)。有些系统中,代码区会同时保存俩份代码bootloder+Application,但每个程序都需要独立的中断向量表。
bootloder的向量表在默认位置,当程序从bootlodaer跳转到Applcation时,先偏移到应用程序中断向量表,再执行应用程序。
通过中断偏移寄存器来重新定位中断向量表,该寄存器会要求设置偏移向量表的地址。
注意:向量表的启始地址是有要求的,先求出系统总共有多少向量,再把这个数字增大到2个整次幂N,启始地址必须能被4*N这个数整除。
偏移后的中断向量表,前四个向量必须存在,前俩个用于跳转重新代码执行,后俩个因为偏移过程中,可能会出现这个异常:
地址0 主堆栈指针MSP的初始值
地址1 复位向量
地址2 NMI
地址3 hard fault
3.3. 中断产生过程:
当中断产生后,会停止当前应用程序执行转而执行服务程序,
第一步保存当前函数的状态到栈中;
第二步从中断向量表中找到对应的服务程序入口地址,进而执行中断服务。
第三步:异常返回,恢复到原有的程序。
3.4. 中断常用寄存器:
1 使能与除能寄存器
配置中断是否支持。
2 悬起与解悬寄存器
用于中断嵌套机制。
3 优先级寄存器
设置中断优先级
4 活动状态寄存器
3.5. 中断函数定义及规则:
1 中断服务函数不能传入参数;
2 中断服务函数不能有返回值;
3 进来函数简洁
4 不要使用printf函数
- Interrupt exercise on autosar(Vector)
4.1. 代码中定义中断向量表
在Vector_core.s中汇编程序定义了中断向量表,如以下格式。
可见系统异常的处理函数已经定义完毕。
外设中断的处理函数没有设置,外设中断会在程序中动态设置。
汇编程序
/Vector_core.s/
VTABLE:
.long _Stack_start /* Top of Stack for Initial Stack Pointer /
.long Reset_Handler / Reset Handler /
.long NMI_Handler / NMI Handler /
.long HardFault_Handler / Hard Fault Handler /
.long MemManage_Handler / Reserved /
.long BusFault_Handler / Bus Fault Handler /
.long UsageFault_Handler / Usage Fault Handler /
.long 0 / Reserved /
.long 0 / Reserved /
.long 0 / Reserved /
.long 0 / Reserved /
.long SVC_Handler / SVCall Handler /
.long DebugMon_Handler / Debug Monitor Handler /
.long 0 / Reserved /
.long PendSV_Handler / PendSV Handler /
.long SysTick_Handler / SysTick Handler / / 15*/
.long undefined_handler /0/
.long undefined_handler
.long undefined_handler
.long undefined_handler
.long undefined_handler
.long undefined_handler
.long undefined_handler
.long undefined_handler
.long undefined_handler
.long undefined_handler
.long undefined_handler /10/
.long undefined_handler
.long undefined_handler
.long undefined_handler
.long undefined_handler
.long undefined_handler
.long undefined_handler
.long undefined_handler
.long undefined_handler
.long undefined_handler
.long undefined_handler /20/
.long undefined_handler
.long undefined_handler
.long undefined_handler
4.2. 连接脚本文件定义中断向量表存储地址及加载方式
/链接文件/
.intc_vector : {
intc_vector_start = .;
*(.intc_vector);
intc_vector_stop = .;
. = ALIGN(4);
} > int_sram AT>flash_memory =0xFF
中断向量表编译之后会存在ROM中,该指令会指定启动时把该数据从ROM中拷贝到RAM,且第一步变量VTABLE的值为这段RAM的首地址。
4.3. 向量表偏移
把偏移后的中断向量表的地址赋值给中断向量表偏移寄存器,从而实现中断向量表的偏移。
/Startup.s/
/***************************************************************/
/ Autosar Guidance 1 - The start-up code shall initialize the /
/ base addresses for interrupt and trap vector tables. These base/
/ addresses are provided as configuration parameters or /
/ linker/locator setting. /
/*****************************************************************/
.set VTOR_REG, 0xE000ED08
/* relocate vector table to RAM /
ldr r0, =VTOR_REG
ldr r1, =VTABLE
/ ;ldr r2, =(1 << 29)
;orr r1, r2 // r1 = r1 | r2 */
str r1,[r0]
4.4. 中断常用功能
注意:所有中断相关操作,需要考虑是否关闭所有中断以及是否进入特权模式。
4.4.1. 暂停/启动 某个中断
通过设置对寄存器的对应位来开启及关闭中断,即使一个中断是disable的,这个中断发生了,这个中断会进入pending状态。
标准函数:
NVIC_DisableIRQ(id);
NVIC_EnableIRQ(id);
4.4.2. 设置中断优先级
设置中断优先级的
标准函数:
NVIC_SetPriority(id, prio);
4.4.3. 动态设置中断入口函数
(volatile uint32_t)(S32_SCB->VTOR + ((16 + irq_id) << 2)))= (uint32_t)(isr_handler))
VTOR寄存器中放的是中断向量表的启始地址,中断向量表前0~15为系统中断,16以后为外部中断。每个中断向量表占4个bytes。
4.4.4. 运行及禁止所有中断
SuspendAllInterrupts
{
__asm(“cpsid i”);
}
ResumeAllInterrupts
{
__asm(“cpsie i”);
}
Reference:
Cortex -M4 Devices Generic User Guide.pdf