AVR ATtiny814 程序执行第一个函数,忽略 main

AVR ATtiny814 program executes first function, ignoring main

我正在尝试为 ATtiny814(微型 avr 1 系列)微控制器编写软件,但我遇到了一个奇怪的问题:无论 main.c 中的第一个函数是什么,它都会被执行,其余代码也会被执行忽略 - 包括 main() 函数。

我在 macOS 上使用 Arduino IDE 的 avr 工具链,但我没有使用 IDE,我只是添加了 bin/ avr-toolchain 的目录到 PATH 变量。代码编译正常,没有错误或警告。使用 pyupdi 我可以成功地将程序闪存到芯片,并且它再次工作正常 - 除了只执行 main.c 中第一个函数的代码。

Makefile:

TARGET      = project
CLOCK       = 2000000 # configured in main
SOURCES     = main.c

OBJECTS = $(SOURCES:.c=.o)
COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -D__AVR_DEVICE_NAME__=attiny814 -D__AVR_DEV_LIB_NAME__=tn814

# compiling and linking, target is the finished hex file
all: $(TARGET).hex

# compile source files to object files
.c.o:
    $(COMPILE) -c $< -o $@

# link the object files together
$(TARGET).elf: $(OBJECTS)
    $(COMPILE) $(OBJECTS) -o $(TARGET).elf

# convert elf file to hex file
$(TARGET).hex: $(TARGET).elf
    avr-objcopy -O ihex -j .data -j .text $(TARGET).elf $(TARGET).hex

clean:
    rm -f $(TARGET).hex $(TARGET).elf $(OBJECTS)

示例 1

main.c:

#include <avr/io.h>


void test1() {
    // turn on PB1
    PORTB.DIR |= PIN1_bm;
    PORTB.OUT |= PIN1_bm;
}


int main() {
    // disable protection to configure clock frequency
    CCP = CCP_IOREG_gc;
    
    // configure CPU frequency
    CLKCTRL.MCLKCTRLA = CLKCTRL_CLKSEL_OSC20M_gc; // use 20 MHz internal clock as source
    CLKCTRL.MCLKCTRLB = CLKCTRL_PDIV_10X_gc | CLKCTRL_PEN_bm; // divide by 10 and enable divider
    
    // turn on PB0
    PORTB.DIR |= PIN0_bm;
    PORTB.OUT |= PIN0_bm;
    
    // main program loop
    while(1) {};
    return 0;
}

这里只执行test1(),因为只有PB1打开

示例 2

main.c:

#include <avr/io.h>

// prototype
void test1();


int main() {
    // disable protection to configure clock frequency
    CCP = CCP_IOREG_gc;
    
    // configure CPU frequency
    CLKCTRL.MCLKCTRLA = CLKCTRL_CLKSEL_OSC20M_gc; // use 20 MHz internal clock as source
    CLKCTRL.MCLKCTRLB = CLKCTRL_PDIV_10X_gc | CLKCTRL_PEN_bm; // divide by 10 and enable divider
    
    // turn on PB0
    PORTB.DIR |= PIN0_bm;
    PORTB.OUT |= PIN0_bm;
    
    // main program loop
    while(1) {};
    return 0;
}


void test1() {
    // turn on PB1
    PORTB.DIR |= PIN1_bm;
    PORTB.OUT |= PIN1_bm;
}

此处,main() 被跳过并再次执行 test1(),打开 PB1。

示例 3

main.c:

#include <avr/io.h>


void test0() {
    // turn on PB0
    PORTB.DIR |= PIN0_bm;
    PORTB.OUT |= PIN0_bm;
}


void test1() {
    // turn on PB1
    PORTB.DIR |= PIN1_bm;
    PORTB.OUT |= PIN1_bm;
}

根本没有主要功能。没有编译器错误。只有 test0() 被执行并且 PB0 打开。

我不知道这里发生了什么。顺便说一句,使用相同的 avr 工具链设置,我可以按预期为 ATtiny841(它是不同的 architecture/series)编写软件。

好的,找到了一个解决方案:当我按照此处https://github.com/vladbelous/tinyAVR_gcc_setup#example-of-compiler-usage的描述编译它时,它起作用了。

所以就我而言:

avr-gcc -c -Os -DF_CPU=2000000 -mmcu=attiny814 main.c
avr-gcc -mmcu=attiny814 -o main.elf main.o
avr-objcopy -j .text -j .data -j .rodata -O ihex main.elf main.hex

固定Makefile:

TARGET = project
MCU = attiny814
DEVICE = tiny814
# clock settings applied in main.c
CLOCK = 2000000
PROGRAMMER = /dev/tty.usbserial-A50285BI

SOURCES = main.c
OBJECTS = $(SOURCES:.c=.o)
COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(MCU)

# compiling and linking, target is the finished hex file
all: $(TARGET).hex

# compile source files to object files
.c.o:
    $(COMPILE) -c $< -o $@

# link the object files together
$(TARGET).elf: $(OBJECTS)
    $(COMPILE) $(OBJECTS) -o $(TARGET).elf

# convert elf file to hex file
$(TARGET).hex: $(TARGET).elf
    avr-objcopy -j .text -j .data -j .rodata -O ihex $(TARGET).elf $(TARGET).hex

# flash (call make flash), requires pyupdi installed
flash: $(TARGET).hex
    python3 -m updi.pyupdi -d $(DEVICE) -c $(PROGRAMMER) -f "$(shell pwd)/$(TARGET).hex"

clean:
    rm -f $(TARGET).hex $(TARGET).elf $(OBJECTS)