基于STM32看Cotex-M内核中断向量表重定向

2024-05-25 04:20

本文主要是介绍基于STM32看Cotex-M内核中断向量表重定向,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录


中断向量表重定向在芯片IAP(或OTA)升级过程中,是不可避免的问题。
在Cotex-M3/M4内核中有向量表偏移寄存器VTOR
在Cortex-M0内核中没有向量表偏移寄存器,但在Cortex-M0+内核中有
我们先分析有VTOR寄存器的情况,然后再看没有的情况

ARM处理器的启动流程

可以参考基于STM32看Cortex-M内核相关的一些底层知识文章中的“Cortex-M芯片启动详细过程”章节

嵌套中断向量控制器NVIC

在《ARM Cortex-M3与Cortex-M4权威指南》中的4.5.2章节中有如下描述:
当异常发生时,处理器需要确定相应的异常处理入口位置。对于ARM7TDMI等ARM处理器,这一操作由软件实现,**Cortex-M处理器则会从存储器的向量表中自动定位异常处理的入口。**因此,这样也降低了从异常产生到异常处理执行间的延时。
4.5.3章节有如下描述:
当异常事件产生且被处理器内核接受后,相应的异常处理就会执行。要确定异常处理的起始地址,处理器利用了一种向量表机制。向量表为系统存储器内的字数据数组,每个元素都代表一个异常类型的起始地址,如图4.26所示。向量表是可以重定位的,重定位由NVIC中名为向量表偏移寄存器(VTOR)的可编程寄存器控制。复位后,VTOR默认为0,向量表则位于地址0x0处。
在这里插入图片描述
通过上面的描述我们可以知道,当中断触发时,处理器会到0x0+VTOR的位置寻找向量表,并跳转到对应的异常处理函数。所以我们的代码中有多个向量表也是可以的,只需要动态改变VTOR寄存器的值即可。

向量表和向量表重定位

详细内容请看《ARM Cortex-M3与Cortex-M4权威指南》7.5章节。
一版来说,起始地址(0x00000000)处应为启动存储器,它可以为Flash存储器或ROM设备,而且在运行时不能对他们进行修改。不过,有些应用可能需要在运行时修改或定义向量表,为了进行这种处理,Cortex-M3和Cortex-M4处理器实现了一种名为向量表重定位的特性。

使用VTOR偏移不在起始位置时需要注意对齐问题:
在使用VTOR时,需要将向量表大小扩展为下一个2的整数次方,且新向量表的基地址必须要对齐到这个数值。
在这里插入图片描述
在这里插入图片描述

IAP过程中的重定向

在这里插入图片描述
正常的执行过程为,启动时先执行Boot程序中的Reset_Handler函数然后经过分散加载,初始化堆栈,初始化C库后跳转到用户main函数执行,其中监测到不许要升级则通过跳转函数(设置主栈指针,将App中Reset_Handler函数的地址作为执行地址)跳转到App程序中的Reset_Handler函数,然后再经过分散加载,初始化堆栈,初始化C库等操作后跳转到用户main函数中执行,在main函数开始位置首先要修改VTOR的值,则后续的中断触发都会跳转到App代码中对应的中断服务函数中。

没有VTOR寄存器的情况

对于STM32F0系列的单片机使用的是Cortex-M0内核,是没有VTOR寄存器的。这种情况可以通过将中断向量表复制到RAM起始位置,然后通过SYSCFG系统配置控制器中的SYSCFG_CFGR1寄存器中的MEM_MODE位控制将SRAM空间映射到0x00000000位置。然后中断触发的时候处理器将会在起始地址寻找中断向量表并确定入口位置。
在这里插入图片描述

在这里插入图片描述
ST F0参考手册中也讲述了这种重定向方法,这也是STM32F0系列单片机实现IAP升级的方法,需要注意的是:中断向量表一定要复制到SRAM的起始位置才可以,因为映射后也是要到起始位置查找中断向量表。
在这里插入图片描述

#if defined(__CC_ARM)
__IO uint32_t VectorTable[48] __attribute__((at(0x20000000)));
#endifvoid iap_appInit(void) {for(uint8_t i = 0; i < 48; ++i) {VectorTable[i] = *(__IO uint32_t*)(APP_START_ADDR + (i<<2));}/* Enable the SYSCFG peripheral clock */__HAL_RCC_SYSCFG_CLK_ENABLE();/* Remap SRAM at 0x0000000 */__HAL_SYSCFG_REMAPMEMORY_SRAM();
}

在这里插入图片描述
这里要注意的是IRAM1的配置处要将前面0xC0大小的空间流出来给代码中定义的中断向量表数组,否则编译的时候会报错。

这篇关于基于STM32看Cotex-M内核中断向量表重定向的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1000469

相关文章

【Linux进阶】UNIX体系结构分解——操作系统,内核,shell

