gcc扩展选项__attribute__((interrupt))——指定中断处理函数属性

1、调用者保存寄存器与被调用者保存寄存器

在这里插入图片描述

  • 假设:函数A调用了函数B,寄存器x在函数B中被修改了,对于A函数而言,逻辑上x内容在调用函数B的前后应该保持一致。现在需要解决前后不一致的问题,有两种思路:
    • 第一种:调用者保存的寄存器
      • 在函数A在调用函数B之前提前把寄存器x的值存入栈中,执行完函数B之后再恢复x的内容。
      • 在函数跳转前保存的寄存器,叫调用者保存寄存器
    • 第二种:被调用者保存的寄存器
      • 函数B在使用寄存器x前,先保存寄存器x的值到栈中,在函数B返回之前,要恢复寄存器x原来存储
        的内容
      • 在函数中,使用前必须保存、返回前必须恢复的寄存器
  • 至于怎么划分寄存器是调用者保存,还是被调用者保存,这是芯片架构的函数调用规范决定的,写C语言的程序员不用感知。想了解RISC-V架构的函数调用规范,可参考文章:《RISC-V架构的函数调用规范和栈布局》

2、异常向量表的访问方式:direct mode、vector mode

3、attribute((interrupt))的作用

__attribute__((interrupt)) void my_interrupt_function(void)
{
	...... //中断处理
	return;
}
  • 在使用中断的vector模式时,需要将中断处理函数写到对应的异常向量表处,当产生中断时,硬件将自动跳转
  • 中断处理就涉及到中断现场的保存和恢复,vector模式的中断处理函数一般C语言写的,那是否需要在中断处理函数里去写保存/恢复中断现场的代码?答案是不需要,只需要在中断处理函数前使用“_attribute_((interrupt))”修饰
  • 作用:编译器将C语言写的中断处理函数翻译成汇编代码时,会自动插入保存/恢复现场的汇编代码。也就是把中断处理函数中会用到的寄存器都先存入栈中,在中断返回前,再从栈里面读出来恢复到寄存器中

4、汇编代码分析

在这里插入图片描述

  • 同样的C语言函数,对比使用/不使用__attribute__((interrupt))修饰得到的反汇编文件
  • 可以看到,使用__attribute__((interrupt))修饰后,汇编代码会多申请栈空间用于保存/恢复现场
  • 函数的返回指令也不一样

5、总结

  • 不使用__attribute__((interrupt))修饰,函数内只需要保存被调用者保存的寄存器
  • 使用__attribute__((interrupt))修饰后,只要在函数内使用到的寄存器都必须保存再恢复,会占用更多的栈空间,翻译得到的汇编代码也会增多
  • 还可以指定中断处理函数的优化等级: __attribute__((interrupt, optimize("O0")))
  • 总结:只有中断处理函数才用__attribute__((interrupt))修饰,其余常规函数不要使用
  • 15
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

正在起飞的蜗牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值