atmega32u4avr-gcc (WinAVR 2010) 编译 启动代码 crtm32u4.o

xiaoxiao2021-02-28  28

研究是基于: SparkFun ATMEGA32U4 Breakout https://github.com/sparkfun/32U4_Breakout_Board 32U4_Breakout_Board-master\Examples\32U4_digital_input 源码为: main.c

/* Created 05/22/2012 by Jordan McConnell at Sparkfun Electronics * This code is beerware, you know what I'm sayin'? * * Built on WinXP SP3 and WinAVR-20100110, AVRDUDE 5.10 * * This code is a simple example of digital input for Sparkfun's * 32U4 Breakout Board using C and standard AVR libraries. It * teaches you how to read the status of a digital pin to determine * whether its current status is HIGH or LOW. * * Pin PF0 is used as a digital input. If its status is HIGH, * pin PD5 toggles each second, if it's status is LOW, pin PD6 * toggles each second instead. * * The user can connect LED's to pins PD5 and PD6 or use a multimeter * to verify operation. If pin PF0 is left unconnected, it's status * will be HIGH due to internal pullup resistors, and PD5 toggles. * If PF0 is connected to ground, PD6 toggles each second instead. */ // Libraries for register names and the delay function #include <avr/io.h> #include <util/delay.h> // Macros to make bit manipulation easier #define set_bit(address,bit) (address |= (1<<bit)) #define clear_bit(address,bit) (address &= ~(1<<bit)) #define toggle_bit(address,bit) (address ^= (1<<bit)) // This macro is for checking if a certain bit is set in a given register. // This is useful here for checking the status of individual input pins. #define check_bit(address,bit) ((address & (1<<bit)) == (1<<bit)) int main(void) { // The following line sets bit 5 HIGH in register DDRD set_bit(DDRD,5); // Pin PD5 is now configured as an OUTPUT set_bit(DDRD,6); // Pin PD6 is now configured as an OUTPUT // The following line sets bit 0 LOW in register DDRF clear_bit(DDRF,0); // Pin PF0 is now configured as an INPUT set_bit(PORTF,0); // Turn on internal pullups for PF0 while(1) { // PINF is the register you have to read to check if a particular // pin on port F (PFx) is HIGH or LOW if(check_bit(PINF,0)) { // If PF0 is HIGH, toggle pin PD5's output status toggle_bit(PORTD,5); } else { // If PF0 is LOW, toggle pin PD6's output status toggle_bit(PORTD,6); } _delay_ms(1000); // Delay 1 second before checking PF0 again } return 0; }

Makefile

