Sunteți pe pagina 1din 40

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
Type bit char unsigned char signed char int short int unsigned int signed int long int unsigned long int signed long int float double Size (bits) 1 8 8 8 16 16 16 16 32 32 32 32 32 Range 0,1 -128 to 127 0 to 255 -128 to 127 -32768 to 32767 -32768 to 32767 0 to 65536 -32768 to 32767 -2147483648 to 2147483647 0 to 4294967295 -2147483648 to 2147483647 1.175e-38 to 3.402e38 1.175e-38 to 3.402e38

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 Section


Uninitialized

global or static variables end up in the .bss section.

Memory Sections

The .eeprom Section


This This

is where eeprom variables are stored.

The .noinit Section


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 Space


RAM Space unsigned char mydata[3][4] = { {0x00,0x01,0x02,0x03}, {0x0A,0x0B,0x0C,0x0D}, {0x04,0x05,0x06,0x07} }; 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]));

byte = mydata[i][j];

Inline Assembler
asm(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 optimization
asm volatile("in %0, %1" : "=r" (value) : "I" (_SFR_IO_ADDR(PORTD)));

Input & Output Operands


Constraint a b d e q r t w x y z G I J K L l M N O P Used for Simple upper registers Base pointer registers pairs Upper register Pointer register pairs Stack pointer register Any register Temporary register Special upper register pairs Pointer register pair X Pointer register pair Y Pointer register pair Z Floating point constant 6-bit positive integer constant 6-bit negative integer constant Integer constant Integer constant Lower registers 8-bit integer constant Integer constant Integer constant Integer constant Range r16 to r23 y, z r16 to r31 x, y, z SPH:SPL r0 to r31 r0 r24, r26, r28, r30 x (r27:r26) y (r29:r28) z (r31:r30) 0.0 0 to 63 -63 to 0 2 0 r0 to r15 0 to 255 -1 8, 16, 24 1

asm volatile( "cli" "ld r24, %a0" "inc r24" "st %a0, r24" "sei" : : "e" (ptr) : "r24" ); cli ld r24, Z inc r24 st Z, r24 sei

"\n\t" "\n\t" "\n\t" "\n\t" "\n\t"

Example C Program 1
// C version of led.asm #include <avr/io.h> unsigned char z; void main(void) { DDRB=0xFF; DDRD=0x00; while(1){ } } //I/O definition header file //declare z

//set all bits of portB for output //set all bits of portD for input

//infinite loop z = PIND; //read from PortD pins PORTB = z; //write to PortB port

avr-gcc -g -mmcu=at90s8515 -o avr-p1.elf avr-p1.c

Example C Program 1

Examining the Object File


avr-objdump -h -S avr-p1.elf
avr-p1.elf: Sections: Idx Name 0 .text file format elf32-avr

Size VMA LMA File off Algn 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(){ int count_delay = 255; while(count_delay>0) count_delay--; return; } //function delay

void longdelay(){ //function longdelay int count_longdelay = 255; while(count_longdelay>0){ count_longdelay--; delay(); //function call } return; }

Example 2: (2)
void delay(){ int count_delay = 255; while(count_delay>0) count_delay--; return; } //function delay

void longdelay(){ //function longdelay int 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 //void _delay_us (double __us) // The maximal possible delay is 262.14 ms / F_CPU in Mhz. _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); outp((1<<TOV0), TIMSK); TCNT0=0x00; outp((1<<CS00), TCCR0); sei(); // use PortB for output (LED) //enable timer overflow interrupt //set timer counter initial value //start timer without presscaler // 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 rate UBRRH = (uint8_t)(USART_UBBR_VALUE>>8); UBRRL = (uint8_t)USART_UBBR_VALUE; // Set frame format to 8 data bits, no parity, 1 stop bit UCSRC = (0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0); // Enable receiver and transmitter UCSRB = (1<<RXEN)|(1<<TXEN); }

Example 5: UART (2)


void USART_vSendByte(uint8_t u8Data) { // Wait if a byte is being transmitted while((UCSRA&(1<<UDRE)) == 0); // Transmit data UDR = u8Data; } uint8_t USART_vReceiveByte() { // Wait until a byte has been received while((UCSRA&(1<<RXC)) == 0); // Return received data return UDR; }

Example 5: UART (3)


int main(void) { uint8_t u8Data; USART_vInit(); USART_vSendByte('A'); for(;;) { // Initialise USART // Send string // Repeat indefinitely // Echo received characters u8Data = 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() { UBRRL=UBRRVAL; UBRRH=(UBRRVAL>>8); //Set baud rate //low byte //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; Temp=UDR; Temp++; //define temp value for storing received byte //Store data to 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(); return 0; }

//nothing here interrupts are working

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): * <joerg@FreeBSD.ORG> 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)


void ioinit (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; DDROC = _BV (OC1); TIMSK = _BV (TOIE1); sei (); /* Set PWM value to 0. */ /* Enable OC1 as output. */ /* Enable timer 1 overflow interrupt. */

Example 8: PWM - LED (5)


int main (void) { ioinit (); /* loop forever, the interrupts are doing the rest */ for (;;) sleep_mode(); return (0); }

S-ar putea să vă placă și