基于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

相关文章

内核启动时减少log的方式

内核引导选项 内核引导选项大体上可以分为两类:一类与设备无关、另一类与设备有关。与设备有关的引导选项多如牛毛,需要你自己阅读内核中的相应驱动程序源码以获取其能够接受的引导选项。比如,如果你想知道可以向 AHA1542 SCSI 驱动程序传递哪些引导选项,那么就查看 drivers/scsi/aha1542.c 文件,一般在前面 100 行注释里就可以找到所接受的引导选项说明。大多数选项是通过"_

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2

STM32(十一):ADC数模转换器实验

AD单通道: 1.RCC开启GPIO和ADC时钟。配置ADCCLK分频器。 2.配置GPIO,把GPIO配置成模拟输入的模式。 3.配置多路开关,把左面通道接入到右面规则组列表里。 4.配置ADC转换器, 包括AD转换器和AD数据寄存器。单次转换,连续转换;扫描、非扫描;有几个通道,触发源是什么,数据对齐是左对齐还是右对齐。 5.ADC_CMD 开启ADC。 void RCC_AD

STM32内部闪存FLASH(内部ROM)、IAP

1 FLASH简介  1 利用程序存储器的剩余空间来保存掉电不丢失的用户数据 2 通过在程序中编程(IAP)实现程序的自我更新 (OTA) 3在线编程(ICP把整个程序都更新掉) 1 系统的Bootloader写死了,只能用串口下载到指定的位置,启动方式也不方便需要配置BOOT引脚触发启动  4 IAP(自己写的Bootloader,实现程序升级) 1 比如蓝牙转串口,

FreeRTOS-基本介绍和移植STM32

FreeRTOS-基本介绍和STM32移植 一、裸机开发和操作系统开发介绍二、任务调度和任务状态介绍2.1 任务调度2.1.1 抢占式调度2.1.2 时间片调度 2.2 任务状态 三、FreeRTOS源码和移植STM323.1 FreeRTOS源码3.2 FreeRTOS移植STM323.2.1 代码移植3.2.2 时钟中断配置 一、裸机开发和操作系统开发介绍 裸机:前后台系

寻迹模块TCRT5000的应用原理和功能实现(基于STM32)

目录 概述 1 认识TCRT5000 1.1 模块介绍 1.2 电气特性 2 系统应用 2.1 系统架构 2.2 STM32Cube创建工程 3 功能实现 3.1 代码实现 3.2 源代码文件 4 功能测试 4.1 检测黑线状态 4.2 未检测黑线状态 概述 本文主要介绍TCRT5000模块的使用原理,包括该模块的硬件实现方式,电路实现原理,还使用STM32类

笔记整理—内核!启动!—kernel部分(2)从汇编阶段到start_kernel

kernel起始与ENTRY(stext),和uboot一样,都是从汇编阶段开始的,因为对于kernel而言,还没进行栈的维护,所以无法使用c语言。_HEAD定义了后面代码属于段名为.head .text的段。         内核起始部分代码被解压代码调用,前面关于uboot的文章中有提到过(eg:zImage)。uboot启动是无条件的,只要代码的位置对,上电就工作,kern

STM32 ADC+DMA导致写FLASH失败

最近用STM32G070系列的ADC+DMA采样时,遇到了一些小坑记录一下; 一、ADC+DMA采样时进入死循环; 解决方法:ADC-dma死循环问题_stm32 adc dma死机-CSDN博客 将ADC的DMA中断调整为最高,且增大ADCHAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, ADC_Buffer_Size); 的ADC_Bu

Ubuntu22.04回退系统内核

文章目录 起因回退操作卸载内核禁止内核升级 起因 最近因为系统内核自动升级,导致显卡驱动检测不到,炼丹环境被破坏。无奈只能重装驱动,于是跟着手册操作发现驱动要求的是内核版本是5.15.0-25-generic,而我通过uname -r发现这时候的内核版本是6.8.0-40-generic,看来只能回退了。 我搜索了网上很多的文章,没有一篇文章能够完全解决这个问题,所以在我多次尝