问题背景

项目使用STM32F030,需要通过IAP进行固件升级,在FLASH里面要烧录两份代码:一个Boot loader,一个用户应用程序APP。在开发应用程序APP时,外设中断不能正确响应进到对应的中断函数。

解决方案

此原因是在Cortex-M3内核的MCU上可以通过设置SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;该寄存器的值来实现中断向量表的重定义。但在STM32F0xx系列以Cortex-M0为内核的单片机中却怎么也找不到这个设置中断向量表的寄存器,用户可以通过以下方法来实现中断向量表重定义。(注意这种情况不止在STM32F0xx系列芯片上存在,在其他一些国产32位Cortex-M0内核也有此问题,比如MM32L073,在SMT32新的Cortex-M0+内核的芯片已经提供了SCB->VTOR这个寄存器)

在STM32F030CC的Reference manual中找到以下说明:

Physical remap

Once the boot mode is selected, the application software can modify the memory accessible in the code area.This modification is performed by programming the MEM_MODE bits in the SYSCFG configuration register 1 (SYSCFG_CFGR1). Unlike Cortex® M3 and M4, the M0 CPU does not support the vector table relocation. For application code which is located in a different address than 0x0800 0000, some additional code must be added in order to be able to serve the application interrupts. A solution will be to relocate by software the vector table to the internal SRAM:

• Copy the vector table from the Flash (mapped at the base of the application load address) to the base address of the SRAM at 0x2000 0000.

• Remap SRAM at address 0x0000 0000, using SYSCFG configuration register 1.

• Then once an interrupt occurs, the Cortex®-M0 processor will fetch the interrupt handler start address from the relocated vector table in SRAM, then it will jump to execute the interrupt handler located in the Flash.

This operation should be done at the initialization phase of the application. Please refer to AN4065 and attached IAP code from www.st.com for more details.

翻译如下:

物理重映射

一旦选择了引导模式,应用软件就可以修改代码中可访问的内存区域。这个通过对SYSCFG配置寄存器1(SYSCFG_CFGR1)中的MEM_MODE模式位进行编程来执行修改。与Cortex®M3和M4不同,M0
CPU不支持向量表重定位。对于位于不同于0x0800
0000的地址的应用程序代码,必须添加一些附加代码,以便能够为该应用程序中断提供服务。解决方案是通过软件将矢量表重新定位到内部SRAM:

• 将矢量表从闪存(映射到应用程序加载地址的基地址)复制到SRAM的基地址0x2000 0000。

• 使用SYSCFG配置寄存器1在地址0x0000 0000处重新映射SRAM。

• 一旦发生中断,Cortex®-M0处理器将从SRAM中重新定位的向量表中获取中断处理程序的起始地址,然后跳转执行闪存中的中断处理程序。

此操作应在应用程序的初始化阶段完成。请参考AN4065和随附的IAP代码www.st.com更多细节。

基本思想:
1、将中断向量表放入到RAM的起始地址(只需要在应用程序中保留RAM起始地址开始的0x100大小的内存区不使用即可),可根据实际中断向量表的大小作调整,多了没事,少了不行。
2、在bootload中将应用程序的中断向量表从Flash中拷贝到RAM中。(在app程序中去拷贝应该也是可以的?)
3、设置STM32F0xx中断向量表位于RAM中。

在用户应用程序中,按照以上方法,添加以下两行代码(在跳转APP之前执行):

    memcpy((void*)0x20000000, (void*)0x08004000, VECTOR_SIZE);SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);//SYSCFG->CFGR1 |= 0x03;

其中,0x2000 0000是SRAM的起始地址,这个不需要改动。

而之后的两个参数需要根据实际情况作出修改。0x0800 4000是应用程序的起址地址,从这里开始的VECTOR_SIZE字节,存放是的应用程序的中断向量表。VECTOR_SIZE是指中断向量表的大小,具体多大可以在startup.s文件里计算得到。以下以startup_stm32f030.s为例作说明:

