【裸机开发】认识中断向量表(设置中断向量偏移的原因)

这篇具有很好参考价值的文章主要介绍了【裸机开发】认识中断向量表(设置中断向量偏移的原因)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

之前的LED驱动不存在中断,也就不包含中断的初始化。如果程序包含了中断,我们应还需要初始化哪些内容?要解决这个问题,我们需要先了解一个中断系统包含了哪些内容。

中断向量表描述中断对应的中断服务函数,保存在程序开始运行的地方,默认是0x00000000

中断控制器(NVIC、GIC)中断系统的管理机构

中断使能:某个外设的中断使能(要使用某个外设的中断,要先使能这个外设的中断)

中断服务函数:当中断产生时,中断服务函数就会被调用(中断处理逻辑都在中断服务函数中)


目录

一、中断向量表

1、什么是中断向量表?

2、中断类型

二、为什么要设置中断向量表偏移 

1、原因分析

2、如何确定偏移量

3、如何设置

三、汇编编写中断向量表框架


一、中断向量表

1、什么是中断向量表?

中断向量表的作用是描述中断对应的中断服务函数。保存在程序开始运行的地方,默认是0x00000000,可以通过设置中断向量偏移,来改变中断向量表的位置。

Cortex-M 的中断向量表中列举出了所有的中断,每一个中断对应一个中断服务函数;而 Cortex-A 的中断向量表则是将中断分为了 7 类

  • 某个中断发生时,先判断属于哪一类
  • 然后,去中断向量表找对应类的中断服务函数
  • 随后,执行对应的中断服务函数
  • 最后,回到程序暂停的下一个位置

【裸机开发】认识中断向量表(设置中断向量偏移的原因),# I.MX6ULL裸机开发,c语言,开发语言

中断向量表所写的就是不同中断类型所对应的中断服务函数地址

2、中断类型

中断大致可以分为七种类型,不同的中断类型对应着一种 CPU 工作模式,当中断产生时,CPU 会先切换到对应的模式,然后再处理中断。其中我们最常用的是 Reset IRQ 中断。

  • ResetCPU 复位以后就会进入复位中断,我们可以在复位中断服务函数里面做一些初始化工作,比如初始化 SP 指针、DDR 等
  • Undefined Instruction:如果指令不能识别的话就会产生此中断
  • SWI:Linux 的系统调用会用 SWI 指令来引起软中断,通过软中断来陷入到内核空间
  • Prefetch Abort:预取指令的出错的时候会产生此中断
  • Data Abort:访问数据出错的时候会产生此中断
  • IRQ外设中断都会引起此中断的发生
  • FIQ:快速中断,如果需要快速处理中断的话就可以使用此中断
偏移地址 中断类型 中断模式
0x00 复位中断(Reset) SVC
0x04 未定义指令中断(Undefined Instruction) Undef
0x08 软中断(Software Interrupt,SWI) SVC
0x0C 指令预取中止中断(Prefetch Abort) Abort
0x10 数据访问中止中断(Data Abort) Abort
0x14 保留(Reserved) -
0x18 IRQ 中断(IRQ Interrupt) IRQ
0x1C FIQ 中断(FIQ Interrupt) FIQ

注意:因为中断向量表是放在程序运行的起始位置,所以这里的偏移位置是相对于起始位置而言的

二、为什么要设置中断向量表偏移 

1、原因分析

中断向量表保存在程序运行的起始位置,默认是 0x00000000。根据参考手册中的内存映射表我们发现, 0x00000000 的位置保存了 boot rom,也就是设备上电启动的相关内容,为了不占用其他部分的内容,我们决定对中断向量表施加一个偏移。

【裸机开发】认识中断向量表(设置中断向量偏移的原因),# I.MX6ULL裸机开发,c语言,开发语言

中断控制器(GIC)可以配置中断向量表的偏移位置。裸机开发的环境下,我一般在Reset 中断服务函数中手动指定中断向量表的位置;在有 OS 的环境下,OS 会初始化中断控制器,并将中断向量表放置在一个没有被保留的地址空间中。

2、如何确定偏移量

考虑到 RAM 和 DDR 的范围,我们一般将程序保存在 DDR 中。

  • RAM:CPU内部的一段可用内存,imx6ull内部RAM的大小为128K(0X900000~0X91FFFF)
  • DDR:CPU外的存储器,封装在SOC 中,DDR的大小为 256M 或者 512M(虽然看着有2048,但是受到总线约束,CPU可访问的大小是256M)

