打印
[AVR单片机]

5.11如何**?

[复制链接]
2744|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
mxh0506|  楼主 | 2008-10-24 11:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
看看,两种循环结构,编译后的结果大相径庭:
第一种,由于改变了关中断,开中断的操作顺序,导致不能工作:

                             while(SPMCSR & RWWSB)
    403                      {
    404                         cli();
    405                         SPMCSR = (1 << RWWSRE)|(1 << SPMEN);
                                  ??main_1:
      0000007E   E101               LDI     R16, 17
      00000080   93000068           STS     104, R16
    406                         asm("spm");
      00000084   95E8               spm
    407                      sei();
      00000086   9478               SEI
    408                   }
                                  ??main_2:
      00000088   91000068           LDS     R16, 104
      0000008C   7006               ANDI    R16, 0x06
      0000008E   94F8               CLI
      00000090   F7B1               BRNE    ??main_1  

  改成do{}while(xx)后,问题解决:
                             do{
    403                  cli();
                                  ??main_2:
      0000008A   94F8               CLI
    404                      SPMCSR = (1 << RWWSRE)|(1 << SPMEN);
      0000008C   E101               LDI     R16, 17
      0000008E   93000068           STS     104, R16
    405                         asm("spm");
      00000092   95E8               spm
    406                      sei();
      00000094   9478               SEI
    407                      }while(SPMCSR & RWWSB);
      00000096   91000068           LDS     R16, 104
      0000009A   7006               ANDI    R16, 0x06
      0000009C   F7B1               BRNE    ??main_2

相关帖子

沙发
avr| | 2008-10-24 12:17 | 只看该作者

你再看看while(SPMCSR & RWWSB)前面一段

你再看看while(SPMCSR & RWWSB)前面一段,看是从哪个点开始执行的.

使用特权

评论回复
板凳
mxh0506|  楼主 | 2008-10-24 17:09 | 只看该作者

前面是WDT初始化

这是main()函数开头的一段.

使用特权

评论回复
地板
avr| | 2008-10-24 17:41 | 只看该作者

按while的语法,应该是从??main_2先执行才对.

使用特权

评论回复
5
dudongdao| | 2008-10-24 18:39 | 只看该作者

AVR,无论从哪执行,那为什么第一种不能工作呢

第一种为什么不能工作呢?  还有,楼主你看一下你上面的程序是调到min_2 还是main_1.
第一种怎么看都怪,那个CLI是不是应该编译到BRNE    ??main_1 的后面去?

使用特权

评论回复
6
mxh0506|  楼主 | 2008-10-24 22:38 | 只看该作者

如果直接调到main_2也是不对的

本来while(){}循环的意图是满足条件才做循环体里的操作,如果直接跳到main_2开始执行,判断条件之前就关了中断(即执行了循环体中的一部分操作!),如果条件不满足,BRNE    ??main_1不会继续跳到main_1,而是跳出循环,执行下面的操作,结果是关了中断,却不再开中断,与C源程序的本义也是不符的.

使用特权

评论回复
7
dtmcp| | 2008-10-25 08:00 | 只看该作者

5.11如何**?

5.11如何破解?

使用特权

评论回复
8
avr| | 2008-10-25 08:54 | 只看该作者

这也是511B编译的结果,好象并没有问题。


#include <iom128.h>
void main(void)
{
  while(SPMCSR & RWWSB)
  {
    asm("cli");  
    SPMCSR = (1 << RWWSRE)|(1 << SPMEN);
    asm("spm");
    asm("sei");  
    
  }
  
  while(1)
  {
  ;
  }
}


     2          void main(void)
                        main:
      3          {
      00000000   C006               RJMP    ??main_0
      4            while(SPMCSR & RWWSB)
      5            {
      6              asm("cli");  
                        ??main_1:
      00000002   94F8               cli
      7              SPMCSR = (1 << RWWSRE)|(1 << SPMEN);
      00000004   E101               LDI     R16, 17
      00000006   93000068           STS     104, R16
      8              asm("spm");
      0000000A   95E8               spm
      9              asm("sei");  
      0000000C   9478               sei
     10              
     11            }
                        ??main_0:
      0000000E   91000068           LDS     R16, 104
      00000012   7006               ANDI    R16, 0x06
      00000014   2300               TST     R16
      00000016   F7A9               BRNE    ??main_1
     12            
     13            while(1)
                        ??main_2:
      00000018   CFFF               RJMP    ??main_2
      0000001A                      REQUIRE _A_SPMCSR
     14            {
     15            ;
     16            }
     17          }

使用特权

评论回复
9
avr| | 2008-10-25 08:57 | 只看该作者

LZ应该检查一下自己的写法

LZ应该检查一下自己的写法,对编译器来讲,要尽可能简单,使用编译器推荐的语法,cli和sei两条指令的实现IAR有定义好的本征函数的。

使用特权

评论回复
10
avr| | 2008-10-25 09:02 | 只看该作者

这种写法也是同样的编译结果,Z9优化

