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

研究是基于:
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

别的都没有设置。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值