为什么函数按照定义的顺序执行,而不是按照 avr-c 中 int main() 调用的顺序执行?

sho*_*hit 2 c avr atmega avr-gcc

我正在尝试学习 AVR C,并且正在修补 atmega328p 微控制器。我正在 Linux Mint 上使用 avr-gcc 工具链来编译我的代码并将其烧写到 Arduino 板上。

所以我尝试使用函数调用使两个 LED 灯闪烁。我制作了两个函数 - 一个用于连接到 Arduino 板的引脚 7 的闪烁 LED,另一个用于连接到 Arduino 板的引脚 13 的闪烁 LED。

这些功能正在运行,但是当我修改代码时,我注意到一个奇怪的行为。这些函数按照它们定义的顺序在 main() 之外被调用和执行;而不是按照它们从 内部调用的顺序int main()

这是我的代码

#include <avr/io.h>
#include <util/delay.h>

void blinkPin13() {
    while(1) {
        DDRB = DDRB | (1 << DDB5);
        PORTB = PORTB | (1 << PORTB5);
        _delay_ms(5000);
        PORTB = PORTB & ~(1 << PORTB5);
        _delay_ms(500);
    }
}

void blinkPin7() {
    while(1) {
        DDRD = DDRD | (1 << DDD7);
        PORTD = PORTD | (1 << PORTD7);
        _delay_ms(1000);
        PORTD = PORTD & ~(1 << PORTD7);
        _delay_ms(500);
    }
}


int main(void) {    
    blinkPin7();
    blinkPin13();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是用于编译和刷新代码的 makefile

default:
    avr-gcc -Os -DF_CPU=16000000UL -mmcu=atmega328p -c -o led.o led.c
    avr-gcc -o led.bin led.o
    avr-objcopy -O ihex -R .eeprom led.bin led.hex
    sudo avrdude -F -V -c arduino -p ATMEGA328P -P /dev/ttyACM0 -b 115200 -U flash:w:led.hex
Run Code Online (Sandbox Code Playgroud)

blinkPin7()因此,当我将上述代码刷新到 Arduino 板时,即使首先调用该函数,连接到引脚 13 的 LED 也会闪烁。我注意到函数的执行顺序始终对应于函数在 main() 外部定义的顺序,而不是对应于从 main() 内部调用它们的顺序。

为什么会这样呢?

hch*_*ung 10

你的代码没有任何问题。但你的 Makefile 不正确。

avr-gcc -o led.bin led.o
Run Code Online (Sandbox Code Playgroud)

它不会-mmcu=atmega328p通过链接阶段。如果没有此选项,您应该会收到如下所示的 ld 错误:

avr:103 architecture of input file `led.o' is incompatible with avr output
Run Code Online (Sandbox Code Playgroud)

这意味着您没有目标 MCU。使用正确的链接器脚本,main() 从地址 0(重置向量)开始,一切都会正常工作。但是,如果链接器脚本错误,没有添加启动代码和中断向量表,那么现在首先出现的任何函数都将位于地址 0 处,并且将按照您观察到的情况开始执行。

添加目标 MCU 将解决该问题:

     avr-gcc -o led.bin led.o -mmcu=atmega328p
Run Code Online (Sandbox Code Playgroud)