1.什么是操作系统? 从严格意义上说,可将操作系统定义为一种软件,它控制计算机硬件资源,提供程序运行环境。我们通常将这种软件称为内核(kerel),因为它相对较小,而且位于环境的核心。  从广义上说,操作系统包括了内核和一些其他软件,这些软件使得计算机能够发挥作用,并使计算机具有自己的特生。这里所说的其他软件包括系统实用程序(system utility)、应用程序、shell以及公用函数库等

零基础STM32单片机编程入门(一)初识STM32单片机

文章目录 一.概要二.单片机型号命名规则三.STM32F103系统架构四.STM32F103C8T6单片机启动流程五.STM32F103C8T6单片机主要外设资源六.编程过程中芯片数据手册的作用1.单片机外设资源情况2.STM32单片机内部框图3.STM32单片机管脚图4.STM32单片机每个管脚可配功能5.单片机功耗数据6.FALSH编程时间,擦写次数7.I/O高低电平电压表格8.外设接口

国产数据库 - 内核特性 - CloudberryDB中的Runtime Filter

国产数据库 - 内核特性 - CloudberryDB中的Runtime Filter 今年5月份GreenPlum官方将GitHub仓库代码全部删除,各个分支的issues和bugs讨论等信息全部清除,仅将master分支代码进行归档。对于国内应用GPDB的用户来说,这是一个挑战性事件,对与后期维护、升级等都变得非常困难。有幸HashData开源了基于GP衍生版本CloudberryDB版本,

STM32单片机PWR电源控制详解

文章目录 1. PWR概述 2. 电源结构框图 3. 上电复位和掉电复位 4. 可编程电压监测器 5. 低功耗模式 6. 模式选择 6.1 睡眠模式 6.2 停止模式 6.3 待机模式 7. 代码示例 1. PWR概述 PWR(Power Control)电源控制,负责管理STM32内部的电源供电部分,可以实现可编程电压监测器和低功耗模式的功能。 可编程电压监测器

java NIO 缓存区之内核空间、用户空间和虚拟地址

IO是基于缓存区来做的,所谓的输入和输出就是从缓存区中移入和移出数据。以IO输入为例,首先是用户空间进程向内核请求某个磁盘空间数据,然后内核将磁盘数据读取到内核空间的buffer中,然后用户空间的进程再将内核空间buffer中的数据读取到自身的buffer中,然后进程就可以访问使用这些数据。     内核空间是指操作系统内核运行的空间,是为了保证操作系统内核的能够安全稳定地运行而为内核专

STM32学习之一:什么是STM32

目录 1.什么是STM32 2.STM32命名规则 3.STM32外设资源 4. STM32的系统架构 5. 从0到1搭建一个STM32工程 学习stm32已经很久了,因为种种原因,也有很久一段时间没接触过stm32了。等我捡起来的时候,发现很多都已经忘记了,重新捡起来吧。 每次谈到stm32如何如何,那么该如何解释什么是stm32呢? 1.什么是STM32 stm32

几何内核开发-实现自己的NURBS曲线生成API

我去年有一篇帖子,介绍了NURBS曲线生成与显示的实现代码。 https://blog.csdn.net/stonewu/article/details/133387469?spm=1001.2014.3001.5501文章浏览阅读323次,点赞4次,收藏2次。搞3D几何内核算法研究,必须学习NURBS样条曲线曲面。看《非均匀有理B样条 第2版》这本书,学习起来,事半功倍。在《插件化算法研究平台

Redhat7.2上编译Linux内核源码

下载linux源码包:https://git.kernel.org/pub/scm/virt/kvm/kvm.git/snapshot/kvm-4.17-1.tar.gz (这是包含kvm开发版本的linux内核源码)解压到源码根目录下执行make allyesconfig生成编译的配置文件查看Documentation目录下的Changes文件,把需要的工具都安装好,通过以下命令把工具安装好:y

STM32学习 修改系统主频

前面时钟树的学习说明单片机的主频是可以修改的,那么怎么更改系统的主频,这里做一个简单的介绍。首先要明白,单片机的程序是如何运行,这里简单说明一下。 对应的代码在startup_stm32....文件里面,这里是复位程序的汇编代码。 复位子程序是系统上电后第一个执行的程序,调用 SystemInit 函数初始化系统时钟,然后调用 C 库函数 _mian,最终调用 main 函数去到 C

使用J-Link Commander查找STM32死机问题

接口:PA13,PA14,请勿连接复位引脚。 输入usb命令 这里我已经连接过了STM32F407VET6了。 再输入connect命令 这里我已经默认选择了SWD接口,4000K速率。 可以输入speed 4000命令选择4000K速率: 写一段崩溃代码进行测试: void CashCode(void){*((volatile uint32_t*) 0x080FFFFF)