Stack_Size      EQU     0x00000400AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size
__initial_sp; <h> Heap Configuration
;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>Heap_Size       EQU     0x00000200AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limitPRESERVE8THUMB; Vector Table Mapped to Address 0 at ResetAREA    RESET, DATA, READONLYEXPORT  __VectorsEXPORT  __Vectors_EndEXPORT  __Vectors_Size__Vectors       DCD     __initial_sp                   ; Top of StackDCD     Reset_Handler                  ; Reset HandlerDCD     NMI_Handler                    ; NMI HandlerDCD     HardFault_Handler              ; Hard Fault HandlerDCD     0                              ; ReservedDCD     0                              ; ReservedDCD     0                              ; ReservedDCD     0                              ; ReservedDCD     0                              ; ReservedDCD     0                              ; ReservedDCD     0                              ; ReservedDCD     SVC_Handler                    ; SVCall HandlerDCD     0                              ; ReservedDCD     0                              ; ReservedDCD     PendSV_Handler                 ; PendSV HandlerDCD     SysTick_Handler                ; SysTick Handler; External InterruptsDCD     WWDG_IRQHandler                ; Window WatchdogDCD     0                              ; ReservedDCD     RTC_IRQHandler                 ; RTC through EXTI LineDCD     FLASH_IRQHandler               ; FLASHDCD     RCC_IRQHandler                 ; RCCDCD     EXTI0_1_IRQHandler             ; EXTI Line 0 and 1DCD     EXTI2_3_IRQHandler             ; EXTI Line 2 and 3DCD     EXTI4_15_IRQHandler            ; EXTI Line 4 to 15DCD     0                              ; ReservedDCD     DMA1_Channel1_IRQHandler       ; DMA1 Channel 1DCD     DMA1_Channel2_3_IRQHandler     ; DMA1 Channel 2 and Channel 3DCD     DMA1_Channel4_5_IRQHandler     ; DMA1 Channel 4 and Channel 5DCD     ADC1_IRQHandler                ; ADC1DCD     TIM1_BRK_UP_TRG_COM_IRQHandler ; TIM1 Break, Update, Trigger and CommutationDCD     TIM1_CC_IRQHandler             ; TIM1 Capture CompareDCD     0                              ; ReservedDCD     TIM3_IRQHandler                ; TIM3DCD     0                              ; ReservedDCD     0                              ; ReservedDCD     TIM14_IRQHandler               ; TIM14DCD     TIM15_IRQHandler               ; TIM15DCD     TIM16_IRQHandler               ; TIM16DCD     TIM17_IRQHandler               ; TIM17DCD     I2C1_IRQHandler                ; I2C1DCD     I2C2_IRQHandler                ; I2C2DCD     SPI1_IRQHandler                ; SPI1DCD     SPI2_IRQHandler                ; SPI2DCD     USART1_IRQHandler              ; USART1DCD     USART2_IRQHandler              ; USART2__Vectors_End__Vectors_Size  EQU  __Vectors_End - __VectorsAREA    |.text|, CODE, READONLY; Reset handler routine
Reset_Handler    PROCEXPORT  Reset_Handler                 [WEAK]IMPORT  __mainIMPORT  SystemInitLDR     R0, =__initial_sp          ; set stack pointerMSR     MSP, R0

我们只需关注其中的一小部分。从29行开始,直到75行,每一个DCD都代表一个中断向量(所谓中断向量,说得明白点,其实就是某个中断服务程序的入口地址)。例如第74行的:

DCD USART1_IRQHandler ; USART1
  这里的“USART1_IRQHandler"其实就是UART1中断服务程序USART1_IRQHandler这个函数,同时,它也代表这个函数的入口地址。

以上代码即定义了这样一张表,这张表包括45个元素,每个元素是一个长度为4字节的地址。除了第一个地址是SP(堆栈指针)外,其它的地址都是某个中断服务程序的入口地址。

那么,回到我们要解决的问题上来,之前memcpy函数中的第三个参数VECTOR_SIZE,针对本例,就应该是45*4=180(0xB4)个字节。

在执行完以上两行代码后,若发生中断,CPU就会去SRAM(即0x2000 0000处)取中断向量了,所以,以0x2000 0000作为起始地址之后的VECTOR_SIZE个字节就不能被改动了。为了达到这VECTOR_SIZE个字节不被修改的目的,如下两种方法可以实现。

• 在工程文件内修改SRAM的起始地址以及长度,预留出空间存储中断向量表,如下图

• 如果使用了分散加载文件,则在分散加载文件中修改SRAM的起始地址及长度也能达到目的。

至此,STM32F0系列Cortex-M0内核芯片中断向量表重映射的问题已解决。

注意:关于STM32F0的IAP,ST官方有套参考代码,即STM32F0xx_AN4065_FW_V1.0.0例程。

参考:
https://www.cnblogs.com/outs/p/4948134.html
https://blog.csdn.net/findaway123/article/details/41602931
http://mcu.eetrend.com/content/2018/100010135.html

