打印

keil这个报错说什么意思????

[复制链接]
4660|25
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 zzkk1988 于 2010-7-5 16:46 编辑

我在程序里有很多浮点运算   程序没问题

还有我把浮点运算放在中断里了,这有什么不妥吗??

但编译下来  keil  总是报错  

画面如下     什么意思啊??是内存不够用吗???如何改??

还有keil有很多警告啊 ?这警告什么意思啊 晕

图片1.png (111.35 KB )

图片1.png

相关帖子

沙发
ayb_ice| | 2010-7-5 16:53 | 只看该作者
应该是函数不重入引起的

使用特权

评论回复
板凳
oufuqiang| | 2010-7-5 17:02 | 只看该作者
版本问题啊,所超出版本限制。**一下?

使用特权

评论回复
地板
ayb_ice| | 2010-7-5 17:05 | 只看该作者
LS

不要乱说

有个方法可以解决

再建立一个函数,功能与原函数一样,在中断中调用即可

使用特权

评论回复
5
原野之狼| | 2010-7-5 19:41 | 只看该作者
LS 正解
或者在调用这个函数前禁止下中断执行完后再开放中断

使用特权

评论回复
6
wangzk| | 2010-7-6 10:07 | 只看该作者
什么是函数不重入啊 ???

使用特权

评论回复
7
zq1987731| | 2010-7-6 10:25 | 只看该作者
LS,主程序中正在调用子程序A且未返回时,中断中再次调用了该子程序,你觉得会怎样呢...

一般解决方法:
1,ayb_ice的方法可以避免该警告,最为推荐的做法
2,中断ISR采用其余寄存器组,那么在该嵌套调用中不至于破坏原先处理到一半的状态,此处需要注意关闭寄存器绝对寻址
3,用reentrant,这样会从0xFF(默认)开始倒向模拟一个堆栈,用以处理可重入问题

使用特权

评论回复
8
wangzk| | 2010-7-6 11:14 | 只看该作者
听得云里雾去啊  不是很明白 7# zq1987731

使用特权

评论回复
9
yuyetufu| | 2010-7-6 12:26 | 只看该作者
就是一个函数同时被调用,C51默认是不允许的。一定这么做的话,需要在函数前加reentrant关键词

使用特权

评论回复
10
zq1987731| | 2010-7-6 13:09 | 只看该作者
本帖最后由 zq1987731 于 2010-7-6 13:12 编辑

之所以在7楼把reentrant的方法放在最后...主要是因为花费太大,得不偿失
不考虑中断清标志位等等乱七八糟事情,举个临时想到未经验证的例子来说:
UINT8 function(UINT8 x)
{
      x++;
      _nop_();    //①
      x++;
      return x;
}
上面这个子程序被主程序执行时,比如有如下调用关系:
void main(void)
{
      UINT8 mTmp = 10;
      function(mTmp);    //②
      while(1);
}
同时还有如下中断ISR:
void ISR(void) interrupt X
{
      UINT8 iTmp = 20;
      function(iTmp);     //③          
}
那么在如上条件时,主程序main运行至②时调用了function,假设在function中的①处中断事件产生,那么:
在响应中断前,function的“现场“会被保护进堆栈,即A、B、PSW、DPTR,此时由于系统默认使用0组寄存器,那么R7中就是形参mTmp,该值被增加了1,于是运行至_nop_();处,中断产生,由于中断使用的同为第0组寄存器(默认),那么它便将形参iTmp送入,R7由原来的11被改变为20,那么③执行完毕后该函数的返回值为22,然后将A、B、PSW、DPTR进行出栈处理(恢复现场)。
此时中断ISR处理完毕跳转回被打断的①处,mTmp的值即R7的值被意外得改变为22,执行完x++;后②的返回值本该为12,结果成了23...
解决方法么....................
1)换个寄存器组,同时为避免寄存器绝对寻址产生问题,特别处理一下
#pragma NOAREGS
UINT8 function(UINT8 x)
{
      x++;
      _nop_();
      x++;
      return x;
}
#pragma AREGS

void main(void)
{
      UINT8 mTmp = 10;
      function(mTmp);
      while(1);
}

void ISR(void) interrupt X using 1
{
      UINT8 iTmp = 20;
      function(iTmp);           
}

