Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
172 views
in Technique[技术] by (71.8m points)

c - AVR ATtiny814 program executes first function, ignoring main

I'm trying to write software for an ATtiny814 (tiny avr 1-series) microcontroller, but I encounter a strange problem: whatever the first function in main.c is, gets executed and the remaining code gets ignored - including the main() function.

I'm using the avr-toolchain from the Arduino IDE on macOS, but I'm not using the IDE, I just added the bin/ directory of the avr-toolchain to the PATH variable. The code just compiles fine without errors or warnings. Using pyupdi I can successfully flash the program to the chip, and again it works fine - except that only code from the first function in the main.c is executed.

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)

Example 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;
}

Here, only test1() is executed, as only PB1 turns on.

Example 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;
}

Here, main() gets skipped and again test1() is executed, turning PB1 on.

Example 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;
}

No main function at all. No compiler errors. Only test0() gets executed and PB0 turns on.

I have no clue whats going on here. Btw, using the same avr-toolchain setup, I can write software for an ATtiny841 (it's a different architecture/series) as expected.

question from:https://stackoverflow.com/questions/65647177/avr-attiny814-program-executes-first-function-ignoring-main

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Okay, found a solution: When I compile it as described here https://github.com/vladbelous/tinyAVR_gcc_setup#example-of-compiler-usage, it works.

So in my case:

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

Fixed 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)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

56.9k users

...