Winavr Avr Gcc

40
AVR-GCC, AVR-LIBC & WinAVR

Transcript of Winavr Avr Gcc

Page 1: Winavr Avr Gcc

AVR-GCC, AVR-LIBC & WinAVR

Page 2: Winavr Avr Gcc

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.

Page 3: Winavr Avr Gcc

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.

Page 4: Winavr Avr Gcc

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.

Page 5: Winavr Avr Gcc

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.

Page 6: Winavr Avr Gcc

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.

Page 7: Winavr Avr Gcc

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.

Page 8: Winavr Avr Gcc

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.

Page 9: Winavr Avr Gcc

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++.

Page 10: Winavr Avr Gcc

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

Page 11: Winavr Avr Gcc

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.

Page 12: Winavr Avr Gcc

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.

Page 13: Winavr Avr Gcc

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.

Page 14: Winavr Avr Gcc

RAM map of a device with internal RAM

Page 15: Winavr Avr Gcc

Internal RAM: variables and stack External RAM: heap

avr-gcc ... -Wl,--defsym=__heap_start=0x802000,--defsym=__heap_end=0x803fff ...

Page 16: Winavr Avr Gcc

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>

Page 17: Winavr Avr Gcc

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]));

Page 18: Winavr Avr Gcc

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

Page 19: Winavr Avr Gcc

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

Page 20: Winavr Avr Gcc

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

}}

Page 21: Winavr Avr Gcc

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..

Page 22: Winavr Avr Gcc

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>

Page 23: Winavr Avr Gcc

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

Page 24: Winavr Avr Gcc

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;

}

Page 25: Winavr Avr Gcc

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;

}

Page 26: Winavr Avr Gcc

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.

Page 27: Winavr Avr Gcc

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

Page 28: Winavr Avr Gcc

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

Page 29: Winavr Avr Gcc

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

}

Page 30: Winavr Avr Gcc

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;

}

Page 31: Winavr Avr Gcc

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

}}

Page 32: Winavr Avr Gcc

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

}

Page 33: Winavr Avr Gcc

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;

}

Page 34: Winavr Avr Gcc

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

}

Page 35: Winavr Avr Gcc

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]));

} }

Page 36: Winavr Avr Gcc

Example 8: PWM - LED (1)

Pulse-width modulator (PWM) will ramp an LED on and off every two seconds.

Page 37: Winavr Avr Gcc

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

Page 38: Winavr Avr Gcc

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}

Page 39: Winavr Avr Gcc

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 ();}

Page 40: Winavr Avr Gcc

Example 8: PWM - LED (5)

intmain (void){ ioinit ();

/* loop forever, the interrupts are doing the rest */ for (;;) sleep_mode(); return (0);}