打印
[其他]

发现 HC-IDE 有问题了【已确认,V3.0.2.0请勿使用静态局部变量】

[复制链接]
3160|20
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 chongdongchen 于 2018-5-17 11:26 编辑

是这样的,我有一个局部变量a只会被一个函数f调用,所以是直接在f里面定义成局部变量的。
但是运行不正常!
后来尝试把a定义到f所在的c(c文件)里面,也就是说在f外面了,也是作为局部变量,竟然就正常了!!!!

另外,我使用的是HC-ICE仿真器(OTP单片机),会不会和这个有关?
因为之前就发现这个仿真器仿AD的时候内部参考电压不对,选择内部2V的效果相当于VDD,但实际到芯片时还是要正常选择VDD

谁这么巧也遇到过?


草图.png (45.57 KB )

如图所示,原来是在1处的,现在只能这样了

如图所示,原来是在1处的,现在只能这样了
沙发
xyz549040622| | 2018-5-7 10:00 | 只看该作者
修改下优化,选择不优化试试,如果说这点不正常的话,局部变量多了,都会失效的。

使用特权

评论回复
板凳
chongdongchen|  楼主 | 2018-5-7 19:11 | 只看该作者
xyz549040622 发表于 2018-5-7 10:00
修改下优化,选择不优化试试,如果说这点不正常的话,局部变量多了,都会失效的。 ...

没找到优化选项,这个编译器超级简洁,我想这些功能都还没做进去吧,就一个核心功能而已。

刚刚有发现了,局部变量放在函数内部和放在函数外部两种情况的编译结果是不一样的,代码大小会相差7字节,好怕怕。。

使用特权

评论回复
地板
chongdongchen|  楼主 | 2018-5-7 19:33 | 只看该作者
刚又发现开机时的一个bug,经再一次确认,还是这个原因造成的!
当前这个版本,我劝大家:函数内的局部变量不要用!不要用!不要用!他是非局部的!非局部的!非局部的!

又或者:还是用汇编吧。

使用特权

评论回复
5
xyz549040622| | 2018-5-7 20:01 | 只看该作者
chongdongchen 发表于 2018-5-7 19:33
刚又发现开机时的一个bug,经再一次确认,还是这个原因造成的!
当前这个版本,我劝大家:函数内的局部变量 ...

你这个OTP用的是他们自己的编译器,不是keil吗?那就怪不得了

使用特权

评论回复
6
chongdongchen|  楼主 | 2018-5-7 20:10 | 只看该作者
xyz549040622 发表于 2018-5-7 20:01
你这个OTP用的是他们自己的编译器,不是keil吗?那就怪不得了

是啊,keil应该还不支持

使用特权

评论回复
7
雨后梧桐| | 2018-5-9 08:39 | 只看该作者
AD仿真的我知道,现在AD仿真只能选内参4V使用才对,VDD好像也不行吧,你说的这个BUG问题就不清楚了

使用特权

评论回复
评论
chongdongchen 2018-5-9 22:42 回复TA
AD仿真本来就没打算它能准,偏差点就偏差点,不过我觉得这个参考电压的逻辑不应该搞错啊 
8
黄灵犀| | 2018-5-9 09:10 | 只看该作者
你好,我刚刚用你的源码测试了下,发现编译是没有问题的,可能仿真有点问题,但是不影响程序逻辑的。
因为你在前面加了static,然后编译器给局部变量前面加了修饰符_input_,我当时做C仿真的时候没有考虑到这种情况,所以你仿真的时候可能看不到局部变量的值,但是不影响程序实际的逻辑的。
有问题还请多多沟通,谢谢!

这是我的源码:
typedef unsigned char u8;
static u8 EmissionStrength = 0;
void input (void)
{
static u8 NcIn = 0x23;
EmissionStrength = NcIn;
}

这是编译器编译生成的汇编:

                                     ; compiler-defined variables
                                           ;--------------------------------------------------------
                                           UDL_main_0 udata
                                           _input_NcIn_1_2 res 1
                                           ;--------------------------------------------------------
                                           ; initialized data
                                           ;--------------------------------------------------------
                                           ID_main_0 idata
                                           _EmissionStrength
                                            db 0x00

                                           ; .line 9; "main.c" EmissionStrength = NcIn;
0000c8   112c     movf    0x2c, 0x0         MOVF _input_NcIn_1_2,W
0000c9   19ad     movwf   0x2d              MOVWF _EmissionStrength
0000ca   0002     return                    RETURN

