STM32F103嵌套向量中断控制器

news/2024/11/20 22:03:22/文章来源:https://www.cnblogs.com/zyly/p/18559424

一、STM32F103中断介绍

1.1 什么是中断

中断:打断CPU执行正常的程序,转而处理紧急程序,然后返回原暂停的程序继续运行;

举例:当你正在写作业时,做到一半又去吃饭,吃完饭后又回来接着原来的作业继续完成。

对于单片机来说,中断是指CPU正在处理某个事件A,发生了另一件事件B,请求CPU迅速去处理(中断发生);

CPU暂时停止当前的工作(中断响应),转去处理事件B(中断服务);

CPU处理事件B完成后,再回到原来的事件A(断点)继续执行,这一过程称之为中断。

中断的作用和含义:

  • 实时控制:在确定的时间内对相应事件做出相应;例如:温度控制;
  • 故障处理:检测到故障,需要第一时间进行处理;
  • 数据传输:不确定数据何时会来,利用中断进行控制;

中断的作用:高效处理紧急程序,并且不会占用CPU资源。

1.2 嵌套向量中断控制器(NVIC

NVIC即嵌套向量中断控制器,全称Nested vectored interrupt controller。属于是内核的器件,其作用是对STM32中的中断进行管理,因为Contex M3内核中的中断数量很多,当同时出现多个中断时,优先处理哪个中断?以及那些中断不处理等,都要靠NVIC进行控制。

Contrex M3内核都是支持256个中断,其中包含了16个内核异常和240个外部中断,并且具有256级的可编程中断设置。

但是对于ST公司来说,用不了Contrex M3内核中的所有中断以及中断优先级,进而对其进行了一定的裁剪。STM32F103中共有:

  • 10个内核异常;
  • 60个可屏蔽中断;

注意一下:Contrex M3的外部中断和STM32F103的外部中断不是一个概念;

  • Contrex M3:除了内核异常之外的都是外部中断;
  • STM32F103:外部中断EXTI只有6个;

在中断的使用中有一个极其重要的一部分为中断服务函数(触发中断后,系统执行的部分,例如上文的吃饭过程)中断服务函数是中断的入口。

1.2.1 异常和中断向量表

定义一块固定的内存,以4字节对齐(32位),用于存放中断服务函数的首地址,系统已经将中断服务函数定义好了,放在中断向量表中,我们只需要进行调用即可。

例如下面的异常和中断中断向量表:

其中前10个中断为内核异常,剩下的60个为可屏蔽中断,其编号为0~59,优先级从7~66

优先级号越小,优先级越高。当表中的某处异常或中断被触发,程序计数器指针(PC)将跳转到该异常或中断的地址处执行,该地址处存放这一条跳转指令,跳转到该异常或中断的服务函数处执行相应的功能。因此,异常和中断向量表只能用汇编语言编写。

1.3 中断优先级

二、中断相关寄存器

三、中断配置源码

3.1 系统启动

无论是是何种MCU,从简单的51MSP430,到ARM9ARM11A7都必须有启动文件,因为对于嵌入式开发,绝大部分情况都是使用C语言,而C语言一般都是从main函数开始,但是对于MCU来说,他是如何找到并执行main函数的,就需要用到“启动文件”。

STM32F103的启动文件为stm32f10x_vectors.s,启动文件是使用机器认识的汇编语言,经过一些必要的配置,最终能够调用main函数,使得用户程序能够在MCU上正常运行起来的必备文件。

本文以MDK环境下的stm32f10x_vectors.s为模板讲解,不同编译器下的启动文件不同。

3.1.1 栈初始化

代码的开始,就是开辟栈空间,用于局部变量,函数调用,函数参数等;

Stack_Size       EQU     0x00000400AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem        SPACE   Stack_Size
__initial_sp

汇编伪指令讲解:

  • EQU:宏定义的伪指令,相当于等于,类似于C语言中的宏定义define
  • AREA: 告诉汇编器汇编一个新的代码段或者数据段;
  • SPACE:用于分配一定大小的内存空间,单位字节;

因此上面的代码结合起来就是分配一个长度为1kb的栈空间,命名为STACK,并且不初始化,可读可写,按照2的3次方(8个字节)对齐开辟。

__initial_sp只是一个标号,标号主要用于表示一片内存空间的某个位置,等价于C语言中的地址概念。地址仅仅表示存储空间的位置。

__initial_sp紧挨着SPACE语句放置,表示栈的结束地址,即栈顶地址,栈是由高向低生长的。

3.1.2 堆初始化

接下来是开辟堆空间,主要用于动态内存分配,使用malloccalloc等函数分配的变量空间是在堆上的;

Heap_Size        EQU     0x00000400AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem         SPACE   Heap_Size
__heap_limit

同样分配一个长度为1kb的堆空间,命名为HEAP,并且不初始化,可读可写,按照2的3次方(8个字节)对齐开辟。

标号_heap_base表示堆的起始地址,标号__heap_limit紧挨着SPACE语句放置,表示堆的结束地址,堆是由低向高生长的(与栈相反)。

3.1.3 导入异常和中断处理函数

接着是导入外部文件定义的异常和中断处理函数,为建立异常和中断向量表做准备;

                 THUMBPRESERVE8; Import exceptions handlersIMPORT  NMIExceptionIMPORT  HardFaultExceptionIMPORT  MemManageExceptionIMPORT  BusFaultExceptionIMPORT  UsageFaultException......IMPORT  FLASH_IRQHandlerIMPORT  RCC_IRQHandlerIMPORT  EXTI0_IRQHandlerIMPORT  EXTI1_IRQHandlerIMPORT  EXTI2_IRQHandlerIMPORT  EXTI3_IRQHandlerIMPORT  EXTI4_IRQHandler......IMPORT  TIM1_BRK_IRQHandlerIMPORT  TIM1_UP_IRQHandlerIMPORT  TIM1_TRG_COM_IRQHandlerIMPORT  TIM1_CC_IRQHandlerIMPORT  TIM2_IRQHandlerIMPORT  TIM3_IRQHandlerIMPORT  TIM4_IRQHandlerIMPORT  I2C1_EV_IRQHandlerIMPORT  I2C1_ER_IRQHandler......IMPORT  DMA2_Channel1_IRQHandlerIMPORT  DMA2_Channel2_IRQHandlerIMPORT  DMA2_Channel3_IRQHandlerIMPORT  DMA2_Channel4_5_IRQHandler;*******************************************************************************
; Fill-up the Vector Table entries with the exceptions ISR address
;*******************************************************************************; 定义一个数据段 命名为RESET,DATA表示数据, READONLY表示可读AREA    RESET, DATA, READONLYEXPORT  __Vectors

其中:

  • PRESERVE8表示指定当前文件的推栈按照8字节对齐;
  • THUMB表示后面指令位THUMB指令;
  • IMPORT用于声明外部符号,告诉汇编器这些符号来自其他模块或库,需要在链接时进行解析。这种机制使得汇编程序能够调用外部库中的函数或访问外部定义的全局变量,实现代码的模块化和复用;
  • EXPORT:声明一个标号具有全局属性,用于将符号暴露给当前源文件以外的其他文件;

代码中AREA定义了一段名为RESETREADONLY只读数据段,只读属性保存在Flash区(如果STM32Flash启动,则此异常和中断向量表的地址为0x0800 0000),

3.1.4 异常和中断向量表

Cortex M3内核规定起始地址必须存放栈顶指针,而第二个地址则必须存放复位中断入口向量地址,这样在Cortex-M3内核复位后,会自动从起始地址的下一个32位空间取出复位中断入口向量,跳转执行复位中断服务程序。

Cortex-M3内核固定了异常和中断向量表的位置, 但是起始地址是可变化的。

__Vectors        DCD  __initial_sp              ; Top of StackDCD  Reset_HandlerDCD  NMIExceptionDCD  HardFaultExceptionDCD  MemManageExceptionDCD  BusFaultExceptionDCD  UsageFaultExceptionDCD  0                 ; ReservedDCD  0                 ; ReservedDCD  0                 ; ReservedDCD  0                 ; ReservedDCD  SVCHandlerDCD  DebugMonitorDCD  0                 ; ReservedDCD  PendSVCDCD  SysTickHandlerDCD  WWDG_IRQHandlerDCD  PVD_IRQHandlerDCD  TAMPER_IRQHandlerDCD  RTC_IRQHandlerDCD  FLASH_IRQHandlerDCD  RCC_IRQHandlerDCD  EXTI0_IRQHandlerDCD  EXTI1_IRQHandlerDCD  EXTI2_IRQHandlerDCD  EXTI3_IRQHandlerDCD  EXTI4_IRQHandlerDCD  DMA1_Channel1_IRQHandlerDCD  DMA1_Channel2_IRQHandlerDCD  DMA1_Channel3_IRQHandlerDCD  DMA1_Channel4_IRQHandlerDCD  DMA1_Channel5_IRQHandlerDCD  DMA1_Channel6_IRQHandlerDCD  DMA1_Channel7_IRQHandlerDCD  ADC1_2_IRQHandlerDCD  USB_HP_CAN_TX_IRQHandlerDCD  USB_LP_CAN_RX0_IRQHandlerDCD  CAN_RX1_IRQHandlerDCD  CAN_SCE_IRQHandlerDCD  EXTI9_5_IRQHandlerDCD  TIM1_BRK_IRQHandlerDCD  TIM1_UP_IRQHandlerDCD  TIM1_TRG_COM_IRQHandlerDCD  TIM1_CC_IRQHandlerDCD  TIM2_IRQHandlerDCD  TIM3_IRQHandlerDCD  TIM4_IRQHandlerDCD  I2C1_EV_IRQHandlerDCD  I2C1_ER_IRQHandlerDCD  I2C2_EV_IRQHandlerDCD  I2C2_ER_IRQHandlerDCD  SPI1_IRQHandlerDCD  SPI2_IRQHandlerDCD  USART1_IRQHandlerDCD  USART2_IRQHandlerDCD  USART3_IRQHandlerDCD  EXTI15_10_IRQHandler......

以上代码定义了处理器复位后各个异常和中断对应的处理函数。异常和中断向量表的第一个元素存放的是__initial_sp栈顶的指针;第二个元素存放的是Reset_Handler函数入口地址。

3.1.5 Reset_Handler

系统上电或者复位后后,首先执行的代码就是Reset_Handler

; Reset handler routine
Reset_Handler    PROCEXPORT  Reset_HandlerIF      DATA_IN_ExtSRAM == 1
; FSMC Bank1 NOR/SRAM3 is used for the STM3210E-EVAL, if another Bank is 
; required, then adjust the Register Addresses; Enable FSMC clockLDR R0,= 0x00000114 LDR R1,= 0x40021014STR R0,[R1]	                 ; Enable GPIOD, GPIOE, GPIOF and GPIOG clocksLDR R0,= 0x000001E0LDR R1,= 0x40021018STR R0,[R1]	   ; SRAM Data lines, NOE and NWE configuration 
; SRAM Address lines configuration 
; NOE and NWE configuration   
; NE3 configuration 
; NBL0, NBL1 configuration LDR R0,= 0x44BB44BB LDR R1,= 0x40011400STR R0,[R1]		LDR R0,= 0xBBBBBBBB LDR R1,= 0x40011404STR R0,[R1]		LDR R0,= 0xB44444BB LDR R1,= 0x40011800STR R0,[R1]		LDR R0,= 0xBBBBBBBB LDR R1,= 0x40011804STR R0,[R1]		LDR R0,= 0x44BBBBBB LDR R1,= 0x40011C00STR R0,[R1]	    LDR R0,= 0xBBBB4444 LDR R1,= 0x40011C04STR R0,[R1]	    LDR R0,= 0x44BBBBBBLDR R1,= 0x40012000STR R0,[R1]		LDR R0,= 0x44444B44LDR R1,= 0x40012004STR R0,[R1]      ; FSMC Configuration   
; Enable FSMC Bank1_SRAM Bank LDR R0,= 0x00001011LDR R1,= 0xA0000010STR R0,[R1]	LDR R0,= 0x00000200 LDR R1,= 0xA0000014STR R0,[R1]	ENDIFIMPORT  __mainLDR     R0, =__mainBX      R0ENDP

PROCENDP这一对伪指令把程序分为若干个过程,使程序结构更加清晰。

_main标号表示C/C++标准实时库函数里的一个初始化子程序main的入口地址。该程序的一个主要作用是初始化堆栈(跳转_user_initial_stackheap标号进行初始化堆栈),并初始化映像文件,最后跳转到C程序中的main函数。这也正解释了为什么所有的C程序必须有一个main函数作为程序的起点,因为这是由C/C++标准实时库所规定的。

__user_initial_stackheapLDR     R0, =  Heap_MemLDR     R1, =(Stack_Mem + Stack_Size)LDR     R2, = (Heap_Mem +  Heap_Size)LDR     R3, = Stack_MemBX      LR

四、源码下载

源码下载路径:stm32f103

参考文章

[1] Mini2440裸机开发之中断控制器

[2] STM32--中断使用

[3] 嵌入式Linux之常用ARM汇编

[4] STM32的启动过程 — startup_xxxx.s文件解析

[5] STM32的内存管理相关

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/837555.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NFLS贪心与数据结构题单笔记(未完结)

A. 奶牛飞车贪心,把最慢的放前面#include <bits/stdc++.h> using namespace std; constexpr int maxn = 1e6 + 10; int n, m, d, L; int s[maxn]; int ans = 0; inline bool cmp(int x, int y) { return x > y; } int main() {cin >> n >> m >> d …

提取图片中目标物轮廓的像素尺寸

利用OpenCV库,对图片空间转化、灰度处理、二值化处理等,寻找图片中目标物轮廓像素尺寸。1.导入数据库 import cv2 import numpy as np from PIL import Image2.导入图片 image_tif = Image.open(1.tif) #导入tif图像 image_tif.convert(RGB).save(1p.png,PNG) # 转换为png格…

[极客大挑战 2019]BuyFlag

点击右上角的菜单,有一个payflag,直接点击,进入到了pay.php页面发现,需要得到flag有两个要求:必须是该校的学生,密码必须正确。在该页面的网页底部,有代码提示,要求密码不能是纯数字,最后又要==404密码才正确。我们可以想到利用php的弱类型比较:只要前缀有404就好。那…

Thinkpad P14s 的 archlinux 成长手册(i3-wm 窗口管理器)

目录电脑信息i3-wm 快捷键分辨率调整终端版文件管理器壁纸设置触摸板配置合盖后不休眠i3 配置文件截图工具剪切板i3lock-color卸载 i3lock安装 i3lock-color定义配置文件i3 配置文件增加锁屏配置i3 主题和图标修改i3 工作区配置分配应用程序到工作区工作区字体修改i3 启用透明效…

一键生成美观的彩页演示+AI的训练过程科普

一键生成美观彩页 + AI训练揭秘:让你的内容瞬间高大上! 阅读时间: 8分钟 | 字数: 1300+ 你是否曾为制作精美的演示文稿而烦恼?是否对AI的训练过程充满好奇?今天,让我们一起探索如何用AI一键生成美观彩页,同时揭秘ChatGPT的训练过程! 🌟 天工AI彩页:内容创作的革命 🤔事情…

2个月搞定计算机二级C语言——真题(12)解析

1. 前言 本篇我们讲解2个月搞定计算机二级C语言——真题122. 程序填空题 2.1 题目要求2.2 提供的代码 #include <stdio.h> #define N 3 int fun(int (*a)[N]) {int i, j, m1, m2, row, colum;m1 = m2 = 0;for (i = 0; i < N; i++){j = N - i - 1; m1 += a[i][…

mini-lsm通关笔记Week2Day5

项目地址:https://github.com/skyzh/mini-lsm 个人实现地址:https://gitee.com/cnyuyang/mini-lsmSummary 在本章中,您将:实现manifest文件的编解码。 系统重启时从manifest文件中恢复。要将测试用例复制到启动器代码中并运行它们, cargo x copy-test --week 2 --day 5 ca…

SSTI(模板注入)

SSTI:SSTI(Server-Side Template Injection)即服务端模板注入,它是一种安全漏洞攻击技术。 当应用程序在服务器端使用模板引擎来呈现动态生成的内容时,如果用户可以控制模板引擎的输入,就可能导致 SSTI 漏洞。 服务端接收攻击者的恶意输入以后,未经任何处理就将其作为 Web…

blktrace分析IO

前言 上篇博客介绍了iostat的一些输出,这篇介绍blktrace这个神器。上一节介绍iostat的时候,我们心心念念希望得到块设备处理io的service time,而不是service time + wait time,因为对于评估一个磁盘或者云磁盘而言,service time才是衡量磁盘性能的核心指标和直接指标。很不…

数据库 校验名称唯一性,用于新增和修改功能

数据库 校验名称唯一性,用于新增和修改功能@目录概述代码 概述应用场景:xml,注解方式的自己略微改造即可使用。 提示:存粹方便自己拷贝代码,用于新增和修改前校验名称唯一性问题。代码Service/*** 校验名称是否重名* @Author 211145187* @Date 2022/5/5 15:37* @param nam…

人工智能之机器学习最优化基础——凸优化

凸优化(Convex Optimization) 是优化问题的一个重要分支,其目标是最小化或最大化一个凸函数(或凹函数),通常受限于一组凸约束条件。由于凸优化问题具有良好的数学性质,许多优化问题可以转化为凸优化问题并高效求解。1. 什么是凸优化问题? 一个标准的凸优化问题可以表示…

可信执行环境(TEE)学习笔记

可信执行环境(TEE)学习笔记来越多的数据在云环境下进行存储、共享和计算,云环境下的数据安全与隐私保护也逐渐成为学术界以及工业界关注的热点问题。目前阶段,隐私保护技术主要基于密码算法及协议(如安全多方计算、同态加密等)完成场景落地,其优点主要在于具有较高的安全…