Table of Contents

Configuring GCC Projects in AVR Studio

Step-by-Step Instructions

Example Program

The following program has two source files: sampleC.c and configB.s. The program turns every other LED on and then toggles all of the state of the LEDs every 0.5 seconds.

sampleC.c

This source file has two functions:

/* sampleC.c -- Sample program that causes every other LED to toggle on and
 *              off every half second.
 * Configuration: PORTB must be connected to eight LEDs.
 * Dependencies: configB.s and stk200/delay.c 
 *               (You do not need to include standard libraries in this list.)
 * Author: t a y l o r@msoe.edu
 * Date: 5-4-2007
 */
#include <avr/io.h>        /* Contains I/O port declarations */
#include <inttypes.h>      /* Contains C99 type declarations */
#include <avr/interrupt.h> /* Contains interrupt related functions */
#include <stk200/delay.c>  /* Contains delay function */
 
/* Configures PORTB for I/O based on the mask
 * Parameters:
 *     mask -- 8-bit mask with 1 indicating output and 0 indicating input
 * Assembly implementation in configB.s
 */
extern void configPortB(uint8_t mask);
 
/* Selects one of two bit patterns
 * Parameters:
 *     type -- selects the desired bit pattern
 * return:
 *     0b10101010 if type==1
 *     0b01010101 if type!=1
 * C implementation in this file.
 */
uint8_t getPattern(uint8_t type);
 
/* Causes every other LED to toggle on and off every half second.
 * return:
 *     never
 */
int main(void)
{
  sei();                        /* Sets global interrupt flag so ATmon works */
  configPortB(0xff);            /* Configure all pins on PORTB for output */
 
  while(1)                      /* Loop forever */
  {
    PORTB = getPattern(0);      /* Turn every other light on */
    delay_ms(500);              /* Pass for 0.5 seconds */
    PORTB = getPattern(1);      /* Toggle all the lights on/off */
    delay_ms(500);              /* Pass for 0.5 seconds */
  }
  return 0;                     /* We never get here */
}
 
uint8_t getPattern(uint8_t type)
{
  uint8_t pattern = 0b01010101;
  if(type==1)
  {
    pattern = 0b10101010;
  }
  return pattern;
}

configB.s

The assembly source file contains the confgPortB function.

#define _SFR_ASM_COMPAT 1
#define __SFR_OFFSET 0     /* Required for port labels to work as expected */
#include <avr/io.h>        /* Contains I/O port declarations */

#define temp r16           /* Associate temp label with R16 */

.global configPortB        ; Make configPortB function visible to other source files.

.section .text             ; Start program section

; Configures PORTB for I/O based on the mask
; Parameters:
;     mask -- 8-bit mask with 1 indicating output and 0 indicating input
; Implementation notes:
;  The implementation is more complicated than it needs to be.  We could
;  just send R24 directly out to DDRB.
configPortB:
     push  temp            ; Save temp register on stack

     mov   temp, r24       ; Copy parameter passed in to temp register
     out   DDRB, temp      ; Configure PORTB

     pop   temp            ; Restore temp register
     ret

Resulting Listing File: sampleC.lss

The results of compiling, assembling, and linking this project are stored in a default folder in the project directory. The listing file looks like this:

Sections

sampleC.elf:     file format elf32-avr

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         000001a8  00000000  00000000  00000094  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         00000000  00800060  000001a8  0000023c  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  00800060  000001a8  0000023c  2**0
                  ALLOC
  3 .noinit       00000000  00800060  00800060  0000023c  2**0
                  CONTENTS
  4 .eeprom       00000000  00810000  00810000  0000023c  2**0
                  CONTENTS
  5 .stab         0000036c  00000000  00000000  0000023c  2**2
                  CONTENTS, READONLY, DEBUGGING
  6 .stabstr      00000084  00000000  00000000  000005a8  2**0
                  CONTENTS, READONLY, DEBUGGING
  7 .debug_aranges 00000014  00000000  00000000  0000062c  2**0
                  CONTENTS, READONLY, DEBUGGING
  8 .debug_pubnames 00000044  00000000  00000000  00000640  2**0
                  CONTENTS, READONLY, DEBUGGING
  9 .debug_info   000001c5  00000000  00000000  00000684  2**0
                  CONTENTS, READONLY, DEBUGGING
 10 .debug_abbrev 00000096  00000000  00000000  00000849  2**0
                  CONTENTS, READONLY, DEBUGGING
 11 .debug_line   00000112  00000000  00000000  000008df  2**0
                  CONTENTS, READONLY, DEBUGGING

Interrupt Jump Table

Disassembly of section .text:

00000000 <__vectors>:
   0:	0c 94 2a 00 	jmp	0x54 <__ctors_end>
   4:	0c 94 45 00 	jmp	0x8a <__bad_interrupt>
   8:	0c 94 45 00 	jmp	0x8a <__bad_interrupt>
   c:	0c 94 45 00 	jmp	0x8a <__bad_interrupt>
  10:	0c 94 45 00 	jmp	0x8a <__bad_interrupt>
  14:	0c 94 45 00 	jmp	0x8a <__bad_interrupt>
  18:	0c 94 45 00 	jmp	0x8a <__bad_interrupt>
  1c:	0c 94 45 00 	jmp	0x8a <__bad_interrupt>
  20:	0c 94 45 00 	jmp	0x8a <__bad_interrupt>
  24:	0c 94 45 00 	jmp	0x8a <__bad_interrupt>
  28:	0c 94 45 00 	jmp	0x8a <__bad_interrupt>
  2c:	0c 94 45 00 	jmp	0x8a <__bad_interrupt>
  30:	0c 94 45 00 	jmp	0x8a <__bad_interrupt>
  34:	0c 94 45 00 	jmp	0x8a <__bad_interrupt>
  38:	0c 94 45 00 	jmp	0x8a <__bad_interrupt>
  3c:	0c 94 45 00 	jmp	0x8a <__bad_interrupt>
  40:	0c 94 45 00 	jmp	0x8a <__bad_interrupt>
  44:	0c 94 45 00 	jmp	0x8a <__bad_interrupt>
  48:	0c 94 45 00 	jmp	0x8a <__bad_interrupt>
  4c:	0c 94 45 00 	jmp	0x8a <__bad_interrupt>
  50:	0c 94 45 00 	jmp	0x8a <__bad_interrupt>

Initialization Code

00000054 <__ctors_end>:
  54:	11 24       	eor	r1, r1
  56:	1f be       	out	0x3f, r1	; 63   Ensure R1 = 0x00
  58:	cf e5       	ldi	r28, 0x5F	; 95   Initialize stack pointer
  5a:	d8 e0       	ldi	r29, 0x08	; 8    Initialize stack pointer
  5c:	de bf       	out	0x3e, r29	; 62   0x3e = SPH
  5e:	cd bf       	out	0x3d, r28	; 61   0x3d = SPL

00000060 <__do_copy_data>:
  60:	10 e0       	ldi	r17, 0x00	; 0    r17=0
  62:	a0 e6       	ldi	r26, 0x60	; 96   X=0x0060
  64:	b0 e0       	ldi	r27, 0x00	; 0     (start of free SRAM)
  66:	e8 ea       	ldi	r30, 0xA8	; 168  Z=0x01a8
  68:	f1 e0       	ldi	r31, 0x01	; 1     (end of program)
  6a:	02 c0       	rjmp	.+4      	; 0x70 <.do_copy_data_start>

0000006c <.do_copy_data_loop>:                  ; Doesn't get here in this case
  6c:	05 90       	lpm	r0, Z+          ; Move from program memory
  6e:	0d 92       	st	X+, r0          ;  to data memory

00000070 <.do_copy_data_start>:
  70:	a0 36       	cpi	r26, 0x60	; 96
  72:	b1 07       	cpc	r27, r17
  74:	d9 f7       	brne	.-10     	; 0x6c <.do_copy_data_loop>
00000076 <__do_clear_bss>:
  76:	10 e0       	ldi	r17, 0x00	; 0
  78:	a0 e6       	ldi	r26, 0x60	; 96
  7a:	b0 e0       	ldi	r27, 0x00	; 0
  7c:	01 c0       	rjmp	.+2      	; 0x80 <.do_clear_bss_start>

0000007e <.do_clear_bss_loop>:
  7e:	1d 92       	st	X+, r1

00000080 <.do_clear_bss_start>:
  80:	a0 36       	cpi	r26, 0x60	; 96
  82:	b1 07       	cpc	r27, r17
  84:	e1 f7       	brne	.-8      	; 0x7e <.do_clear_bss_loop>
  86:	0c 94 97 00 	jmp	0x12e <main>

0000008a <__bad_interrupt>:                     ; Don't know how to deal with
  8a:	0c 94 00 00 	jmp	0x0 <__vectors> ; this, just start at reset vector

Assembled and then Disassembled delay.c Code

0000008e <delay_ms>:

// delay for ms milli-seconds 
// delay times are only half-way accurate if optimization is turned on!
void delay_ms(uint16_t ms) 
{
  8e:	cf 93       	push	r28
  90:	df 93       	push	r29
  92:	cd b7       	in	r28, 0x3d	; 61
  94:	de b7       	in	r29, 0x3e	; 62
  96:	24 97       	sbiw	r28, 0x04	; 4
  98:	0f b6       	in	r0, 0x3f	; 63
  9a:	f8 94       	cli
  9c:	de bf       	out	0x3e, r29	; 62
  9e:	0f be       	out	0x3f, r0	; 63
  a0:	cd bf       	out	0x3d, r28	; 61
  a2:	9a 83       	std	Y+2, r25	; 0x02
  a4:	89 83       	std	Y+1, r24	; 0x01
	volatile uint16_t i;

	for(i=ms;i>0;i--)
  a6:	89 81       	ldd	r24, Y+1	; 0x01
  a8:	9a 81       	ldd	r25, Y+2	; 0x02
  aa:	9c 83       	std	Y+4, r25	; 0x04
  ac:	8b 83       	std	Y+3, r24	; 0x03
  ae:	8b 81       	ldd	r24, Y+3	; 0x03
  b0:	9c 81       	ldd	r25, Y+4	; 0x04
  b2:	00 97       	sbiw	r24, 0x00	; 0
  b4:	51 f0       	breq	.+20     	; 0xca <delay_ms+0x3c>
	{
		delay_us(1000);
  b6:	88 ee       	ldi	r24, 0xE8	; 232
  b8:	93 e0       	ldi	r25, 0x03	; 3
  ba:	0e 94 6e 00 	call	0xdc <delay_us>
  be:	8b 81       	ldd	r24, Y+3	; 0x03
  c0:	9c 81       	ldd	r25, Y+4	; 0x04
  c2:	01 97       	sbiw	r24, 0x01	; 1
  c4:	9c 83       	std	Y+4, r25	; 0x04
  c6:	8b 83       	std	Y+3, r24	; 0x03
  c8:	f2 cf       	rjmp	.-28     	; 0xae <delay_ms+0x20>
  ca:	24 96       	adiw	r28, 0x04	; 4
  cc:	0f b6       	in	r0, 0x3f	; 63
  ce:	f8 94       	cli
  d0:	de bf       	out	0x3e, r29	; 62
  d2:	0f be       	out	0x3f, r0	; 63
  d4:	cd bf       	out	0x3d, r28	; 61
  d6:	df 91       	pop	r29
  d8:	cf 91       	pop	r28
  da:	08 95       	ret

000000dc <delay_us>:
	}
} 