源码.jpg (74.82 KB )

源码.jpg

使用特权

评论回复
9
黄灵犀| | 2018-5-9 10:06 | 只看该作者
chongdongchen 发表于 2018-5-7 19:33
刚又发现开机时的一个bug,经再一次确认,还是这个原因造成的!
当前这个版本,我劝大家:函数内的局部变量 ...

经测试,局部变量的逻辑是没有问题的,编译器只是对它做了优化,例如下面这段代码,编译器会直接跳过这个局部变量

源码:
static u8 byTest = 0x89;
static u8 EmissionStrength = 0;
void main()
{
u8 byData = 0x12;
byData = 0x23;
byData = 0x34;
byData = 0x45;
byData = 0x56;
byData = 0x67;
byData = 0x78;
byData = byTest;
EmissionStrength = byData;
while (1)
{
}
}

汇编:
0000ce   112c     movf    0x2c, 0x0         MOVF _byTest,W
0000cf   19ad     movwf   0x2d              MOVWF _EmissionStrength

使用特权

评论回复
10
chongdongchen|  楼主 | 2018-5-9 22:31 | 只看该作者
黄灵犀 发表于 2018-5-9 09:10
你好,我刚刚用你的源码测试了下,发现编译是没有问题的,可能仿真有点问题,但是不影响程序逻辑的。
因为 ...

问题是我说的那个开机bug,我没有经过仿真器,是直接烧录到单片机里的。
我只是把局部变量移到函数外面就没有这个bug了。

另外一个问题也很奇怪啊:
一个字节的局部变量从函数内部移到外部,编译的代码就大了7字节;
如果两个字节的局部变量移动,那就大了14字节,3个也就21字节,很有规律。
这又是为什么呢,我认为应该是一样的才对,求解(对编译原理不是很懂)。

使用特权

评论回复
11
黄灵犀| | 2018-5-10 14:22 | 只看该作者
chongdongchen 发表于 2018-5-9 22:31
问题是我说的那个开机bug,我没有经过仿真器,是直接烧录到单片机里的。
我只是把局部变量移到函数外面就 ...

你好,针对第一个问题我不是很明白,可以的话能否把源码贴出来,也可以单独联系我。

针对第二个问题,解释如下:
定义的全局变量会在进入main函数之前执行一段初始化的程序,这段程序就是会给全局变量赋初值,这个初值编译器事先是把它记录在ROM里面的,芯片上电运行后就会将ROM里面的值读到那个变量对应的RAM地址里面,这是个循环操作,跟你的变量大小以及个数有关系

使用特权

评论回复
评论
chongdongchen 2018-5-10 20:25 回复TA
函数内的局部变量不也是要初始化吗,那和全局变量的初始化有什么区别呢? 
12
chongdongchen|  楼主 | 2018-5-10 20:19 | 只看该作者
黄灵犀 发表于 2018-5-10 14:22
你好,针对第一个问题我不是很明白,可以的话能否把源码贴出来,也可以单独联系我。

针对第二个问题,解 ...
#include "led.h"

static u8 lastOut = 0;

//就是这个lastOut变量,原来是定义在函数 LedDisplay 里面的
//发现开机时在以下【BUG的地方】明显停留过长的时间(Output一直为0),这个现象通过LED直接能观察到,不用仿真器
//就好像static u8 lastOut = 0;这句失效了的效果,并没有初始化为0,感觉被初始化成200以上的值
//现在我把他移到函数之外,就正常了,看不到那个BUG现象了
//LedDisplay 函数是定时调用的

//LED显示
void LedDisplay (void)
{
        if(Output)
        {
                SET_PORTx_DIR(B,(1 << 1),1);                //这是IO口操作宏定义

                if(lastOut < 13)
                {
                        LED_OUT(1);                        //这是IO口操作宏定义
                }
                else
                {
                        LED_OUT(t_06ms & 1);                //这是IO口操作宏定义
                }
        }
        else
        {
                if(lastOut)
                {
                        SET_PORTx_DIR(B,(1 << 1),0);        //这是IO口操作宏定义        【BUG的地方】
                }
                else
                {
                        SET_PORTx_DIR(B,(1 << 1),1);        //这是IO口操作宏定义
                }
                LED_OUT(0);                                //这是IO口操作宏定义
        }
       
        if(Output)
        {
                if(lastOut < 13) lastOut++;
        }
        else if(lastOut)
        {
                lastOut--;
        }
}