【裸机开发】认识中断向量表(设置中断向量偏移的原因),# I.MX6ULL裸机开发,c语言,开发语言

DDR 的范围较广,考虑到后续的系统移植,所以使用的是DDR。假设中断向量表设为 0x83000000,其实就是在告诉CPU,中断发生时,到 0x83000000 的位置去找对应的中断服务函数。

【裸机开发】认识中断向量表(设置中断向量偏移的原因),# I.MX6ULL裸机开发,c语言,开发语言

其实我们也可以将中断向量表和存储地址都设置成 0x87800000

【裸机开发】认识中断向量表(设置中断向量偏移的原因),# I.MX6ULL裸机开发,c语言,开发语言

3、如何设置

通过汇编设置

如果是汇编形式,建议放在 Reset 中断服务函数中,因为设备上电就会触发 Reset 中断,然后去执行 Reset 中断服务函数。

/* 复位中断服务函数 */ 
Reset_Handler:
    /* ... */

    ldr r0, =0x87800000         /* 设置中断向量表的偏移 */
	dsb
	isb
	mcr p15, 0, r0, c12, c0, 0
	dsb
	isb

    /* ... */

调用 C 函数

我们可以直接调用 C 函数来设置中断向量表,只要在中断发生之前设置即可。一般放在中断初始化的函数中。

/* 设置中断向量表偏移 */
__set_VBAR((uint32_t)0x87800000);

三、汇编编写中断向量表框架

1、局部流程

中断向量表保存在程序运行的起始位置,默认是 0x00000000。其实就是在告诉内核,每一个中断对应的中断服务函数位置在哪。假设我们要设置 Reset 中断的服务函数地址。

.global _start
 
_start:
    /* 把 Reset_Handler 的地址保存到 pc 指向的位置 */ 
    ldr pc, =Reset_Handler          


/* 复位中断服务函数 */ 
Reset_Handler:
    b Reset_Handler      @ 暂时先死循环,后面再修改              

pc 是程序计数器,用于保存下一次要执行的指令地址。默认情况下,程序从 0x00000000 开始执行,即 pc 最开始拿到的地址就是 0x00000000,这里其实就把 Reset_Handler 的地址保存到了 0x00000000 的位置。

随后,pc 会指向下一个地址,即 0x00000004。

2、整体框架

其他中断也是类似的,我们借助pc寄存器的地址自动递增的特性,逐个设置各个中断服务函数的地址。至于具体实现,这里有 Reset 中断 和 IRQ 中断的汇编部分。

Reset中断:仅包含汇编部分,因为一般只有在复位或者刚上电的时候才会触发,没有需要特意实现的逻辑。Reset 中断服务函数(汇编部分)

② IRQ 中断:包含汇编部分和 C代码部分。文章来源地址https://www.toymoban.com/news/detail-709121.html

  • 汇编部分用于初始化环境
  • C 代码部分用于逻辑实现
_start:
    ldr pc, =Reset_Handler          /* 复位中断 */ 
    ldr pc, =Undefined_Handler      /* 未定义指令中断 */
    ldr pc, =SVC_Handler            /* SVC(Supervisor)中断*/
    ldr pc, =PrefAbort_Handler      /* 预取终止中断 */
    ldr pc, =DataAbort_Handler      /* 数据终止中断 */
    ldr pc, =NotUsed_Handler        /* 保留中断 */
    ldr pc, =IRQ_Handler            /* IRQ 中断 */
    ldr pc, =FIQ_Handler            /* FIQ(快速中断) */

/* 复位中断 */ 
Reset_Handler:
    b Reset_Handler

/* 未定义指令中断 */ 
Undefined_Handler:
    b Undefined_Handler

/* SVC */ 
SVC_Handler:
    b SVC_Handler

/* 预取终止中断 */ 
PrefAbort_Handler:
    b PrefAbort_Handler

/* 数据终止中断 */ 
DataAbort_Handler:
    b DataAbort_Handler    

/* 保留中断 */ 
NotUsed_Handler:
    b NotUsed_Handler 

/* IRQ 中断 */ 
IRQ_Handler:
    b IRQ_Handler   

/* FIQ(快速中断) */ 
FIQ_Handler:
    b FIQ_Handler  

