OpenEdv-开源电子网

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

求助个貌似很简单但很奇怪的全局变量问题

[复制链接]

1

主题

18

帖子

0

精华

高级会员

Rank: 4

积分
542
金钱
542
注册时间
2022-7-10
在线时间
58 小时
发表于 2024-6-5 09:37:02 | 显示全部楼层 |阅读模式
20金钱
背景:
    (512K+64K)STM32 RTOS代码(实则貌似和RTOS无关)。在main源文件增加个全局变量并且只是在main函数一开始就简单赋值一下,结果程序就崩了,但去掉是正常的。
实测了好几个源文件类似的操作,大部分都会有这种现象。
    调试在main函数经过该全局变量是正常的,确实是崩在了RTOS任务中,但调试器有点奇怪正常程序有时候都起不来所以这个调试感觉不太靠谱看不出什么。
    网上搜过这方面的可能原因,大致有以下几个排查也貌似对不上
    1、全局变量共享。这个不搭边吧,真的只是在main函数简单赋值一下,总共就定义+赋值两句话!!
    2、堆栈溢出。不应该,只是1字节的全局变量,看了map地址正常,而且启动文件的堆、栈、RTOS的任务栈、总RAM我都试过增加了在不超出64kRAM的情况下。
    3、优先级问题。一些中断优先级比RTOS的优先级高不受控制之类的,更不涉及了,而且原来代码就是正常运行的
    4、内存对齐。这个是也是一开始最倾向怀疑的,但我对比了map实在找不出问题。截图在附件
    有没有大佬指点下方向,实在郁闷这问题,看上去应该是很简单的操作,拜托了十分感谢!!!
微信图片_20240605091244.png

最佳答案