# Hey Emacs, this is a -*- makefile -*- #---------------------------------------------------------------------------- # WinAVR Makefile Template written by Eric B. Weddington, J鰎g Wunsch, et al. # # Released to the Public Domain # # Additional material for this makefile was written by: # Peter Fleury # Tim Henigan # Colin O'Flynn # Reiner Patommel # Markus Pfaff # Sander Pool # Frederik Rouleau # Carlos Lamas # #---------------------------------------------------------------------------- # On command line: # # make all = Make software. # # make clean = Clean out built project files. # # make coff = Convert ELF to AVR COFF. # # make extcoff = Convert ELF to AVR Extended COFF. # # make program = Download the hex file to the device, using avrdude. # Please customize the avrdude settings below first! # # make debug = Start either simulavr or avarice as specified for debugging, # with avr-gdb or avr-insight as the front end for debugging. # # make filename.s = Just compile filename.c into the assembler code only. # # make filename.i = Create a preprocessed source file for use in submitting # bug reports to the GCC project. # # To rebuild project do "make clean" then "make all". #---------------------------------------------------------------------------- # MCU name MCU = atmega32u4 # Processor frequency. # This will define a symbol, F_CPU, in all source code files equal to the # processor frequency. You can then use this symbol in your source code to # calculate timings. Do NOT tack on a 'UL' at the end, this will be done # automatically to create a 32-bit value in your source code. # Typical values are: # F_CPU = 1000000 # F_CPU = 1843200 # F_CPU = 2000000 # F_CPU = 3686400 # F_CPU = 4000000 # F_CPU = 7372800 # F_CPU = 8000000 # F_CPU = 11059200 # F_CPU = 14745600 # F_CPU = 16000000 # F_CPU = 18432000 # F_CPU = 20000000 F_CPU = 16000000 # Output format. (can be srec, ihex, binary) FORMAT = ihex # Target file name (without extension). TARGET = main # Object files directory # To put object files in current directory, use a dot (.), do NOT make # this an empty or blank macro! OBJDIR = ./obj # List C source files here. (C dependencies are automatically generated.) SRC = $(TARGET).c # List C++ source files here. (C dependencies are automatically generated.) CPPSRC = # List Assembler source files here. # Make them always end in a capital .S. Files ending in a lowercase .s # will not be considered source files but generated files (assembler # output from the compiler), and will be deleted upon "make clean"! # Even though the DOS/Win* filesystem matches both .s and .S the same, # it will preserve the spelling of the filenames, and gcc itself does # care about how the name is spelled on its command-line. ASRC = # Optimization level, can be [0, 1, 2, 3, s]. # 0 = turn off optimization. s = optimize for size. # (Note: 3 is not always the best optimization level. See avr-libc FAQ.) OPT = s # Debugging format. # Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs. # AVR Studio 4.10 requires dwarf-2. # AVR [Extended] COFF format requires stabs, plus an avr-objcopy run. DEBUG = dwarf-2 # List any extra directories to look for include files here. # Each directory must be seperated by a space. # Use forward slashes for directory separators. # For a directory that has spaces, enclose it in quotes. EXTRAINCDIRS = # Compiler flag to set the C Standard level. # c89 = "ANSI" C # gnu89 = c89 plus GCC extensions # c99 = ISO C99 standard (not yet fully implemented) # gnu99 = c99 plus GCC extensions CSTANDARD = -std=gnu99 # Place -D or -U options here for C sources CDEFS = -DF_CPU=$(F_CPU)UL # Place -D or -U options here for ASM sources ADEFS = -DF_CPU=$(F_CPU) # Place -D or -U options here for C++ sources CPPDEFS = -DF_CPU=$(F_CPU)UL #CPPDEFS += -D__STDC_LIMIT_MACROS #CPPDEFS += -D__STDC_CONSTANT_MACROS ....... #---------------- Library Options ---------------- # Minimalistic printf version PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min # Floating point printf version (requires MATH_LIB = -lm below) PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt # If this is left blank, then it will use the Standard printf version. PRINTF_LIB = #PRINTF_LIB = $(PRINTF_LIB_MIN) #PRINTF_LIB = $(PRINTF_LIB_FLOAT) # Minimalistic scanf version SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min # Floating point + %[ scanf version (requires MATH_LIB = -lm below) SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt # If this is left blank, then it will use the Standard scanf version. SCANF_LIB = #SCANF_LIB = $(SCANF_LIB_MIN) #SCANF_LIB = $(SCANF_LIB_FLOAT) MATH_LIB = -lm # List any extra directories to look for libraries here. # Each directory must be seperated by a space. # Use forward slashes for directory separators. # For a directory that has spaces, enclose it in quotes. EXTRALIBDIRS =

编译过程: 重点看:avr-objdump -h -S -z main.elf > main.lss

-------- begin -------- avr-gcc (WinAVR 20100110) 4.3.3 Copyright (C) 2008 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Compiling C: main.c avr-gcc -c -mmcu=atmega32u4 -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./obj/main.lst -std=gnu99 -MMD -MP -MF .dep/main.o.d main.c -o obj/main.o Linking: main.elf avr-gcc -mmcu=atmega32u4 -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=obj/main.o -std=gnu99 -MMD -MP -MF .dep/main.elf.d obj/main.o --output main.elf -Wl,-Map=main.map,--cref -lm Creating load file for Flash: main.hex avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature main.elf main.hex Creating load file for EEPROM: main.eep avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ --change-section-lma .eeprom=0 --no-change-warnings -O ihex main.elf main.eep || exit 0 Creating Extended Listing: main.lss avr-objdump -h -S -z main.elf > main.lss Creating Symbol Table: main.sym avr-nm -n main.elf > main.sym Size after: AVR Memory Usage ---------------- Device: atmega32u4 Program: 248 bytes (0.8% Full) (.text + .data + .bootloader) Data: 0 bytes (0.0% Full) (.data + .bss + .noinit) -------- end --------