2)在function执行过程中对中断不予响应
#pragma disable
UINT8 function(UINT8 x)
{
      x++;
      _nop_();
      x++;
      return x;
}

void main(void)
{
      UINT8 mTmp = 10;
      function(mTmp);
      while(1);
}

void ISR(void) interrupt X
{
      UINT8 iTmp = 20;
      function(iTmp);           
}

3)加reentrant的方式,注意startup中的配置,此时的主程序与ISR中调用的虽为同一函数,但变量空间无交集,效率奇低不推荐
UINT8 function(UINT8 x) reentrant
{
      x++;
      _nop_();
      x++;
      return x;
}

void main(void)
{
      UINT8 mTmp = 10;
      function(mTmp);
      while(1);
}

void ISR(void) interrupt X
{
      UINT8 iTmp = 20;
      function(iTmp);           
}

使用特权

评论回复
11
sheriff| | 2010-7-6 13:27 | 只看该作者
7楼的方法2和10楼的方法1在理论上是有问题的,因为局部变量不只是使用寄存器的,keil的函数如果不声明为reentrant,在局部变量较多的时候编译器会把局部变量定位在RAM里。

使用特权

评论回复
12
btiger2000| | 2010-7-6 14:21 | 只看该作者
警告是重入问题;错误是代码限制,需要和谐下

使用特权

评论回复
13
wangzk| | 2010-7-6 14:25 | 只看该作者
to  tiger2000:是keil编译的代码限制??

使用特权

评论回复
14
btiger2000| | 2010-7-6 14:35 | 只看该作者
demo版

使用特权

评论回复
15
zq1987731| | 2010-7-6 15:32 | 只看该作者
之所以不考虑
在局部变量较多的时候编译器会把局部变量定位在RAM里

是因为对于【51这个“小东西”】从程序架构上以及实时性上来说,中断的ISR顶多就是处理些标志位,外加简单的功能,能在里面用到超过3个参量导致需要动用外部RAM的,其程序本身就是个大问题...
另外reentrant不如函数副本方法的原因...大家可以注意下startup.a51中
“Reentrant Stack Initialization”下的内容,由0xFF向下生长的堆栈,倘若你的程序比较庞大,IDATA区占用空间与reentrant空间产生冲突的话,死都不知道怎么死的

使用特权

评论回复
16
sheriff| | 2010-7-6 15:44 | 只看该作者
之所以不考虑
是因为对于【51这个“小东西”】从程序架构上以及实时性上来说,中断的ISR顶多就是处理些标志位,外加简单的功能,能在里面用到超过3个参量导致需要动用外部RAM的,其程序本身就是个大问题...
zq1987731 发表于 2010-7-6 15:32

“能在里面用到超过3个参量导致需要动用外部RAM的,其程序本身就是个大问题”
太牵强了,没有说服力。没有人规定在ISR里应该干什么,不能干什么。。。这得根据具体的应用来说。

使用特权

评论回复
17
ayb_ice| | 2010-7-6 15:53 | 只看该作者
KEIL重入reentrant关键字没有那么可怕
效率是会低些,有限使用是没有什么问题的,IAR编译器用的都是模拟堆栈,用的人也很多,据说效率也不低
当然针对KEIL,不建议在中断中调用reentrant声明的函数,特别是频繁的中断
模拟模拟是可以配置的,甚至3个区域<idata,pdata,xdata>都可以同时使用,定义声明好函数即可
...

使用特权

评论回复
18
zq1987731| | 2010-7-6 16:38 | 只看该作者
呵呵~~
没有人规定在ISR里应该干什么,不能干什么。。。这得根据具体的应用来说

比较同意,各人风格不同,当年学校里...我甚至看见同学们在ISR里放delayms(10);
关于这问题...毕竟是警告不是错误,如果对自己采取的方法所能造成的一切后果都了如指掌,那么完全可以无视掉该警告了...

使用特权

评论回复
19
wangzk| | 2010-7-6 16:50 | 只看该作者
呵呵呵   谢谢大家的讨论   现在又长了些见识!!:)

使用特权

评论回复
20
mbutterfly| | 2010-7-6 17:02 | 只看该作者
4楼的方法以前用过,如果程序存储器空间够用,这种办法很省事管用。

使用特权

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

本版积分规则

0

主题

7

帖子

1

粉丝