stm32中关于NVIC_SetVectorTable函数使用的疑惑与理解
[转载]2017年12月4日14:48:29
先描述下这几天碰到的一个奇怪的问题:
一个基于stm32的工程中使用到了IAP编程,其中boot空间预留长度为0x6100,实际boot的bin文件大小为21.1KB,具体为21633Byte.我在最开始调试时对于IAP编程的app程序直接下载到单片机中,程序工作一切正常,但是在通过boot将app更新到单片机中后程序可以进入到app中,但是程序工作不正常。
最后经过查找原因,最后在代码注释中找到了问题所在:
途中划红线的部分可以看出,NVIC_SetVectorTable函数参数中的Offset必须是0x200的倍数,但是~但是我刚刚说的那个IAP中的boot空间大小为0x6100,这个值并不是0x200的整数倍,这也就是问题所在了。
=============================分割线==============================
上面找到了问题所在,那么是不是就结束了呢?很明显没有,NVIC_SetVectorTable的函数注释中知识轻描淡写的说Offset必须是0x200的倍数,但是为什么要这样它并没有进行解释。着就是目前的新问题了。
首先查看NVIC_SetVectorTable函数的实现代码,非常简单,首先是对参数进行正确性判断,然后就是对一个寄存器进行赋值。在判断参数正确性的代码中并没有找到有关于0x200的代码,那么问题肯定就在这个寄存器赋值上了。具体代码如下:
SCB->VTOR = NVIC_VectTab | (Offset & (uint32_t)0x1FFFFF80);
我们关注Offset部分,它与0x1FFFFF80进行与运算,奇怪的是这个与运算的结果只能使得Offset能够0x80的整数倍,并不是0x200。如果要是0x200,那么倒推回来那么这个地方应该是0x1FFFFE00才对,难道是stm32官方的库函数有问题?!这个真是让我有点小兴奋。我隐约感觉到问题没有这么简单,决定先看看这个寄存器相关的资料在做结论,经过查看,在周立功的《CM3技术参考手册》中的讲解NVIC章节(第90页)中发现了如下的讲解:
这个地方说明VTOR寄存器的第7到28位是用来存储偏移量的,这也就能解释为什么刚才代码里面进行与运算的是0x1FFFFF80了。
但是问题还是没有解决,为什么Offset要是0x200的整数倍呢?
对于这种与CM3系统架构相关的内容,一般都是去看《Cortex-M3权威指南》,果然,最后找到了如下解释(中文版第113页):
途中划红线的部分是关键,按照它说的方法,我打开工程的启动文件,发现其中有60个普通中断,另外有16个系统中断,一起是74个中断,由于74大于2的6次方(也就是64,),所以幂向上加1也就是2的7次方,即128,然后一个地址占用四个字节,所以得出128*4=512,也就是我苦苦寻觅的0x200。
至此最初的疑问已经解决,但是在读上面划红线的文字时,一个疑问在我脑海环绕:为什么要一定为2的整数次幂,按着划红线的示例,我在flash中就花费48*4个字节给中断向量表不就挺好么。对于这个问题目前还没有发现比较好的答案,根据我个人的理解,我觉得可能是出于以下两点原因:
1 方便扩从中断向量表
解释:比如现在需要48个中断向量那我就分配它48*4个字节空间,但是以后需要49个捏?考虑到拓展性所以还是多留空间的好
2 方便编程时的FLASH擦写
解释:给出一个Offset的相对固定的值,方便程序员在编程时提高效率,试想如果设置一个非常复杂的boot长度地址,每次修改都会浪费不少时间
当然,这两点只是我个人拙见,如果各位读者谁有好的答案,还请务必指教指教我~~
stm32中关于NVIC_SetVectorTable函数使用的疑惑与理解的更多相关文章
- STM32 中的 assert_param 函数
在学STM32的时候函数assert_param出现的几率非常大,上网搜索一下,网上一般解释断言机制,做为程序开发调试阶段时使用. 断言机制函数assert_param我们在分析库函数的时候,几乎每一 ...
- stm32中的延时函数
//粗延时函数,微秒 void delay_nus(u16 time) { u16 i=0; while(time--) { i=10; //自己定义 while(i--) ; } } //毫秒级的 ...
- 简单理解ECMAScript2015中的箭头函数新特性
箭头函数(Arrow functions),是ECMAScript2015中新加的特性,它的产生,主要有以下两个原因:一是使得函数表达式(匿名函数)有更简洁的语法,二是它拥有词法作用域的this值,也 ...
- STM32中如何对printf函数重定向
通过USART1向计算机的串口调试助手打印数据,或者接收计算机串口调试助手的数据,接下来我们现STM32工程上的printf()函数,方便用于程序开发中调试信息的打印. 方法一:使用MicroLIB库 ...
- 如果简化stm32中printf函数的使用——首先重定向
STM32单片机极简方法 使用宏定义 代替复杂的重定向printf()函数,实现串口打印.(HAL库例程)https://blog.csdn.net/wu10188/article/details/9 ...
- (二)STM32中中断优先级理解
很多人在配置STM32中断时对固件库中的这个函数NVIC_PriorityGroupConfig()——配置优先级分组方式,会很不理解,尤其是看中文翻译版的,因为中文翻译版里把这里翻译成“先占优先级和 ...
- C语言学习及应用笔记之七:C语言中的回调函数及使用方式
我们在使用C语言实现相对复杂的软件开发时,经常会碰到使用回调函数的问题.但是回调函数的理解和使用却不是一件简单的事,在本篇我们根据我们个人的理解和应用经验对回调函数做简要的分析. 1.什么是回调函数 ...
- 初识STM32中的USMART组件
今天看了usmart那部分的模块,感觉使我们stm32的学习变更加方便,你可以通过串口查看和检验你所注册过的函数. USMART配步骤1.将USMART包添加到工程中,头文件要包括path2.添加所需 ...
- stm32中assert_param的用法说明
stm32中assert_param的用法说明 首先是要知道条件判断语句 这个运算符分成三部分: (条件) ? (条件成立执行部分) :(条件不成立执行部分) 就这么简单 例如:a=(x>y ...
随机推荐
- tensorflow学习--数据加载
文章主要来自Tensorflow官方文档,同时加入了自己的理解以及部分代码 数据读取 TensorFlow程序读取数据一共有3种方法: 供给数据(Feeding): 在TensorFlow程序运行的每 ...
- Mybatis3源码笔记(八)小窥MyBatis-plus
前言 Mybatis-Plus是一个 MyBatis增强工具包,简化 CRUD 操作,在 MyBatis 的基础上只做增强不做改变,为简化开发.提高效率而生,号称无侵入,现在开发中比较常用,包括我自己 ...
- Day01_03_Java名词
java名词 SDK 软件开发工具包 JDK Java的软件开发工具包,其中包括Java虚拟机(JVM),Java运行环境(即jre),Java工具(编译器,运行工具等)和Java基础类库等. JRE ...
- Jenkins 自动触发执行的配置
1. 两种触发方式 2. jenkins 和 github 同步配置 ngrok 安装 webhook 配置 1. 两种触发条件 Jenkins 中建立的任务是可以设置自动触发,更进一步的实现自动化. ...
- 数栈运维实例:Oracle数据库运维场景下,智能运维如何落地生根?
从马车到汽车是为了提升运输效率,而随着时代的发展,如今我们又希望用自动驾驶把驾驶员从开车这项体力劳动中解放出来,增加运行效率,同时也可减少交通事故发生率,这也是企业对于智能运维的诉求. 从人工运维到自 ...
- 1.7.8- HTML合并单元格
跨行与跨列
- hdu4791水题
题意: 打印东西,给你区间和每个区间的价格,然后输入任务张数,输出最少花费.. 题解: 昨晚的小测试就有这个题目,当时蒙B了,怎么也读不懂题目,一直纠结怎么把150拆成1 ...
- PAT 乙级 -- 1010 -- 一元多项式求导
题目简述 设计函数求一元多项式的导数.(注:xn(n为整数)的一阶导数为n*xn-1.) 输入格式:以指数递降方式输入多项式非零项系数和指数(绝对值均为不超过1000的整数).数字间以空格分隔. 输出 ...
- hdu4845 状态压缩BFS
题意: 给一个n*m的矩阵,从11,走到nm,格子和格子之间可能有墙,也可能有门,有的格子上面有钥匙,相应的钥匙开相应的们,捡钥匙和开门都不需要时间,问你最少多少部能走到nm. 思路: ...
- windows-CODE注入(远程线程注入)
远程线程注入(先简单说,下面会详细说)今天整理下代码注入(远程线程注入),所谓代码注入,可以简单的理解为是在指定内进程里申请一块内存,然后把我们自己的执行代码和一些变量拷贝进去(通常是以启线程的方式) ...