查看完整内容[请看2#楼]

破案了。原来是设置中断向量表VTOR的问题,调试时习惯性把起始地址设为0x08000000,和代码默认的中断向量表偏移是不对应了,所以才会出现奇奇怪怪的问题。核心问题就是代码下载到flash的起始地址要和VTOR对应,不管是0x08000000还是0x08010800。附件是正确配置之一。 还是认识不够深刻所以完全没联想到原因在这里,踩坑了这波,最后还是感谢各位给出的排查方向。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

18

帖子

0

精华

高级会员

Rank: 4

积分
542
金钱
542
注册时间
2022-7-10
在线时间
58 小时
 楼主| 发表于 2024-6-5 09:37:03 | 显示全部楼层
        破案了。原来是设置中断向量表VTOR的问题,调试时习惯性把起始地址设为0x08000000,和代码默认的中断向量表偏移是不对应了,所以才会出现奇奇怪怪的问题。核心问题就是代码下载到flash的起始地址要和VTOR对应,不管是0x08000000还是0x08010800。附件是正确配置之一。
        还是认识不够深刻所以完全没联想到原因在这里,踩坑了这波,最后还是感谢各位给出的排查方向。


文档.png
回复

使用道具 举报

5

主题

66

帖子

0

精华

初级会员

Rank: 2

积分
194
金钱
194
注册时间
2023-6-26
在线时间
53 小时
发表于 2024-6-5 11:20:54 | 显示全部楼层
全局RTOS要加保护,关中断,赋值,再开中断
回复

使用道具 举报

1

主题

18

帖子

0

精华

高级会员

Rank: 4

积分
542
金钱
542
注册时间
2022-7-10
在线时间
58 小时
 楼主| 发表于 2024-6-5 11:55:15 | 显示全部楼层
HelloSiri 发表于 2024-6-5 11:20
全局RTOS要加保护,关中断,赋值,再开中断

但是并没有在任务之间共享使用也需要吗?甚至都没有放任务中使用
回复

使用道具 举报

10

主题

3281

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8184
金钱
8184
注册时间
2020-5-11
在线时间
3697 小时
发表于 2024-6-5 13:47:43 | 显示全部楼层
可能问题不在于全局变量,而是在别处,这个全局变量诱发了问题。
建议加上全局变量后,删除一些代码来作排查。
比如某些变量未赋初值,在作为数组下标时可能越界,而增加变量后这个未赋初值的变量存放位置不同,
形成了不同的初值。
专治疑难杂症
回复

使用道具 举报

4

主题

881

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4195
金钱
4195
注册时间
2019-9-4
在线时间
881 小时
发表于 2024-6-5 15:55:54 | 显示全部楼层
定义了全局变量,赋值之后就崩了。可能是这个全局变量跟其他地方有冲突,你定义变量之后不要赋值,跑仿真看下变量的值。正常来说全局变量定义不赋值的话,值应该是0的,看下值对不对。如果值不是0,应该就是这块内存不止申请给了全局变量,应该还在其他地方也被使用了,去找一下是哪里
回复

使用道具 举报

1

主题

18

帖子

0

精华

高级会员

Rank: 4

积分
542
金钱
542
注册时间
2022-7-10
在线时间
58 小时
 楼主| 发表于 2024-6-5 17:00:03 | 显示全部楼层
LcwSwust 发表于 2024-6-5 13:47
可能问题不在于全局变量,而是在别处,这个全局变量诱发了问题。
建议加上全局变量后,删除一些代码来作排 ...

感觉方向是对了,试了不少发现如果全局变量放在data段就很大概率崩,我从最后一个放在bss的全局变量往上放的话开始还正常,逐渐地放在到某个变量之前又继续崩了,可能真的是影响了某些bss全局变量的初值。继续排除中。。
回复

使用道具 举报

1

主题

18

帖子

0

精华

高级会员

Rank: 4

积分
542
金钱
542
注册时间
2022-7-10
在线时间
58 小时
 楼主| 发表于 2024-6-5 17:02:37 | 显示全部楼层
A571157242 发表于 2024-6-5 15:55
定义了全局变量,赋值之后就崩了。可能是这个全局变量跟其他地方有冲突,你定义变量之后不要赋值,跑仿真看 ...

定义不赋值是没有分配内存的,map里找不到哪怕初始化了初值。这问题方向更像是楼上说的,还在继续排查中
回复

使用道具 举报

10

主题

3281

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8184
金钱
8184
注册时间
2020-5-11
在线时间
3697 小时
发表于 2024-6-5 17:17:06 | 显示全部楼层
这里还有一个类似的例子,现象是"变量位置不同会死机",原因是指针未赋初值就往里写,参考一下:
https://bbs.21ic.com/icview-3382032-1-1.html
专治疑难杂症
回复

使用道具 举报

2

主题

446

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4133
金钱
4133
注册时间
2018-5-14
在线时间
902 小时
发表于 2024-6-6 08:53:31 | 显示全部楼层
你有没有数组或者内存区域是指定的地址,有可能会出现
char* heap=0x20000000;
HEAP_SIZE=1024;
但是编译器不知道你这个地址是被使用的,你再定义一个全局变量 gobal;
gobal会存放在0x20000004这个位置,当你向gobal写值时,rtos使用的某个变量(更有可能是指针)正好地址也是0x20000004,导致指针变成了无效指针,然后就hardfault了
回复

使用道具 举报

1

主题

18

帖子

0

精华

高级会员

Rank: 4

积分
542
金钱
542
注册时间
2022-7-10
在线时间
58 小时
 楼主| 发表于 2024-6-6 12:32:09 | 显示全部楼层
本帖最后由 Matima007 于 2024-6-6 12:36 编辑
LcwSwust 发表于 2024-6-5 17:17
这里还有一个类似的例子,现象是"变量位置不同会死机",原因是指针未赋初值就往里写,参考一下:
https://bbs. ...

    好像是调试器的坑。。。
    我一直使用界面download或者jflash直接下载,一直都是增加全局变量就大概率崩,偶尔download正常程序也会崩不过我以为是flash锁死导致没太在意,往往断电或者重刷flash就恢复正常了,上午发现正常程序一直download都不行,反复断电重刷都不行,很是莫名其妙。
   于是我就换了usb转can写入的方式,这是发布版本的升级方式,和界面download唯一的区别就是这个带bootloader,也就是download的app地址是0x08000000,这种方式的app地址是0x08010800。结果发现根本没有异常哦,随便增加全局变量都没问题。。。
    再说这Jlink调试就莫名其妙,往往就跑飞了,应该关系极大吧
回复

使用道具 举报

1

主题

18

帖子

0

精华

高级会员

Rank: 4

积分
542
金钱
542
注册时间
2022-7-10
在线时间
58 小时
 楼主| 发表于 2024-6-6 12:38:25 | 显示全部楼层
姚先起 发表于 2024-6-6 08:53
你有没有数组或者内存区域是指定的地址,有可能会出现
char* heap=0x20000000;
HEAP_SIZE=1024;

没有这种情况,所有全局变量我都查看了。应该是调试器的锅吧,上面有回复
回复

使用道具 举报

2

主题

446

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4133
金钱
4133
注册时间
2018-5-14
在线时间
902 小时
发表于 2024-6-6 12:46:46 | 显示全部楼层
Matima007 发表于 2024-6-6 12:38
没有这种情况,所有全局变量我都查看了。应该是调试器的锅吧,上面有回复

调试器的锅我还真没遇到过你这种情况,淘宝100来块的Jlink用了7-8年了,有点不敢置信
回复

使用道具 举报

1

主题

18

帖子

0

精华

高级会员

Rank: 4

积分
542
金钱
542
注册时间
2022-7-10
在线时间
58 小时
 楼主| 发表于 2024-6-6 15:46:09 | 显示全部楼层
姚先起 发表于 2024-6-6 12:46
调试器的锅我还真没遇到过你这种情况,淘宝100来块的Jlink用了7-8年了,有点不敢置信

上面回复的帖子还没审核通过发出来。
情况大概是这样,增加全局变量时(就定义+赋值两句话很简单),通过JLINK烧到0x08000000时很大可能就会起不来,换了几个都是这种情况。
但是通过usb写入,这种方式会多个bootloader,app起始地址变为0x08010080,随便增加使用全局变量都是正常的。
暂时归咎于JLINK的问题吧,也许还是影响了内存什么的吧,还是倾向相信JLINK没那么容易出问题
回复

使用道具 举报

4

主题

881

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4195
金钱
4195
注册时间
2019-9-4
在线时间
881 小时
发表于 2024-6-11 16:36:41 | 显示全部楼层
Matima007 发表于 2024-6-5 17:02
定义不赋值是没有分配内存的,map里找不到哪怕初始化了初值。这问题方向更像是楼上说的,还在继续排查中

我印象中,C语言定义了一个全局变量,不管你是否使用,编译器都会开辟一个空间给这个变量的,全局变量没有初始化的情况下,编译器默认给的初值为0
回复

使用道具 举报

1

主题

18

帖子

0

精华

高级会员

Rank: 4

积分
542
金钱
542
注册时间
2022-7-10
在线时间
58 小时
 楼主| 发表于 2024-6-11 21:04:14 | 显示全部楼层
A571157242 发表于 2024-6-11 16:36
我印象中,C语言定义了一个全局变量,不管你是否使用,编译器都会开辟一个空间给这个变量的,全局变量没 ...

keil编译器的优化问题吧,毕竟mcu的内存很小,以map文件为准
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-11-22 11:07

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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