资讯详情

VTOR的对齐

📅 2026/10/29 11:08:39 | 华诺云谱 👁 阅读
VTOR的对齐
最近有一个问题会导致MCU不停的reset经过调试发现是由于中断向量表被意外篡改了那是什么原因导致中断向量表被意外篡改的呢主要原因是VTOR的对齐问题接下来详细介绍一下这个问题。一开始从call stack中发现在某个中断触发后会进入hardfault回溯hardfault的堆栈信息发现是一个无效的PC值导致了hardfault这个时候去查看0x0处中断向量表对应的地址发现并没有这个无效地址那么这个无效地址是从哪里来的呢此时脑海想到了VTOR这个寄存器所以去查看了一下这个寄存器的值果然有问题VOTR的值为0x20000200所以中断向量表被重定向到了0x20000200这个区域。并且通过调试器定位到向量表重定向发生在库函数Interrupt_Initialisation(nvic_servicedata)中。通过去查看0x20000200物理区域也发现确实存在这个无效地址。所以这个无效地址是怎么来的呢并且发现Interrupt_Initialisation(nvic_servicedata)调用完之后0x0处的中断向量表被拷贝在了0x20000280开始的表中这显然与VTOR中显示的0x20000200是有出入的。此时去查看map文件发现“nvic_servicedata 0x20000280 Data”nvic_servicedata占用了0x20000280为起始地址的ram区域再一看0x20000200-0x20000280这一块区域被分配给其他变量所以真相就是MCU认为的中断向量表的起始地址是0x20000200但是中断向量被拷贝到了预留的0x20000280的nvic_servicedata区域。但是在这里有产生一个问题那就是实际的中断向量表在物理地址0x20000280这个区域但是MCU因为VTOR中为0x20000200会认为向量表在0x20000200那么应该所有的中断函数都会有问题但实际上并没有这是什么原因呢原因是Interrupt_Initialisation(nvic_servicedata)之后紧接着调用了InterruptRegister()这个库函数初始化了除16个异常之外的中断服务函数好在这个InterruptRegister()在进行初始化时是以VTOR中的20000200为基址初始化的。因此只要你没有触发16个异常中的任何一个就暂时不会有问题。这里正好也可以解释为什么MCU会reset因为hardfault的异常入口地址被更改为了0x0所以hardfault产生时程序跑飞了最后导致了watchdog reset。通过Armv8-M Architecture Reference Manual.pdf可以发现确实VTOR的最小对齐为0x80所以这里有两种可能一供应商固化在flash里面的库函数Interrupt_Initialisation有bug把后8位mask掉了二芯片设计时硬件上就把后8位mask掉了。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