STM32F0芯片IAP实现之中断向量表重映射(没有中断向量表偏移寄存器SCB->VTOR的应对方法)相关推荐

  1. for根据ID去重_汽车ECU参数标定之配置Overlay RAM实现Qorivva MPC57xx系列MCU参数在线标定和代码重映射原理和方法详解...

    内容提要 引言 1. MPC5744P的Overlay RAM工作原理介绍 2 MPC5744P的Flash Overlay配置详解 2.1 平台Flash标定区域描述字寄存器配置字0--PFLASH ...

  2. 关于STM32的中断向量表的重映射的问题

    1 为什么要对中断向量表进行重新映射? COREM3权威指南上讲"然而,为了动态重分发中断, CM3 允许向量表重定位--从其它地址处开始定位各异常向量. 这些地址对应的区域可以是代码区,但 ...

  3. ST芯片的引脚复用功能和重映射功能

    重映射:将原来属于A引脚的默认的复用功能,转移到具有这个重映射功能的B引脚. 当把GPIO用作EXTI外部中断或使用重映射功能的时候,必须开启AFIO时钟,使用默认复用功能的时候不用开启.

  4. STM32从Flash地址0x08000000的启动重映射

    在初写STM32程序时,遇到一个困惑,STM32的Flash在MDK里被设置为起始地址0x0800 0000,而CM3手册规定芯片复位时要从0x0000 0000地址开始取出中断向量 ,那STM32怎 ...

  5. 痞子衡嵌入式:利用i.MXRT1060,1010上新增的FlexSPI地址重映射(Remap)功能可安全OTA...

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT部分型号上新增的FlexSPI Remap功能. OTA升级设计几乎是每个量产客户都绕不开的话题,产品发布后免不了要做固件( ...

  6. remap(地址重映射)机制

    remap(地址重映射)机制 (1)在系统复位之后,ARM将从地址0处开始执行指令,因此地址0x0处必须是ROM之类的在掉电之后数据不会天失的存储介质,而且存放的必须是E确的可执行的指令. (2)在A ...

  7. STM32F1 端口复用、端口(部分和完全)重映射

    端口复用功能         STM32 有很多的内置外设(比如:串口.ADC.DAC等是独立的模块和内核连接在一起),这些外设的外部引脚都是与 GPIO 复用的.也就是说,一个 GPIO如果可以复用 ...

  8. stm32f4有重映射么_STM32管教复用与重映射关系

    摘自:http://blog.csdn.net/lincheng15/article/details/51789093 概括一下:复用就是一个引脚有几个功能,1.做普通IO输入输出 2.其他外设的输入 ...

  9. 浅谈嵌入式MCU软件开发之S32K1xx系列MCU启动过程及重映射代码到RAM中运行方法详解

    内容提要 注:本文摘自NXP工程师胡恩伟的微信公众号"汽车电子expert成长之路",大家感兴趣可以关注一下. 引言 1. S32K1xx系列MCU启动过程详解(startup_S ...

最新文章

  1. 阿里巴巴开源的缓存框架JetCache创建缓存
  2. 9位AI教授总结2017年:技术变得平民化,但商业竞争在不断升级
  3. protel快捷键大全
  4. selenium python_Python+Selenium基础入门及实践
  5. Spark2内存调优总结 - 内存划分 与 内存计算 与 调参方式
  6. 二叉树的先序、中序、后续遍历【Java】
  7. 《算法:C语言实现》——连通性
  8. 新东方在线战略亏损:扩张提速or高层动荡?
  9. mfc 子窗体 按钮不触发_实战经验:MFC非模态对话框的使用
  10. BZOJ3571 [Hnoi2014]画框 【分治 + KM算法】
  11. 4月1日标准IO和文件IO的区别(个人收藏)
  12. Phpmyadmin的一次渗透测试
  13. 春节钱包大流量奖励系统入账及展示的设计与实现
  14. 苹果CMS海螺模板V16魔改版2.0修复bug分享给大家
  15. PDF合并:如何将两个PDF文件合并成一个PDF文件
  16. java基础之重写父类_繁星漫天_新浪博客
  17. 【Java基础系列】tob和toc的区别
  18. 高质量股票数据_10个网站免费下载高质量的股票视频
  19. c语言中fbfd函数,FBFD
  20. Android源码之init.rc文件详解

热门文章

  1. 电子邮箱如何大量发送邮件?TOM VIP邮箱邮件群发的建议
  2. 谈谈绘画为什么要重视画人物肖像?
  3. 考研考计算机英语作文,从2016考研英语作文真题透析考研命题规律
  4. apache 基金会 project 概述
  5. 美服疯狂坦克辅助瞄准外挂C#版开发(二)全局鼠标键盘HOOK
  6. 面试官问:如何用Elasticsearch实现Word、PDF,TXT文件的全文内容检索?
  7. simulink仿真pid控制伺服系统
  8. 俄罗斯前总统叶利钦逝世
  9. 【考研英语词汇训练营】Day 11 —— offer ,form ,maintain ,critical
  10. springboot向手机发送验证码