到了这里,关于【裸机开发】认识中断向量表(设置中断向量偏移的原因)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • linuxARM裸机学习笔记(4)----GPIO中断以及定时器中断实验

    这个表里面存放的都是中断向量,中断服务程序的入口地址或存放中断服务程序的首地址成为中断向量。中断向量表是一系列中断服务程序入口地址组成的表,当某个中断触发的时候会自动跳转到中断向量表对应的中断服务程序的入口。 2.NVIC(内嵌向量中断控制器) 在IMU6U的中

    2024年02月14日
    浏览(45)
  • 【智能家居项目】裸机版本——认识esp8266 | 网络子系统

    🐱作者:一只大喵咪1201 🐱专栏:《智能家居项目》 🔥格言: 你只管努力,剩下的交给时间! 如上图整个智能家居程序总体框架图,还剩下网络子系统没有实现,以及最终的业务子系统没有实现。 如上图所示是乐鑫的多种网卡芯片,本喵使用的是其中的 ESP8266 ,具体性能

    2024年02月08日
    浏览(44)
  • ARM裸机 - 中断处理编程实战_arm断电文件内容丢失

    #define exception_vector_table_base 0xD0037400 #define exception_reset (exception_vector_table_base + 0x00) #define exception_undef (exception_vector_table_base + 0x04) #define exception_sotf_int (exception_vector_table_base + 0x08) #define exception_prefetch (exception_vector_table_base + 0x0C) #define exception_data (exception_vector_table_base + 0x10) #de

    2024年04月16日
    浏览(81)
  • 【Linux 裸机篇(七)】I.MX6U 中断系统

    中断向量表是一个表,这个表里面存放的是中断向量。中断服务程序的入口地址或存放中断服务程序的首地址成为中断向量,因此中断向量表是一系列中断服务程序入口地址组成的表。这些中断服务程序(函数)在中断向量表中的位置是由半导体厂商定好的,当某个中断被触发

    2024年02月01日
    浏览(45)
  • IMX6ULL裸机篇之中断实验-通用中断驱动说明二

    本文是 IMX6ULL 裸机篇---中断实验 。旨在用 C 语言编写一套简单的中断驱动框架代码。 在 start.S 文件中,我们在中断服务函数 IRQ_Handler 中调用了 C 函数 system_irqhandler 来处 理具体的中断。 本实验会认识中断控制器: GIC控制器。 I.MX6U(Cortex-A)的中断控制器,关于 GIC 的详细内容

    2023年04月24日
    浏览(57)
  • 【Linux 裸机篇(八)】I.MX6U EPIT 定时器中断、定时器按键消抖

    EPIT 的全称是: Enhanced Periodic Interrupt Timer,直译过来就是增强的周期中断定时器,它主要是完成周期性中断定时的。学过 STM32 的话应该知道, STM32 里面的定时器还有很多其它的功能,比如输入捕获、 PWM 输出等等。但是 I.MX6U 的 EPIT 定时器只是完成周期性中断定时的,仅此一

    2024年02月02日
    浏览(64)
  • 【STM32】中断向量表

    我是通过这个进行学习的,我觉得讲的很好,这里我稍加修改,作为自己的学习笔记: 嵌入式杂谈之中断向量表 STM32根据boot引脚的配置方式有3种启动方式,但是无论哪一种方式,对于STM32来说都是从0x0000 0000启动 STM32单片机启动第一件事就是取得 中断向量表 中断向量表是一个

    2024年02月11日
    浏览(35)
  • 线代:认识行列式、矩阵和向量

    本文主要参考的视频教程如下: 8小时学完线代【中国大学MOOC*小元老师】线性代数速学_哔哩哔哩_bilibili 另外这个视频可以作为补充: 【考研数学 线性代数 基础课】—全集_哔哩哔哩_bilibili 一般会由方程组来引出行列式 比如一个二阶行列式 二阶行列式的计算就是主对角线的

    2024年02月19日
    浏览(48)
  • I.MX6ULL开发笔记(二)——硬件外设操作

    在文章http://t.csdnimg.cn/EGWt9中有介绍Linux下文件目录,那么在Linux系统下,RGB灯也是一个设备,所以我们需要到 /sys 目录下去操作这个设备。 之后,我们进入到 class 目录,这里挂载着开发板上的外设: 在这里就能看到熟悉的硬件接口了,那么我们进入到 leds 的目录下: 可以看

    2024年01月24日
    浏览(54)
  • uniapp小程序地图设置中心点位置向上偏移

    图示: id=\\\"map\\\" ref=\\\"map\\\"

    2024年02月11日
    浏览(67)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包