Winavr Avr Gcc
Transcript of Winavr Avr Gcc
AVR-GCC, AVR-LIBC & WinAVR
GCC GCC stands for GNU Compiler Collection
Highly flexible compiler system. Has different compiler front-ends for different
languages. Has many back-ends that generate assembly
code for many different processors and host operating systems.
All share a common "middle-end", containing the generic parts of the compiler, including a lot of optimizations.
AVR GCC
AVR GCC has three available compilers for the AVR: C language, C++, and Ada. The compiler itself does not assemble or link
the final code.
GNU Binutils contains the GNU assembler (gas), and the
GNU linker (ld), and many other utilities.
GNU bin utils avr-as
The Assembler. avr-ld
The Linker. avr-ar
Create, modify, and extract from libraries (archives). avr-ranlib
Generate index to library (archive) contents. avr-objcopy
Copy and translate object files to different formats. avr-objdump
Display information from object files including disassembly. avr-size
List section sizes and total size.
GNU bin utils avr-nm
List symbols from object files. avr-strings
List printable strings from files. avr-strip
Discard symbols from files. avr-readelf
Display the contents of ELF format files. avr-addr2line
Convert addresses to file and line. avr-c++filt
Filter to demangle encoded C++ symbols.
Standard C Library: avr-libc
AVR-Libc provides many of the same functions found in a regular
Standard C Library, and many additional library functions that is
specific to an AVR.
Other AVR Utilities
GNU Make interprets and executes a Makefile that is
written for a project. A Makefile contains dependency rules and
instructions on how to build output files from input files.
AVRDUDE It helps you to program your device.
Other AVR Utilities
GDB / Insight / DDD GDB is a command-line debugger Insight is GDB plus a GUI written in Tcl/Tk. DDD (Data Display Debugger) is another
popular GUI front end to GDB.
AVaRICE is a back-end program to AVR GDB interfaces to the Atmel JTAG In-Circuit
Emulator (ICE), to provide emulation capabilities.
WinAVR
WinAVR (pronounced "whenever") It is a suite of executable, open source
software development tools for the Atmel AVR series of RISC microprocessors hosted on the Windows platform.
It includes the GNU GCC compiler for C and C++.
Variable Types
±1.175e-38 to ±3.402e3832double
±1.175e-38 to ±3.402e3832float
-2147483648 to 214748364732signed long int
0 to 429496729532unsigned long int
-2147483648 to 214748364732long int
-32768 to 3276716signed int
0 to 6553616unsigned int
-32768 to 3276716short int
-32768 to 3276716int
-128 to 1278signed char
0 to 2558unsigned char
-128 to 1278char
0,11bit
RangeSize (bits)Type
Memory Sections The .text Section
It contains the actual machine instructions which make up your program.
The .data Section It contains static data which was defined in
your code. It is possible to tell the linker the SRAM
address of the beginning of the .data section.
The .bss SectionUninitialized global or static variables end up
in the .bss section.
Memory Sections The .eeprom Section
This is where eeprom variables are stored. The .noinit Section
This sections is a part of the .bss section. int foo __attribute__ ((section (".noinit"))); will not be initialized to zero during startup as
would normal .bss data.
Memory Areas Many of the devices have a minimal
amount of RAM. This needs to be shared between
initialized and uninitialized variables (sections .data and .bss),
the dynamic memory allocator, and the stack that is used for calling subroutines
and storing local (automatic) variables.
RAM map of a device with internal RAM
Internal RAM: variables and stack External RAM: heap
avr-gcc ... -Wl,--defsym=__heap_start=0x802000,--defsym=__heap_end=0x803fff ...
Data in Program Space GCC has a special keyword: __attribute__
It is used to attach different attributes to function declarations, variables, and types.
A special attribute, progmem, is use on data declarations, and tells the compiler to place the data in the Program Memory (Flash).
AVR-Libc provides a simple macro PROGMEM
It is defined in the <avr/pgmspace.h>
Data in the Program SpaceRAM Space
unsigned char mydata[3][4] =
{
{0x00,0x01,0x02,0x03},
{0x0A,0x0B,0x0C,0x0D},
{0x04,0x05,0x06,0x07}
};
byte = mydata[i][j];
ROM Space
#include <avr/pgmspace.h>
.
.
unsigned char mydata[3][4] PROGMEM =
{
{0x00,0x01,0x02,0x03},
{0x0A,0x0B,0x0C,0x0D},
{0x04,0x05,0x06,0x07}
};
byte = pgm_read_byte(&(mydata[i][j]));
Inline Assemblerasm(code : output operand list : input operand list [: clobber list]); Reading a value from port D:
asm("in %0, %1" : "=r" (value) : "I" (_SFR_IO_ADDR(PORTD)) );
The assembler instructions as a single string constant: "in %0, %1"
A list of output operands, separated by commas: "=r" (value)
A comma separated list of input operands: "I" (_SFR_IO_ADDR(PORTD))
To avoid compiler optimizationasm volatile("in %0, %1" : "=r" (value) : "I" (_SFR_IO_ADDR(PORTD)));
Input & Output OperandsConstraint Used for Range
a Simple upper registers r16 to r23
b Base pointer registers pairs y, z
d Upper register r16 to r31
e Pointer register pairs x, y, z
q Stack pointer register SPH:SPL
r Any register r0 to r31
t Temporary register r0
w Special upper register pairs r24, r26, r28, r30
x Pointer register pair X x (r27:r26)
y Pointer register pair Y y (r29:r28)
z Pointer register pair Z z (r31:r30)
G Floating point constant 0.0
I 6-bit positive integer constant 0 to 63
J 6-bit negative integer constant -63 to 0
K Integer constant 2
L Integer constant 0
l Lower registers r0 to r15
M 8-bit integer constant 0 to 255
N Integer constant -1
O Integer constant 8, 16, 24
P Integer constant 1
asm volatile( "cli" "\n\t" "ld r24, %a0" "\n\t" "inc r24" "\n\t" "st %a0, r24" "\n\t" "sei" "\n\t" : : "e" (ptr) : "r24");
clild r24, Zinc r24st Z, r24sei
Example C Program 1
avr-gcc -g -mmcu=at90s8515 -o avr-p1.elf avr-p1.c
// C version of led.asm#include <avr/io.h> //I/O definition header file
unsigned char z; //declare z
void main(void){
DDRB=0xFF; //set all bits of portB for outputDDRD=0x00; //set all bits of portD for input
while(1){ //infinite loopz = PIND; //read from PortD pinsPORTB = z; //write to PortB port
}}
Example C Program 1 Examining the Object File
avr-objdump -h -S avr-p1.elf
avr-p1.elf: file format elf32-avr
Sections:Idx Name Size VMA LMA File off Algn 0 .text 00000076 00000000 00000000 00000094 2**0 CONTENTS, ALLOC, LOAD, READONLY, CODE 1 .data 00000000 00800060 00000076 0000010a 2**0 CONTENTS, ALLOC, LOAD, DATA 2 .bss 00000001 00800060 00800060 0000010a 2**0 ALLOC 3 .noinit 00000000 00800061 00800061 0000010a 2**0 CONTENTS 4 .eeprom 00000000 00810000 00810000 0000010a 2**0..
Example C Program 1 Examining the Object File
avr-objdump -h -S avr-p1.elf void main(void){ 52: cf e5 ldi r28, 0x5F ; 95 54: d2 e0 ldi r29, 0x02 ; 2 56: de bf out 0x3e, r29 ; 62 58: cd bf out 0x3d, r28 ; 61 DDRB=0xFF; /* set all bits of portB for output */ 5a: 8f ef ldi r24, 0xFF ; 255 5c: 80 93 37 00 sts 0x0037, r24 DDRD=0x00; /* set all bits of portD for input */ 60: 10 92 31 00 sts 0x0031, r1
while(1){ /* infinite loop */ z = PIND; /* read from PortD pins */ 64: 80 91 30 00 lds r24, 0x0030 68: 80 93 60 00 sts 0x0060, r24 PORTB = z; /* write to PortB port */ 6c: 80 91 60 00 lds r24, 0x0060 70: 80 93 38 00 sts 0x0038, r24 74: f7 cf rjmp .-18 ; 0x64 <main+0x12>
Generating Intel Hex Files
avr-objcopy -j .text -j .data -O ihex avr-p1.elf avr-p1.hex
:100000000CC026C025C024C023C022C021C020C0EF:100010001FC01EC01DC01CC01BC011241FBECFE5C9:10002000D2E0DEBFCDBF10E0A0E6B0E0E6E7F0E052:1000300003C0C89531960D92A036B107D1F710E0F4:10004000A0E6B0E001C01D92A136B107E1F701C002:10005000D7CFCFE5D2E0DEBFCDBF8FEF80933700A3:100060001092310080913000809360008091600098:0600700080933800F7CF79:00000001FF
Example 2: (1) void delay(){ //function delay
int count_delay = 255;while(count_delay>0)
count_delay--;return;
}
void longdelay(){ //function longdelayint count_longdelay = 255;while(count_longdelay>0){
count_longdelay--;delay(); //function call
} return;
}
Example 2: (2)void delay(){ //function delay
int count_delay = 255;while(count_delay>0)
count_delay--;return;
}
void longdelay(){ //function longdelayint count_longdelay = 255;while(count_longdelay>0){
count_longdelay--;delay(); //function call
} return;
}
Example 2: (3)
#define F_CPU 4000000UL#include <util/delay.h>
//void _delay_us (double __us)// The maximal possible delay is 262.14 ms / F_CPU in Mhz.
//void _delay_ms (double __ms)// The maximal possible delay is 768 us / F_CPU in MHz.
Example 3: Interrupts (1)
#include <avr/io.h>#include <avr/interrupt.h>#define outp(a, b) b = a
uint8_t led;
// signal handler for timer interrupt TOV0 ISR(TIMER0_OVF_vect) { led++;}
Example 3: Interrupts (2)int main(void) {
outp(0xFF, DDRB); // use PortB for output (LED) outp((1<<TOV0), TIMSK); //enable timer overflow interrupt TCNT0=0x00; //set timer counter initial value outp((1<<CS00), TCCR0); //start timer without presscaler sei(); // enable interrupts
led = 0x00; //Initial led value for (;;) { // loop forever timer interupts will change the led value
outp(led, PORTB); }}
Example 4: UART (1)#include <stdint.h>#include <avr/io.h>
// Define baud rate#define USART_BAUD 115200ul#define USART_UBBR_VALUE ((F_CPU/(USART_BAUD<<4))-1)
void USART_vInit(void){
// Set baud rateUBRRH = (uint8_t)(USART_UBBR_VALUE>>8);UBRRL = (uint8_t)USART_UBBR_VALUE;
// Set frame format to 8 data bits, no parity, 1 stop bitUCSRC = (0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0);
// Enable receiver and transmitterUCSRB = (1<<RXEN)|(1<<TXEN);
}
Example 5: UART (2)void USART_vSendByte(uint8_t u8Data){
// Wait if a byte is being transmittedwhile((UCSRA&(1<<UDRE)) == 0);
// Transmit dataUDR = u8Data;
}
uint8_t USART_vReceiveByte(){
// Wait until a byte has been receivedwhile((UCSRA&(1<<RXC)) == 0);
// Return received datareturn UDR;
}
Example 5: UART (3)int main(void){
uint8_t u8Data;
USART_vInit(); // Initialise USART
USART_vSendByte('A'); // Send string
for(;;) // Repeat indefinitely{
// Echo received charactersu8Data = USART_vReceiveByte();USART_vSendByte(u8Data);
}}
Example 5: UART with Interrupt (1)#include <avr/io.h> #include <avr/interrupt.h> #include <avr/sleep.h>
#ifndef F_CPU #define F_CPU 3686400 //define cpu clock speed if not defined #endif #define BAUDRATE 19200 //set desired baud rate #define UBRRVAL ((F_CPU/(BAUDRATE*16UL))-1) //calculate UBRR value
void USART_Init() { //Set baud rate UBRRL=UBRRVAL; //low byte UBRRH=(UBRRVAL>>8); //high byte
//Set data frame format: asynchronous mode,no parity, 1 stop bit, 8 bit size UCSRC=(1<<URSEL)|(0<<UMSEL)|(0<<UPM1)|(0<<UPM0)|
(0<<USBS)|(0<<UCSZ2)|(1<<UCSZ1)|(1<<UCSZ0);
//Enable Transmitter and Receiver and Interrupt on receive complete UCSRB=(1<<RXEN)|(1<<TXEN)|(1<<RXCIE); set_sleep_mode(SLEEP_MODE_IDLE); sei(); //enable global interrupts
}
Example 5: UART with Interrupt (2)ISR(USART_RXC_vect) {
uint8_t Temp; //define temp value for storing received byte
Temp=UDR; //Store data to temp Temp++; //increment
//send received data back // no need to wait for empty send buffer
UDR=Temp; }
int main(void) { USART_Init(); while(1) sleep_mode(); //nothing here interrupts are working return 0;
}
Example 6: EEPROM Access#include <avr/eeprom.h> //Define EEPROM locations for restoring state#define E_VOLUME 0#define E_LF 1#define E_RF 2#define E_INIT 3
int main() {if (eeprom_read_byte((uint8_t*)E_INIT)!='T'){
eeprom_write_byte((uint8_t*)E_VOLUME,0x0F);eeprom_write_byte((uint8_t*)E_LF,0x80);eeprom_write_byte((uint8_t*)E_RF,0xA0);eeprom_write_byte((uint8_t*)E_INIT,'T'); //eeprom init is done
}
//--------Restore values from EEPROM------ST.value[0]=eeprom_read_byte((uint8_t*)E_VOLUME);ST.value[1]=eeprom_read_byte((uint8_t*)E_LF);ST.value[2]=eeprom_read_byte((uint8_t*)E_RF);
}
Example 7: Send String
#include <avr/pgmspace.h>
const char FlashString[] PROGMEM = "This is a string ";
void SendSTR_P(const char *FlashSTR) { uint8_t i;
for (i = 0; pgm_read_byte(&pFlashSTR[i]); i++) { sendChar(pgm_read_byte(&pFlashSTR[i]));
} }
Example 8: PWM - LED (1)
Pulse-width modulator (PWM) will ramp an LED on and off every two seconds.
Example 8: PWM - LED (2)/* * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * <[email protected]> wrote this file. As long as you retain this notice you * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return. Joerg Wunsch * ---------------------------------------------------------------------------- * * Simple AVR demonstration. Controls a LED that can be directly * connected from OC1/OC1A to GND. The brightness of the LED is * controlled with the PWM. After each period of the PWM, the PWM * value is either incremented or decremented, that's all. * * $Id: group__demo__project.html,v 1.1.1.14 2007/10/30 13:48:56 joerg_wunsch Exp $ */#include <inttypes.h>#include <avr/io.h>#include <avr/interrupt.h>#include <avr/sleep.h>#include "iocompat.h" // Defines port/pin numbers for various mcu
Example 8: PWM - LED (3)enum { UP, DOWN };ISR (TIMER1_OVF_vect) // Timer1 overflow ISR{ static uint16_t pwm; //For 10-bit PWM we need a 16-bit static uint8_t direction; switch (direction) //Determines the new value of the PWM. { case UP: if (++pwm == TIMER1_TOP) direction = DOWN; break; case DOWN: if (--pwm == 0) direction = UP; break; } OCR = pwm; //newly computed value is loaded into the PWM register
//safe to perform in ISR, but not out of ISR}
Example 8: PWM - LED (4)voidioinit (void) // Initializes the PWM and enables interrupts.{ /* Timer 1 is 10-bit PWM (8-bit PWM on some ATtinys). */ TCCR1A = TIMER1_PWM_INIT;
/* Start timer 1. */ TCCR1B |= TIMER1_CLOCKSOURCE;
/* Run any device-dependent timer 1 setup hook if present. */#if defined(TIMER1_SETUP_HOOK) TIMER1_SETUP_HOOK();#endif OCR = 0; /* Set PWM value to 0. */ DDROC = _BV (OC1); /* Enable OC1 as output. */ TIMSK = _BV (TOIE1); /* Enable timer 1 overflow interrupt. */ sei ();}
Example 8: PWM - LED (5)
intmain (void){ ioinit ();
/* loop forever, the interrupts are doing the rest */ for (;;) sleep_mode(); return (0);}