0x07 LiteOS内核详解--中断接管机制(下)

举报
樊心昊 发表于 2020/06/26 17:58:07 2020/06/26
【摘要】 三、中断接管机制涉及到的文件los_hwi.c文件解析 该函数的本质就是直接通过C语言中嵌入汇编代码,读取IPSR寄存器的值,__get_IPSR()函数声明如下图:IPSR寄存器的解析----转自M3内核手册这些函数是用于处理系统中断,系统中断并未被LiteOS中断管理器接管,而是采用传统方案,当发生中断后,直接由中断向量表跳转过来执行。 除系统中断以外的全部中断发...

三、中断接管机制涉及到的文件

los_hwi.c文件解析

image.png

       该函数的本质就是直接通过C语言中嵌入汇编代码,读取IPSR寄存器的值,__get_IPSR()函数声明如下图:

image.png

IPSR寄存器的解析----转自M3内核手册

image.png

image.png这些函数是用于处理系统中断,系统中断并未被LiteOS中断管理器接管,而是采用传统方案,当发生中断后,直接由中断向量表跳转过来执行。

image.png

       除系统中断以外的全部中断发生后,都是先跳转到osInterrupt()中执行。

    先保存PRIMASK的值,然后关闭全部可屏蔽中断,相当于进入临界区。

    恢复PRIMASK的值,相当于进入退出区。

    获取当前触发的中断号

    计算出当前中断的对应处理函数在存储初段处理函数的数组中的位置

    如果该位置有处理函数就开始调用处理函数来处理中断

    调用处理函数来处理中断

    如果没有处理函数的中断发生了,就执行LiteOS默认的中断处理函数,其作用就是打印当前发生中断的值。

    先保存PRIMASK的值,然后关闭全部可屏蔽中断,相当于进入临界区。

    恢复PRIMASK的值,相当于进入退出区。

g_vuwIntCount这个值用于表示当前程序的状态,是否处于中断(异常)状态,如果处于异常状态有些操作不能进行,例如:获取互斥锁,调用系统延时函数等等,防止在中断处理中出现死锁的情况,导致一直无法退出中断。

       还有一个问题需要注意:中断标志位的清除,因为由用户自己写在用户的中断处理函数中,LiteOS并未帮我们提供。

image.png

       LiteOS通过将“中断处理函数指针”按照中断向量表中要求的顺序装入一个函数指针数组中,并通过链接脚本放置到向量表处(也就是0x8000_0000的地方),图中①处就是叫链接器将这块数组数据放到.isr_vector的地方。

       到这里相信细心的同学一定发现了只有14个函数指针+一个栈顶地址,stm32中那么多的中断,14个函数指针怎么会够用?

       现在就可以引出另外一个中断相关的文件----__vectors.h文件,②处在预处理时就会将该文件的内容替换到#incldue “__vectors.h”处。

image.png

我这里只截取了该文件的部分代码,因为太多了,并且都是一样的,到底要在我们的中断向量表中添加多少个函数指针,取决于系统默认定义的OS_HWI_MAX_NUM宏,在Cortex-m3,Cortex-m4 和 Cortex-m7中该宏的为240,一般情况下用户不需要自己修改,使用默认的即可,因为最大中断数和CPU有着强相关。

image.png

       初始化硬件中断,根据芯片内核来设置向量表偏移量寄存器,用于重定位中断向量,如果芯片是M3、M4等大于M3的内核还需要设置中断优先级组,默认是7。

image.png

image.png

该函数用于创建LiteOS的中断,最终被osal_int_connect函数调用。

uwHwiNum中断号(stm32xxx.h文件中有定义,例如USART1_IRQn)。

usHwiPrio中断优先级(这是LiteOS接管中断后的优先级,后面也会设置为NVIC中的优先级)。

usMode该参数暂时未被使用。

pfnHandler中断处理函数的函数指针。

uwArg假设我们的中断处理函数具有参数,可以通过该参数传入。

该函数首先判断我们传入的参数是否处于合理的范围,如果都正确,就关闭所有中断,将我们填入的参数存储到m_pstHwiSlaveForm结构体数组中,并使能我们传入的中断和设置NVIC中该中断的优先级,最后开启恢复所有中断并返回OK。

image.png

中断删除函数,本质上就是关闭该中断,并将该终端的信息从m_pstHwiSlaveForm结构体数组中移除即可。

 

与中断接管机制相关的文件和函数大概都介绍完了,大家如果有不明白的地方欢迎留言,我会给大家解答。

四、中断向量表是如何被链接到”0”地址处

__attribute__关键字

       attribute有属性的含义,一般出现在代码中是用来定义“编译属性”的,当我们需要将C语言代码中的某个部分编译后链接到某个特定的段时,就需要在这个部分前面加上__attribute__((section(段名))),例如在LiteOS代码中使用了__attribute__ ((section(".isr_vector")))将实现的中断向量表数组设置为.isr_vector段的位置,等待链接器链接到.isr_vector段中。

       因为中断向量表数组在los_hwi.c文件中,所以我们可以反汇编编译los_hwi.c后生成的los_hwi.o中间文件来一探究竟。

       使用反汇编命令 arm-none-eabi-objdump -x -j.isr_vector。

-x选项用于显示数据段的全部信息,如果不加该选项则看不到完整的数据。-

-j.isr_vector选项用于反汇编指定的段,我们只关心.isr_vector段。

结果如下:

       image.png

       编译器将下图的这部分数组相关代码编译到了.isr_vector段中:

·image.png

偏移量完全和中断向量表中要求的移植,等到链接时,就会将该段的内容(也就是这个数组中的内容)链接到.isr_vector处,下图为链接脚本(os.ld文件):

image.png

这段数据被放到了0x8000_0000处,上电后stm32“硬件上”自动将0x0000_0000地址和0x8000_0000地址处关联,通俗的来说就是STM32访问0x0000_0000处的数据,实际**问到了0x8000_0000处的数据,也就读取到了栈顶地址、中断向量表。

总结:中断向量表为什么会被链接到”0”地址处(这里的0是指0x8000_0000),一个是加载地址,一个是运行时地址。这里的“链接”比较片面,还包括了编译器进行编译时,将存放中断向量表的数据标记为了.isr_vector段,当链接器来链接生成elf文件时,将.isr_vector段内的数据放到了0x8000_0000地址处(加载时地址)。

五、中断接管机制的好处

       我们可以对比不采用中断接管的方式和采用了中断接管机制的方式实现的中断处理,采用了中断接管的方式:

1、 可以实现中断统一管理,如果要使用某个中断,直接调用osal_int_connect函数创建该中断,并将中断处理函数指针与之绑定,中断处理函数的名称完全可以自定义,无需像之前一样必须按照系统要求设定。

2、 便于移植,移植的时候无需考虑下层代码,因为不同芯片中断处理相关部分的差异完全被中断接管部分屏蔽。

3、 便于维护,调用删除中断函数,即可马上删除某个中断。

其他好处就不一一列举了。


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。