生成的中间文件:main.lss 内容为:

main.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn 0 .text 000000f8 00000000 00000000 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE 1 .debug_aranges 00000020 00000000 00000000 0000014c 2**0 CONTENTS, READONLY, DEBUGGING 2 .debug_pubnames 0000001b 00000000 00000000 0000016c 2**0 CONTENTS, READONLY, DEBUGGING 3 .debug_info 00000110 00000000 00000000 00000187 2**0 CONTENTS, READONLY, DEBUGGING 4 .debug_abbrev 000000b2 00000000 00000000 00000297 2**0 CONTENTS, READONLY, DEBUGGING 5 .debug_line 00000153 00000000 00000000 00000349 2**0 CONTENTS, READONLY, DEBUGGING 6 .debug_frame 00000020 00000000 00000000 0000049c 2**2 CONTENTS, READONLY, DEBUGGING 7 .debug_str 000000ff 00000000 00000000 000004bc 2**0 CONTENTS, READONLY, DEBUGGING 8 .debug_loc 00000038 00000000 00000000 000005bb 2**0 CONTENTS, READONLY, DEBUGGING 9 .debug_ranges 00000048 00000000 00000000 000005f3 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: 00000000 <__vectors>: 0: 0c 94 56 00 jmp 0xac ; 0xac <__ctors_end> 4: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 8: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> c: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 10: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 14: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 18: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 1c: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 20: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 24: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 28: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 2c: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 30: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 34: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 38: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 3c: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 40: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 44: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 48: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 4c: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 50: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 54: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 58: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 5c: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 60: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 64: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 68: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 6c: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 70: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 74: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 78: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 7c: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 80: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 84: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 88: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 8c: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 90: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 94: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 98: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 9c: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> a0: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> a4: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> a8: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__bad_interrupt> 000000ac <__ctors_end>: ac: 11 24 eor r1, r1 ae: 1f be out 0x3f, r1 ; 63 b0: cf ef ldi r28, 0xFF ; 255 b2: da e0 ldi r29, 0x0A ; 10 b4: de bf out 0x3e, r29 ; 62 b6: cd bf out 0x3d, r28 ; 61 b8: 0e 94 62 00 call 0xc4 ; 0xc4 <main> bc: 0c 94 7a 00 jmp 0xf4 ; 0xf4 <_exit> 000000c0 <__bad_interrupt>: c0: 0c 94 00 00 jmp 0 ; 0x0 <__vectors> 000000c4 <main>: #define check_bit(address,bit) ((address & (1<<bit)) == (1<<bit)) int main(void) { // The following line sets bit 5 HIGH in register DDRD set_bit(DDRD,5); // Pin PD5 is now configured as an OUTPUT c4: 55 9a sbi 0x0a, 5 ; 10 set_bit(DDRD,6); // Pin PD6 is now configured as an OUTPUT c6: 56 9a sbi 0x0a, 6 ; 10 // The following line sets bit 0 LOW in register DDRF clear_bit(DDRF,0); // Pin PF0 is now configured as an INPUT c8: 80 98 cbi 0x10, 0 ; 16 set_bit(PORTF,0); // Turn on internal pullups for PF0 ca: 88 9a sbi 0x11, 0 ; 17 toggle_bit(PORTD,5); } else { // If PF0 is LOW, toggle pin PD6's output status toggle_bit(PORTD,6); cc: 50 e4 ldi r21, 0x40 ; 64 // PINF is the register you have to read to check if a particular // pin on port F (PFx) is HIGH or LOW if(check_bit(PINF,0)) { // If PF0 is HIGH, toggle pin PD5's output status toggle_bit(PORTD,5); ce: 40 e2 ldi r20, 0x20 ; 32 milliseconds can be achieved. */ void _delay_loop_2(uint16_t __count) { __asm__ volatile ( d0: 20 e9 ldi r18, 0x90 ; 144 d2: 31 e0 ldi r19, 0x01 ; 1 while(1) { // PINF is the register you have to read to check if a particular // pin on port F (PFx) is HIGH or LOW if(check_bit(PINF,0)) d4: 78 9b sbis 0x0f, 0 ; 15 d6: 03 c0 rjmp .+6 ; 0xde <main+0x1a> { // If PF0 is HIGH, toggle pin PD5's output status toggle_bit(PORTD,5); d8: 8b b1 in r24, 0x0b ; 11 da: 84 27 eor r24, r20 dc: 02 c0 rjmp .+4 ; 0xe2 <main+0x1e> } else { // If PF0 is LOW, toggle pin PD6's output status toggle_bit(PORTD,6); de: 8b b1 in r24, 0x0b ; 11 e0: 85 27 eor r24, r21 e2: 8b b9 out 0x0b, r24 ; 11 e4: 80 e1 ldi r24, 0x10 ; 16 e6: 97 e2 ldi r25, 0x27 ; 39 e8: f9 01 movw r30, r18 ea: 31 97 sbiw r30, 0x01 ; 1 ec: f1 f7 brne .-4 ; 0xea <main+0x26> __ticks = (uint16_t) (__ms * 10.0); while(__ticks) { // wait 1/10 ms _delay_loop_2(((F_CPU) / 4e3) / 10); __ticks --; ee: 01 97 sbiw r24, 0x01 ; 1 __ticks = 1; else if (__tmp > 65535) { // __ticks = requested delay in 1/10 ms __ticks = (uint16_t) (__ms * 10.0); while(__ticks) f0: 89 f3 breq .-30 ; 0xd4 <main+0x10> f2: fa cf rjmp .-12 ; 0xe8 <main+0x24> 000000f4 <_exit>: f4: f8 94 cli 000000f6 <__stop_program>: f6: ff cf rjmp .-2 ; 0xf6 <__stop_program>

