1a2b3c 发表于 2022-1-16 11:55:50

老司机翻船了,遇到使用静态变量赋初值后跳不出C_START问题请教

请教下面问题:
好几年没用51了,最近将一个通用代码移植到51芯片,
发现程序一直在汇编的初始代码中跳动永远出不来了,具体是下面的地方

               C_STARTUP:
C:0x0000    0286AD   LJMP   C:86AD
....略
C:0x86AD    787F   MOV      R0,#0x7F
C:0x86AF    E4       CLR      A
C:0x86B0    F6       MOV      @R0,A
C:0x86B1    D8FD   DJNZ   R0,C:86B0
C:0x86B3    75815D   MOV      SP(0x81),#0x5D
C:0x86B6    0286F4   LJMP   C_START(C:86F4)
C:0x86B9    024573   LJMP   main(C:4573)

复位后跳转到0x86AD,这里是清片内ram,然后完了又会执行LJMP   C_START(C:86F4),程序就是死在这里面了

查找资料知道这是 执行一些程序内部例如变量初始化的一些操作,实际上是复制一些数据到变量,那么就是这里面永远跳不出来了,我直接将仿真时候指针设置为跳过这一部分,到C:0x86B9    024573   LJMP   main(C:4573)后基本上就能正常运行真正的用户代码了

研究了好几天,发现和自己的程序关系还是很大,因为程序中用了一部全局变量和函数内的局部静态变量,以前不太清楚原来静态变量是默认初始化为零的,而我又在申明静态变量时候初始化为零,例如static unsigned char cnt=0;
不断的调试中发现就是这种代码造成的影响,我试着改成 static unsigned char cnt; 后程序就正常了,那么问题来了,为啥像我这种程序初始化赋值多了以后就不能正常了呢?
另外专门看了程序编译的结果,除了ROM尾部(就是一些常量表格以及初始化变量保存信息的地方)有不同外,其它代码部分编译的结果完全相同, 然后就是并非出现一个我这种赋值的情况就不对,而是多一些,例如5,6个后就不行了.之前在其它芯片上没有这个问题,例如stm32,pic等.

这个问题看看有没有能帮我解惑下,感谢


ps:我没有学过c语言,全靠自学,所以像这种初始化静态变量的问题,我以前也压根不知道无需初始化为0,当然除了需要初始化不为零的除外.

chenchaoting 发表于 2022-1-16 16:58:42

会不会没有添加STARTUP文件

lb0857 发表于 2022-1-16 17:34:56

八九不离十是STARTUP文件原因坐等楼主结果

1a2b3c 发表于 2022-1-16 17:38:24

肯定家了啊,而且你看汇编代码标号都是A51里面的那些标准标签写法,现在还没有找到原因,太奇怪了,会翻到这,虽然不精,但是怎么说多少还是用过了好多种51芯片了:(
继续找原因,

laujc 发表于 2022-1-16 17:57:35

不行就发工程吧{:titter:}

fclose 发表于 2022-1-16 19:34:57

没有研究, 纯臆测: 看门狗?

1a2b3c 发表于 2022-1-19 14:35:58

fclose 发表于 2022-1-16 19:34
没有研究, 纯臆测: 看门狗?


你居然乱猜就猜到了最终的结果,虽然原因肯定不是你想的那样{:lol:}

下面来具体解释一下此次问题,也作为后来者的前车之鉴,我觉得这个问题很具有隐藏性,也很具有普遍性,值得借鉴

经过前面2天的研究,问题原因是这样的:

现在用的这款IC,具有看门狗功能,而这个看门狗是芯片默认开启的,也就是说一但芯片复位,就自动生效了,那么肯定会有人说,你程序里面先关闭看门狗呗,这么简单。是的,作为标题里面说的我自称为“老司机”了你想到的这个问题,我肯定早就想到了,以前用这个芯片,或者其它类似芯片也肯定是这么干的,自己程序的第一条指令就是关闭看门狗!
这种做法在大部分情况下是正常没有任何问题的,可是这次的问题就是出在有较多的初始化信息需要处理,从而导致了事件的发生,

怎么发生的呢?
刚才说了,这款IC是复位就自动启动看门狗,也就是说从 ORG 0000H 位置时,看门狗就开始工作了,那么接下来的任何一条指令都会导致看门狗不停的倒计时,直到。。。处理了太多的初始化信息而导致看门狗溢出。。。于是芯片又从0000H开始执行,有开始进行初始化信息,,,又没有处理完看门狗就溢出了,,,又来。。。。。{:huffy:}

而这个时候用户自己写的代码一句都还没有执行,,,虽然自己main代码第一句就是关闭看门狗。。。
解决办法是在编译器的系统启动代码中增加一条汇编关闭看门狗的指令即可。一切就恢复平静了

总结原因,,是因为不熟悉编译器,以及不熟悉C51代码的编译处理流程,心里面认为自己写的main代码第一句才是代码的第一句,殊不知编译器帮你做了很多基础的工作(虽然以前也知道A51代码里面做了一些类似清内存的处理),特别是以前从汇编转过来的人(例如“老司机”我),自己就是从0000H第一句代码开始写的,所以整个过程怎么做的,做了些啥,自己都清楚,而C51的编译器到底做些啥自己就不清楚了,这就导致了杯具的发生,不过还好,总算彻底的知道了原因,因此也作为后来者的借鉴。

wudicgi 发表于 2022-1-19 14:57:03

1a2b3c 发表于 2022-1-19 14:35
你居然乱猜就猜到了最终的结果,虽然原因肯定不是你想的那样

下面来具体解释一下此次问题,也 ...

能说一下用的是什么 51 芯片吗?这默认看门狗复位的时间也太短了

1a2b3c 发表于 2022-1-20 09:49:11

wudicgi 发表于 2022-1-19 14:57
能说一下用的是什么 51 芯片吗?这默认看门狗复位的时间也太短了

芯科的51系列。虽然十多年前就在用了,都属于正常情况使用,这次特殊点所以才暴露问题

初音之恋 发表于 2022-1-20 11:22:35

看这结论有点坑,一般不会去动Starup文件

tianheyun12 发表于 2022-1-20 12:45:21

C:0x86B6    0286F4   LJMP   C_START(C:86F4),看到连续跳到这个地址,就要去看中断复位向量表了.另外为什么不用C去关闭看门狗,下次新建工程,岂不是还要被坑一次?

1a2b3c 发表于 2022-1-20 15:09:30

tianheyun12 发表于 2022-1-20 12:45
C:0x86B6    0286F4   LJMP   C_START(C:86F4),看到连续跳到这个地址,就要去看中断复位向量表了.另外为 ...

你都没仔细看我的总结,,,,

51向量表都在前面,早就跳过了,这都跳到一半的空间位置了,实际上去是复制初始化变量到内存的处理过程,
总结已经写得和清楚了,个人觉得。至少前面2位是看明白了的哈

1a2b3c 发表于 2022-1-20 15:14:08

tianheyun12 发表于 2022-1-20 12:45
C:0x86B6    0286F4   LJMP   C_START(C:86F4),看到连续跳到这个地址,就要去看中断复位向量表了.另外为 ...

因为光看汇编一条条的去眺指令,根本没法看,因为指令条数太多了(都导致看门狗溢出了),而且没有前面的原因的话,压根都不晓得为啥老是这样,
至于你说c里面关狗,我说的很清楚了啊,我在 main 第一句话就是关狗,也许是我不会用c吧,你要是有方法,赶紧教教,免得后面还走弯路
页: [1]
查看完整版本: 老司机翻船了,遇到使用静态变量赋初值后跳不出C_START问题请教