OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 1144|回复: 11

记录贴,自定义中断返回位置

[复制链接]

54

主题

347

帖子

0

精华

高级会员

Rank: 4

积分
948
金钱
948
注册时间
2022-4-20
在线时间
356 小时
发表于 2023-12-26 16:25:26 | 显示全部楼层 |阅读模式
本帖最后由 驭剑的秘密 于 2023-12-28 11:29 编辑
在去年,我提了一个问【点击查看】最近又看见了类似的问题,但是再次打开我当时的帖子时,已经忘记是怎么做的了,于是在此进行记录与分享。

果然,一个人的能力是有限的,将代码分享出来之后,很快朋友就发现了问题。
更新记录:


2023.12.28        在频繁触发目标中断之后,会导致栈溢出,所以增加了栈空间的回收。现在,使用的栈区将恢复到调用GET_lr函数前的大小。
                        此外,GET_lr的调用,会导致在其之后被重复使用的所有局部变量都失效,建议调用完GET_lr后,重新初始化局部变量,  全局变量不受影响。



功能:    使得程序在某个中断执行完毕后,返回到一个自定义的位置继续执行。
原因:    在当时的程序中,希望能够不经过复位(太前面了)、break和continue(这两个必须执行循环内的剩余代码,太靠后了),就返回到一个循环的开始处。于是乎,就产生了这样一个想法。
示例:    在某个工程中,main函数有100条代码,第10条处完成了所有初始化内容,接下来进入了while循环。中断的到来是一个不确定因素,无法得知其在第几条代码处进入和返回,但恰好需要在返回后更快地执行下一个循环,而不是继续执行返回处后方的剩余代码。


先附上代码,这是.s文件中的代码内容:

游客,如果您要查看本帖隐藏内容请回复


在某个.h文件中(一般是中断),需要有以下声明:
  1. extern void GET_lr(uint32_t addr1,uint32_t addr2,uint32_t addr3);
  2. extern void SET_lr(uint32_t addr1,uint32_t addr2,uint32_t addr3);
复制代码

再定义两个全局变量,用于存储返回的位置:
  1. uint32_t P_lr,P_pc,P_sp;
复制代码
接下来是对于返回位置的设置,直接将其放在要返回的位置,这个位置可以理解为搭配goto使用的标签,一般都放在主函数的循环开始之前:
  1.     //传入的参数是三个全局变量的地址,强转为unsigned int 类型再传入
  2.     //第一个用于存储LR的值,第二个用于存储PC的值,第三个用于存储MSP的初始值
  3.     GET_lr((uint32_t)&P_lr, (uint32_t)&P_pc, (uint32_t)&P_sp);
复制代码

最后是设置目标中断
注意:   这个中断尽量是处于嵌套的最外层,否则可能会改变某些参数。
具体情况需要结合.s文件中的注释进行改变。例如:随便打开一个带有中断的例程,进入调试,查看其Disassembly窗口,得到下图:
微信截图_20231226155805.png

可以看见在中断入口处,r4和lr被压栈。
而有的中断入口处并不止压栈这两个寄存器,所以需要结合上方.s文件中的代码和注释进行调整,在这个例子中,无需更改。
现在,就可以把SET_lr函数放在中断入口或出口处进行调用:
  1.     //传入的参数为三个,第一个是LR的值,第二个是PC的值,第三个是MSP的值
  2.     SET_lr(P_lr, P_pc, P_sp);
复制代码




以上就是我对于此功能的实现方法,请多多指教。
相关资料:《Cortex-M3 权威指南
》第9章





又菜又爱指点
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

451

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3316
金钱
3316
注册时间
2016-3-19
在线时间
815 小时
发表于 2023-12-26 16:51:34 | 显示全部楼层
回复 支持 反对

使用道具 举报

0

主题

451

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3316
金钱
3316
注册时间
2016-3-19
在线时间
815 小时
发表于 2023-12-26 16:52:47 | 显示全部楼层
汇编语言实现起来相对容易一些

如果再弄个纯C语言的  就更好了

谢谢分享
Nothing is impossible
回复 支持 反对

使用道具 举报

54

主题

347

帖子

0

精华

高级会员

Rank: 4

积分
948
金钱
948
注册时间
2022-4-20
在线时间
356 小时
 楼主| 发表于 2023-12-27 09:47:18 | 显示全部楼层
unnormal 发表于 2023-12-26 16:52
汇编语言实现起来相对容易一些

如果再弄个纯C语言的  就更好了