你好,非常感谢这么关注我的问题,这是相关源码(整个工程有多个C文件),请帮忙分析一下。

使用特权

评论回复
13
chongdongchen|  楼主 | 2018-5-10 20:29 | 只看该作者
本帖最后由 chongdongchen 于 2018-5-10 20:31 编辑

我现在有一种感觉就是:
函数内的局部变量(定义时赋初值),编译器没做初始化工作,从而导致这些变量上电时的值是随机的。

使用特权

评论回复
14
黄灵犀| | 2018-5-11 10:22 | 只看该作者
chongdongchen 发表于 2018-5-10 20:29
我现在有一种感觉就是:
函数内的局部变量(定义时赋初值),编译器没做初始化工作,从而导致这些变量上电 ...

你好,局部变量定义时是不会赋值的,它只会在被调用时根据具体情况是否分配RAM空间,有时它只会作为立即数传值,并不占用RAM空间。
所以你无论定义多少个局部变量,只要你不调用它,RAM和ROM空间都不会有变化。
所以仿真时局部变量的值是不支持在WATCH窗口查看的,因为我无法知道它具体的地址。
对于局部变量我们这边有做过测试的,验证下来逻辑是正确的。

你给的代码信息量还是不足哦,我不清楚你Output变量的值会有什么变化,能否邮件给到我所有代码?
我的邮件是chao.huang@holychip.cn
有问题还请及时沟通与联系,我会尽我所能给您详尽解答。

使用特权

评论回复
评论
chongdongchen 2018-5-11 14:13 回复TA
Output变量的值不管是多少,【BUG的地方】也不会停留过长的时间的,所以一上电就能发现BUG。 看代码就知道lastOut最大就13 
15
chongdongchen|  楼主 | 2018-5-11 14:04 | 只看该作者
黄灵犀 发表于 2018-5-11 10:22
你好,局部变量定义时是不会赋值的,它只会在被调用时根据具体情况是否分配RAM空间,有时它只会作为立即 ...

不好意思口误了,我说的是静态局部变量,现在此贴的问题也都是关于静态局部变量,只不过是把它变成静态全局变量就正常了。

给我的感觉就是现在的编译器没有对静态局部变量进行初始化(哪怕我定义时赋初值了)。

你说局部变量定义时不会赋值我能理解,但是如果静态局部变量定义时编译器也不赋初值的话(程序上是有赋初值),那么此贴的问题就得到答案了。

使用特权

评论回复
16
黄灵犀| | 2018-5-17 09:43 | 只看该作者
chongdongchen 发表于 2018-5-11 14:04
不好意思口误了,我说的是静态局部变量,现在此贴的问题也都是关于静态局部变量,只不过是把它变成静态全 ...

您好,您的结论是对的,我们的编译器静态局部变量确实有问题,它不会初始化,再次强制对它赋值也无效,所以当前版本编译器不能支持静态局部变量,我们会考虑解决这个BUG。
非常感谢您在使用过程中给我们提供的反馈,我们会尽快解决这个BUG,对您在使用过程中造成的不便还望谅解。

以下是我的测试分析过程:
测试源码:
unsigned char g_byData0 = 0x25;
static unsigned char g_byData1 = 0x38;
void static_test()
{
static unsigned char s_byData = 0x13;
if (0x10 <= s_byData)
{
  s_byData--;
}
else
{
  s_byData++;
}
}
void main()
{
while (1)
{
  static_test();
}
}

map文件:
_static_test_s_byData_1_1   0x00002c       data     static main.asm
               _g_byData0   0x00002d       data     extern main.asm
               _g_byData1   0x00002e       data     static main.asm

lst文件:
                                           ;--------------------------------------------------------
                                           ; compiler-defined variables
                                           ;--------------------------------------------------------
                                           UDL_main_0 udata
                                           _static_test_s_byData_1_1 res 1
                                           ;--------------------------------------------------------
                                           ; initialized data
                                           ;--------------------------------------------------------
                                           ID_main_0 idata
                                           _g_byData0
                                            db 0x25

                                           ID_main_1 idata
                                           _g_byData1
                                            db 0x38



使用特权

评论回复
评论
chongdongchen 2018-5-17 10:59 回复TA
非常感谢您的解答!也希望芯圣能够越来越强大! 
17
xujunyi3611| | 2018-5-19 17:18 | 只看该作者
话说,一般国产的IDE不成熟,有问题很正常。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

54

主题

1231

帖子

10

粉丝