#include <iom128.h>
#define cli()       asm("cli")
#define sei()       asm("sei")
void main(void)
{
  while(SPMCSR & RWWSB)
  {
    cli();  
    SPMCSR = (1 << RWWSRE)|(1 << SPMEN);
    asm("spm");
    sei();  
    
  }
  
  while(1)
  {
  ;
  }
}

     4          void main(void)
                        main:
      5          {
      00000000   C006               RJMP    ??main_0
      6            while(SPMCSR & RWWSB)
      7            {
      8              cli();  
                        ??main_1:
      00000002   94F8               cli
      9              SPMCSR = (1 << RWWSRE)|(1 << SPMEN);
      00000004   E101               LDI     R16, 17
      00000006   93000068           STS     104, R16
     10              asm("spm");
      0000000A   95E8               spm
     11              sei();  
      0000000C   9478               sei
     12              
     13            }
                        ??main_0:
      0000000E   91000068           LDS     R16, 104
      00000012   7006               ANDI    R16, 0x06
      00000014   F7B1               BRNE    ??main_1
     14            
     15            while(1)
                        ??main_2:
      00000016   CFFF               RJMP    ??main_2
      00000018                      REQUIRE _A_SPMCSR
     16            {
     17            ;
     18            }
     19          }

使用特权

评论回复
11
dudongdao| | 2008-10-25 20:02 | 只看该作者

楼主,你是不是呆着没事调戏大家哪,我也

F:panmeifangstydy1main.c
      1          #include <iom128.h>

                                    In segment ABSOLUTE, at 0x68
      union <unnamed> volatile __io _A_SPMCSR
                        _A_SPMCSR:
      00000000                      DS 1
      2          #define    SPMIE    7
      3          #define    RWWSB    6
      4          #define    RWWSRE   4
      5          #define    BLBSET   3
      6          #define    PGWRT    2
      7          #define    PGERS    1
      8          #define    SPMEN    0

                                    In segment CODE, align 2, keep-with-next
      9          void main(void)
                        main:
     10          {
      00000000   C006               RJMP    ??main_0
     11            while(SPMCSR & RWWSB)
     12            {
     13              asm("cli");  
                        ??main_1:
      00000002   94F8               cli
     14              SPMCSR = (1 << RWWSRE)|(1 << SPMEN);
      00000004   E101               LDI     R16, 17
      00000006   93000068           STS     104, R16
     15              asm("spm");
      0000000A   95E8               spm
     16              asm("sei");  
      0000000C   9478               sei
     17              
     18            }
                        ??main_0:
      0000000E   91000068           LDS     R16, 104
      00000012   7006               ANDI    R16, 0x06
      00000014   F7B1               BRNE    ??main_1
     19          }
      00000016   9508               RET

使用特权

评论回复
12
mxh0506|  楼主 | 2008-10-26 10:15 | 只看该作者

我想结果不同的原因是:

楼上两位用的是行间汇编实现开/关中断,而我用的是IAR的intrinsic funtions, 即:
#define sei        __enable_interrupt
#define    cli        __disable_interrupt
之所以这样做,是因为这段程序原来是用GCC写的,移植时为了方便才定义成宏.
而行间汇编是影响编译器的优化结果的
我用的优化选项是最高速度

使用特权

评论回复
13
avr| | 2008-10-26 18:13 | 只看该作者

再来一个S9的,同样使用intrinsic funtions

#include <iom128.h>
#include <inavr.h>
#define cli()      __disable_interrupt() 
#define sei()      __enable_interrupt()

void main(void)
{
  while(SPMCSR & RWWSB)
  {
    cli();  
    SPMCSR = (1 << RWWSRE)|(1 << SPMEN);
    asm("spm");
    sei();  
    
  }
  
  while(1)
  {
  ;
  }
}

      1          #include <iom128.h>

                                    In  segment ABSOLUTE, at 0x68
      <unnamed> volatile __io _A_SPMCSR
                        _A_SPMCSR:
      00000000                      DS 1
      2          #include <inavr.h>
      3          #define cli()      __disable_interrupt() 
      4          #define sei()      __enable_interrupt()
      5          

                                    In  segment CODE, align 2, keep-with-next
      6          void main(void)
                        main:
      7          {
      00000000   C006               RJMP    ??main_0
      8            while(SPMCSR & RWWSB)
      9            {
     10              cli();  
                        ??main_1:
      00000002   94F8               CLI
     11              SPMCSR = (1 << RWWSRE)|(1 << SPMEN);
      00000004   E101               LDI     R16, 17
      00000006   93000068           STS     104, R16
     12              asm("spm");
      0000000A   95E8               spm
     13              sei();  
      0000000C   9478               SEI
     14              
     15            }
                        ??main_0:
      0000000E   91000068           LDS     R16, 104
      00000012   7006               ANDI    R16, 0x06
      00000014   F7B1               BRNE    ??main_1
     16            
     17            while(1)
                        ??main_2:
      00000016   CFFF               RJMP    ??main_2
      00000018                      REQUIRE _A_SPMCSR
     18            {
     19            ;
     20            }
     21          }

使用特权

评论回复
14
zuoyou| | 2008-10-26 23:08 | 只看该作者

re

内嵌的汇编ASM()会影响优化

使用特权

评论回复
15
mxh0506|  楼主 | 2008-10-27 17:25 | 只看该作者

已经慢慢明白一些了

单就这一段程序编译,不会有什么变化
while(SPMCSR & RWWSB)
{
   cli();  
   SPMCSR = (1 << RWWSRE)|(1 << SPMEN);
   asm("spm");
   sei();  
}
但是一旦把它放到特定的上下文里,优化结果会随之改变.
但是目前仍未彻底搞明白为什么第一种写法行不通.

使用特权

评论回复
16
dudongdao| | 2008-10-27 20:42 | 只看该作者

发例子

那你能不能多发点程序呢~  你搞 一个不行的,发上来~ 不然大家认为你调戏人呢

使用特权

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

本版积分规则

85

主题

1601

帖子

2

粉丝