3. S32K中断向量表重映射与外部中断
任务说明
本案例在 S32K1xx(以 S32K144 为例)上完成两件事:把中断向量表从 Flash 重定位到 RAM(VTOR 指向 RAM 中的向量表副本),并配置 PTB2 为下降沿触发的外部中断,在中断服务函数中翻转 LED。验证方式:给 PTB2 一个下降沿(按键按下),观察 LED 状态翻转。
关键点
- 向量表重映射:先把 Flash 中的向量表整体拷贝到 RAM,再写
SCB->VTOR指向 RAM 副本。RAM 向量表需按 512 字节对齐(Cortex-M4 要求)。 - PTB2 对应 PORTB 的
PORTB_IRQn(IRQ 号 43),需在 RAM 向量表中把该表项指向自定义 ISR。 - 下降沿触发:PORT 配置
PORT_PCR_IRQC(0xA)(下降沿中断),并使能 NVIC 对应中断。 - LED 使用 PTD0(S32K144 EVB 板载 RGB 的蓝/绿通道之一,按实际板卡调整引脚)。
完整代码(main.c)
#include "S32K144.h"
#define VECTOR_TABLE_SIZE (48u * 4u) /* 前 48 个表项足够覆盖 PORTB_IRQn(43) */
#define RAM_VECTOR_BASE 0x20000000u /* 512B 对齐 */
extern uint32_t __Vectors[]; /* 链接脚本提供的 Flash 向量表起始 */
void PORTB_IRQHandler(void);
/* 把 Flash 向量表拷到 RAM,并把 PORTB 表项替换为自定义 ISR */
void RemapVectorTable(void)
{
uint32_t *ramVec = (uint32_t *)RAM_VECTOR_BASE;
for (uint32_t i = 0; i < VECTOR_TABLE_SIZE / 4u; i++) {
ramVec[i] = __Vectors[i];
}
ramVec[16 + 43] = (uint32_t)PORTB_IRQHandler; /* 16 为系统异常数,43 为 PORTB_IRQn */
SCB->VTOR = RAM_VECTOR_BASE; /* 重映射 */
__DSB();
__ISB();
}
/* PTB2 下降沿中断:翻转 PTD0 上的 LED */
void PORTB_IRQHandler(void)
{
if (PORTB->ISFR & (1u << 2)) { /* 确认是 PTB2 触发 */
PORTB->ISFR = (1u << 2); /* 写 1 清标志 */
PTD->PTOR ^= (1u << 0); /* 翻转 LED */
}
}
void LED_Init(void)
{
PCC->PCC_PORTD |= PCC_PCC_PORTD_CGC_MASK;
PORTD->PCR[0] = PORT_PCR_MUX(1); /* PTD0 作 GPIO */
PTD->PDDR |= (1u << 0); /* 输出 */
PTD->PSOR = (1u << 0); /* 初始灭 */
}
void PTB2_EXTI_Init(void)
{
PCC->PCC_PORTB |= PCC_PCC_PORTB_CGC_MASK;
PORTB->PCR[2] = PORT_PCR_MUX(1) /* GPIO */
| PORT_PCR_IRQC(0xA) /* 下降沿中断 */
| PORT_PCR_PE_MASK /* 使能上拉 */
| PORT_PCR_PS_MASK;
NVIC_EnableIRQ(PORTB_IRQn);
}
int main(void)
{
RemapVectorTable();
LED_Init();
PTB2_EXTI_Init();
for (;;) { __asm volatile ("wfi"); }
}
运行与验证
- 用 S32 Design Studio 新建 S32K144 工程,把上述
main.c替换默认文件;确认链接脚本中__Vectors符号存在(S32DS 默认提供)。 - 编译、下载到目标板,复位运行。
- 用杜邦线把 PTB2 短接到 GND 再松开,制造一个下降沿;或按下接在 PTB2 上的按键。
- 观察 PTD0 上的 LED:每次下降沿应翻转一次状态。若 LED 不翻转,检查 PTB2 是否已上拉、NVIC 是否使能、
SCB->VTOR是否等于0x20000000。
常见问题
- RAM 向量表未按 512 字节对齐会导致 VTOR 写入被硬件忽略或行为异常,务必使用对齐地址。
- 若只拷贝前 48 项,需保证后续不会触发编号更大的中断;否则应拷贝完整向量表。
- ISR 中必须清
ISFR对应位,否则中断会反复进入。