研究是基于:
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
看一下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
别的都没有设置。