// delay for us micro-seconds 
// delay times are only half-way accurate if optimization is turned on to level 3!
// max value for us is 65535/4*CYCLES_PER_US
// which is app. 17777 for 14.7456MHZ
void delay_us(uint16_t us)
{
  dc:	cf 93       	push	r28
  de:	df 93       	push	r29
  e0:	cd b7       	in	r28, 0x3d	; 61
  e2:	de b7       	in	r29, 0x3e	; 62
  e4:	24 97       	sbiw	r28, 0x04	; 4
  e6:	0f b6       	in	r0, 0x3f	; 63
  e8:	f8 94       	cli
  ea:	de bf       	out	0x3e, r29	; 62
  ec:	0f be       	out	0x3f, r0	; 63
  ee:	cd bf       	out	0x3d, r28	; 61
  f0:	9a 83       	std	Y+2, r25	; 0x02
  f2:	89 83       	std	Y+1, r24	; 0x01
	uint16_t _count;
	_count=us/4*CYCLES_PER_US;
  f4:	89 81       	ldd	r24, Y+1	; 0x01
  f6:	9a 81       	ldd	r25, Y+2	; 0x02
  f8:	96 95       	lsr	r25
  fa:	87 95       	ror	r24
  fc:	96 95       	lsr	r25
  fe:	87 95       	ror	r24
 100:	88 0f       	add	r24, r24
 102:	99 1f       	adc	r25, r25
 104:	88 0f       	add	r24, r24
 106:	99 1f       	adc	r25, r25
 108:	88 0f       	add	r24, r24
 10a:	99 1f       	adc	r25, r25
 10c:	9c 83       	std	Y+4, r25	; 0x04
 10e:	8b 83       	std	Y+3, r24	; 0x03
	
	asm volatile (
 110:	8b 81       	ldd	r24, Y+3	; 0x03
 112:	9c 81       	ldd	r25, Y+4	; 0x04
 114:	01 97       	sbiw	r24, 0x01	; 1
 116:	f1 f7       	brne	.-4      	; 0x114 <delay_us+0x38>
 118:	9c 83       	std	Y+4, r25	; 0x04
 11a:	8b 83       	std	Y+3, r24	; 0x03
 11c:	24 96       	adiw	r28, 0x04	; 4
 11e:	0f b6       	in	r0, 0x3f	; 63
 120:	f8 94       	cli
 122:	de bf       	out	0x3e, r29	; 62
 124:	0f be       	out	0x3f, r0	; 63
 126:	cd bf       	out	0x3d, r28	; 61
 128:	df 91       	pop	r29
 12a:	cf 91       	pop	r28
 12c:	08 95       	ret

Assembled and then Disassembled sampleC.c Code

0000012e <main>:
 * return:
 *     never
 */
int main(void)
{
 12e:	cf e3       	ldi	r28, 0x3F	; 63
 130:	d8 e0       	ldi	r29, 0x08	; 8
 132:	de bf       	out	0x3e, r29	; 62
 134:	cd bf       	out	0x3d, r28	; 61
  sei();                        /* Sets global interrupt flag so ATmon works */
 136:	78 94       	sei
  configPortB(0xff);            /* Configure all pins on PORTB for output */
 138:	8f ef       	ldi	r24, 0xFF	; 255
 13a:	0e 94 cf 00 	call	0x19e <configPortB>

  while(1)                      /* Loop forever */
  {
    PORTB = getPattern(0);      /* Turn every other light on */
 13e:	80 e0       	ldi	r24, 0x00	; 0
 140:	0e 94 b2 00 	call	0x164 <getPattern>
 144:	80 93 38 00 	sts	0x0038, r24
    delay_ms(500);              /* Pass for 0.5 seconds */
 148:	84 ef       	ldi	r24, 0xF4	; 244
 14a:	91 e0       	ldi	r25, 0x01	; 1
 14c:	0e 94 47 00 	call	0x8e <delay_ms>
    PORTB = getPattern(1);      /* Toggle all the lights on/off */
 150:	81 e0       	ldi	r24, 0x01	; 1
 152:	0e 94 b2 00 	call	0x164 <getPattern>
 156:	80 93 38 00 	sts	0x0038, r24
    delay_ms(500);              /* Pass for 0.5 seconds */
 15a:	84 ef       	ldi	r24, 0xF4	; 244
 15c:	91 e0       	ldi	r25, 0x01	; 1
 15e:	0e 94 47 00 	call	0x8e <delay_ms>
 162:	ed cf       	rjmp	.-38     	; 0x13e <main+0x10>

00000164 <getPattern>:
  }
  return 0;                     /* We never get here */
}

Local Variables and the Stack

uint8_t getPattern(uint8_t type)
{
 164:	cf 93       	push	r28
 166:	df 93       	push	r29
 168:	cd b7       	in	r28, 0x3d	; 61
 16a:	de b7       	in	r29, 0x3e	; 62
 16c:	22 97       	sbiw	r28, 0x02	; 2
 16e:	0f b6       	in	r0, 0x3f	; 63
 170:	f8 94       	cli
 172:	de bf       	out	0x3e, r29	; 62
 174:	0f be       	out	0x3f, r0	; 63
 176:	cd bf       	out	0x3d, r28	; 61
 178:	89 83       	std	Y+1, r24	; 0x01
  uint8_t pattern = 0b01010101;
 17a:	85 e5       	ldi	r24, 0x55	; 85
 17c:	8a 83       	std	Y+2, r24	; 0x02
  if(type==1)
 17e:	89 81       	ldd	r24, Y+1	; 0x01
 180:	81 30       	cpi	r24, 0x01	; 1
 182:	11 f4       	brne	.+4      	; 0x188 <getPattern+0x24>
  {
    pattern = 0b10101010;
 184:	8a ea       	ldi	r24, 0xAA	; 170
 186:	8a 83       	std	Y+2, r24	; 0x02
  }
  return pattern;
 188:	8a 81       	ldd	r24, Y+2	; 0x02
 18a:	99 27       	eor	r25, r25
 18c:	22 96       	adiw	r28, 0x02	; 2
 18e:	0f b6       	in	r0, 0x3f	; 63
 190:	f8 94       	cli
 192:	de bf       	out	0x3e, r29	; 62
 194:	0f be       	out	0x3f, r0	; 63
 196:	cd bf       	out	0x3d, r28	; 61
 198:	df 91       	pop	r29
 19a:	cf 91       	pop	r28
 19c:	08 95       	ret

Assembled and then Disassembled configB.s Code

Nothing too spectacular happens here. The assembly code was:

0000019e <configPortB>:
 19e:	0f 93       	push	r16
 1a0:	08 2f       	mov	r16, r24
 1a2:	07 bb       	out	0x17, r16	; 23
 1a4:	0f 91       	pop	r16
 1a6:	08 95       	ret