看一下main.map 重点看:C:\WinAVR-20100110\avr\lib\avr5\crtm32u4.o 这个是单片机跳转到main函数之前的启动代码

部分内容如下:

Archive member included because of file (symbol) c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/avr5\libgcc.a(_exit.o) c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib/avr5/crtm32u4.o (exit) Memory Configuration Name Origin Length Attributes text 0x00000000 0x00020000 xr data 0x00800060 0x0000ffa0 rw !x eeprom 0x00810000 0x00010000 rw !x fuse 0x00820000 0x00000400 rw !x lock 0x00830000 0x00000400 rw !x signature 0x00840000 0x00000400 rw !x *default* 0x00000000 0xffffffff Linker script and memory map Address of section .data set to 0x800100 LOAD c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib/avr5/crtm32u4.o LOAD obj/main.o LOAD c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib/avr5\libm.a LOAD c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/avr5\libgcc.a LOAD c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib/avr5\libc.a LOAD c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/avr5\libgcc.a

重点看: 跳转到main之前做的工作

000000ac <__ctors_end>: ac: 11 24 eor r1, r1 ae: 1f be out 0x3f, r1 ; 63 b0: cf ef ldi r28, 0xFF ; 255 b2: da e0 ldi r29, 0x0A ; 10 b4: de bf out 0x3e, r29 ; 62 b6: cd bf out 0x3d, r28 ; 61 b8: 0e 94 62 00 call 0xc4 ; 0xc4 <main> bc: 0c 94 7a 00 jmp 0xf4 ; 0xf4 <_exit>

异或运算(相同为0,不同为1) SREG 设置为0 SPH设置为 0x0a SPL设置为0xFF

别的都没有设置。

转载请注明原文地址: https://www.6miu.com/read-2632368.html

最新回复(0)