原本就是想用C解决,结果发现我不会
又菜又爱指点
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2023-12-27 22:45:57 | 显示全部楼层
不错, 谢谢分享
回复 支持 反对

使用道具 举报

3

主题

1906

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4100
金钱
4100
注册时间
2018-8-14
在线时间
695 小时
发表于 2023-12-28 15:37:00 | 显示全部楼层
我在另一帖说过,进入一函数后, 会有很多情况下会有压栈的动作, 比如局部变量, 比如计算过程中过多暂时变量, 都会有压栈的动作,而恰恰这些压栈动作都不能从C代码中得知, 而不管压栈硬把返回地址改掉, 栈必定会出问题, 类似堆的内存泄漏, 时间久了就必然栈溢出。

如果说非要实现这要求, 我的建议是把这循环放在另一函数,此函数只放循环的代码, 确保它除了返回地址没有其他压栈的动作, 这时候在中断改返回地址就不会出问题。
回复 支持 反对

使用道具 举报

0

主题

451

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3316
金钱
3316
注册时间
2016-3-19
在线时间
815 小时
发表于 2023-12-28 16:05:30 | 显示全部楼层
edmund1234 发表于 2023-12-28 15:37
我在另一帖说过,进入一函数后, 会有很多情况下会有压栈的动作, 比如局部变量, 比如计算过程中过多暂时 ...

而恰恰这些压栈动作都不能从C代码中得知

如果确定是这样的话  我就不去考虑C语言的实现了

因为汇编更好实现一些   
Nothing is impossible
回复 支持 反对

使用道具 举报

0

主题

451

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3316
金钱
3316
注册时间
2016-3-19
在线时间
815 小时
发表于 2023-12-28 16:06:40 | 显示全部楼层
edmund1234 发表于 2023-12-28 15:37
我在另一帖说过,进入一函数后, 会有很多情况下会有压栈的动作, 比如局部变量, 比如计算过程中过多暂时 ...

您说的这个问题必须处理

不处理的话  只能简单实现功能   而不能实现运用到项目中去
Nothing is impossible
回复 支持 反对

使用道具 举报

0

主题

451

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3316
金钱
3316
注册时间
2016-3-19
在线时间
815 小时
发表于 2023-12-28 16:16:00 | 显示全部楼层
edmund1234 发表于 2023-12-28 15:37
我在另一帖说过,进入一函数后, 会有很多情况下会有压栈的动作, 比如局部变量, 比如计算过程中过多暂时 ...

您建议我看看freertos

我确认了一下

我看的是 ARM_CM3  的

C语言处理栈的操作  是模拟初始任务栈时进行的操作  而且是通过指针进行赋值操作

其它的和现场相关的操作  也是通过汇编来实现的

还有一点就是RTOS的任务栈是各自独立的  与裸机多少有些不同

裸机共用栈

但是最终如果不处理   都会导致栈不够用
Nothing is impossible
回复 支持 反对

使用道具 举报

0

主题

451

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3316
金钱
3316
注册时间
2016-3-19
在线时间
815 小时
发表于 2023-12-28 16:18:16 | 显示全部楼层
edmund1234 发表于 2023-12-28 15:37
我在另一帖说过,进入一函数后, 会有很多情况下会有压栈的动作, 比如局部变量, 比如计算过程中过多暂时 ...

您提供的思路可以解决这个问题

不过我觉得  既然已经使用了汇编  不如都用汇编解决了   岂不是更方便啊

  
Nothing is impossible
回复 支持 反对

使用道具 举报

54

主题

347

帖子

0

精华

高级会员

Rank: 4

积分
948
金钱
948
注册时间
2022-4-20
在线时间
356 小时
 楼主| 发表于 2023-12-29 09:41:20 | 显示全部楼层
edmund1234 发表于 2023-12-28 15:37
我在另一帖说过,进入一函数后, 会有很多情况下会有压栈的动作, 比如局部变量, 比如计算过程中过多暂时 ...

我使用的场景在循环里就没有各种压栈出栈,但是我把这代码拿给朋友看,他的循环里面很多调用的函数,就导致了如果经常在调用之后触发中断,势必会溢出,所以还得看使用者的用法,并不可以像我写的那样无脑用
又菜又爱指点
回复 支持 反对

使用道具 举报

54

主题

347

帖子

0

精华

高级会员

Rank: 4

积分
948
金钱
948
注册时间
2022-4-20
在线时间
356 小时
 楼主| 发表于 2023-12-29 09:43:23 | 显示全部楼层
所以开源的好处就在这了,要搁我自己用,永远都发现不了这个问题
又菜又爱指点
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 12:58

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表