当我从程序中调用exit()时会发生什么?


17

setup或中loop,如果要添加exit(0)呼叫,控制权将传递到哪里?微控制器的下一个状态是什么?它会停止执行并关闭电源吗?

我正在使用修订版2 Arduino Uno。


我认为这只是停止。它不会关闭时钟或关闭电源。
TheDoctor 2014年

其余的内存应填充有NOP汇编语句,该汇编语句仅暂停几个时钟周期
TheDoctor 2014年

Answers:


12

我最初的猜测是错误的。我以为它会简单地从循环中返回,而核心库只会再次调用loop()。但是,我看到创建了以下代码。注意到__stop_program是一个硬循环...

Blink.ino清单的摘录,其中添加了exit(0):

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
  exit(0);
}

上面的反汇编:

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
 100:   80 91 00 01     lds r24, 0x0100
 104:   61 e0           ldi r22, 0x01   ; 1
 106:   0e 94 ca 01     call    0x394   ; 0x394 <digitalWrite>
  delay(1000);               // wait for a second
 10a:   68 ee           ldi r22, 0xE8   ; 232
 10c:   73 e0           ldi r23, 0x03   ; 3
 10e:   80 e0           ldi r24, 0x00   ; 0
 110:   90 e0           ldi r25, 0x00   ; 0
 112:   0e 94 f7 00     call    0x1ee   ; 0x1ee <delay>
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
 116:   80 91 00 01     lds r24, 0x0100
 11a:   60 e0           ldi r22, 0x00   ; 0
 11c:   0e 94 ca 01     call    0x394   ; 0x394 <digitalWrite>
  delay(1000);               // wait for a second
 120:   68 ee           ldi r22, 0xE8   ; 232
 122:   73 e0           ldi r23, 0x03   ; 3
 124:   80 e0           ldi r24, 0x00   ; 0
 126:   90 e0           ldi r25, 0x00   ; 0
 128:   0e 94 f7 00     call    0x1ee   ; 0x1ee <delay>
  exit(0);
 12c:   80 e0           ldi r24, 0x00   ; 0
 12e:   90 e0           ldi r25, 0x00   ; 0
 130:   0e 94 1e 02     call    0x43c   ; 0x43c <_exit>

...

0000043c <_exit>:
 43c:   f8 94           cli

0000043e <__stop_program>:
 43e:   ff cf           rjmp    .-2         ; 0x43e <__stop_program>

请注意,如果_exit没有调用cli,则中断将能够执行操作。但事实并非如此。


avr-objdump -S {compiled *.elf file}生成一个文件,该文件包含通向汇编代码每一部分的C代码。它更容易遵循。
康纳·沃尔夫

我只是尝试了一下,它没有为循环函数正确地发出内联C代码。我勒个去?
康纳·沃尔夫

哇,好奇怪。我用Stino而不是arduino编辑器来编译项目*.elf然后从中反编译,然后得到正确的调试符号。我认为Arduino文本编辑器/按钮宏(我拒绝将其称为IDE,因为它不是)是出于某种奇怪和愚蠢的原因,它仅从已编译的主C ++文件中剥离调试信息。
康纳·沃尔夫

这里一个解释,它是随路IDE复制您的文件做一个临时位置。您可以通过告诉avr-objdump源在哪里来“修复”该问题avr-objdump -S -I/path/to/the/sketch/folder xxx.elf 。那是草图文件夹路径,而不是.ino文件本身。然后,您应该在转储中获得C源代码。
尼克·加蒙

11

好吧,我刚刚用Arduino Uno测试了它,它完全停止了代码,并在代码停止运行时保留了所有输出(因此它使我的LED一直亮着)。调用exit时似乎没有IO清理。这是我所期望的,因为Arduino IDE提供了设置和循环功能,如果您将ATMEGA * 28与任何其他AVR IDE一起编程,则将从主要功能(如所有C / C ++程序)开始。设置和循环功能不是AVR MCU的标准配置。

注意:如果您想知道,按复位按钮可以重新启动代码。


很高兴知道。我正在寻找更详细,底层的内容。在调用exit(0)反汇编指令(IIRC) __stop_programcli和自旋锁。我想通过对控件如何传递的解释(即调用堆栈弹出?,ISR调用)来验证是否正确。
asheeshr 2014年

嗯,好吧,我还没有对arduino进行过如此低的了解,有关该信息,您可能需要检查atmel网站。
杰西·兰宁
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.