---------------------------------------------------------------------- Patch name: patch.port-to-gcc version 1.1 Author: Bryce Denney Date: Mon Mar 4 03:22:37 EST 2002 Detailed description: I have ported Atmel's avr109 code to work with the gcc compiler. See README.port-to-gcc for details. To make this patch, I did diff -urN between a clean version and my working copy, and manually removed any diffs related to CVS (revision control files). Apply patch to: avr109.zip from Atmel application note #109 Instructions: To patch, unzip the avr109.zip file. All the source files land in the current directory. Type "patch -p1 < THIS_PATCH_FILE" to apply this patch. ---------------------------------------------------------------------- diff -urN avr109-dist/Makefile avr109-gcc/Makefile --- avr109-dist/Makefile Wed Dec 31 19:00:00 1969 +++ avr109-gcc/Makefile Mon Mar 4 03:15:56 2002 @@ -0,0 +1,27 @@ +# +# Makefile +# $Id: patch.port-to-gcc,v 1.5 2002/03/04 08:27:08 bryce Exp $ +# +# Makefile for building code for Atmel Application Note 109 using gcc. +# + +MCU=atmega163 +CC=avr-gcc +CFLAGS=-mmcu=$(MCU) -Wa,-ahlms=out.lst -Os -I. +LFLAGS=-mmcu=$(MCU) -Wl,-Map=out.map -L. +all: main + +.c.o: + $(CC) $(CFLAGS) -c $< + +.S.o: + $(CC) $(CFLAGS) -c $< + +main: main.o serial.o assembly.o main.lcf + $(CC) $(LFLAGS) main.o serial.o assembly.o main.lcf -o $@.elf + avr-objcopy -O ihex $@.elf $@ + +clean:: + rm -f *.o main *.elf out.lst out.map + +main.o: main.c defines.h assembly.h diff -urN avr109-dist/README.gcc avr109-gcc/README.gcc --- avr109-dist/README.gcc Wed Dec 31 19:00:00 1969 +++ avr109-gcc/README.gcc Mon Mar 4 03:18:49 2002 @@ -0,0 +1,67 @@ +README.port-to-gcc +Patch version 1.0 +Bryce Denney (bryce at tlw dot com) + +This file is created when you take the code for Atmel Appnote 109 +and apply my patch.port-to-gcc. The readme describes the changes included +in the patch. + +The original appnote 109 code can be found at + http://www.atmel.com + more specifically ftp://www.atmel.com/pub/atmel/avr109.zip + +Here's what I did in this patch: +- enabled ATMEGA163 everywhere, since that's what I can test on. +- added a Makefile which compiles with avr-gcc. +- renamed assembly.s90 to assembly.S and hacked it until it worked. + - commented out the lines at the top which are not understood by gnu tools: + NAME, RSEG, PUBLIC, etc. + - changed "DW data" syntax to ".word data" syntax (e.g. in #define _SPM) + - the C function argument passing conventions are clearly different between + IAR and gcc. The original code (intended for IAR) expects the first + argument to be in R16/R17, the second argument in R18, etc. But gcc + puts the first argument into R24/R25, then the second argument into + R22/R23, etc. I changed the register numbers in the assembly code so + that they would use correct data passed from the C functions. +- removed cstartup.s90 since avr-gcc creates its own. +- removed lnk3s.xcl linker file, and created one that gnu tools can understand + called main.lcf. I've never written a linker control file before, so + there are probably cleaner ways to do this, but it works. main.lcf + causes the linker to put all the code at word address 0x1e00. Since the + linker uses units of bytes, this translates to byte address 0x3c00. +- in all C code: + - include io.h which defines I/O macros for AVR + - change to gcc syntax for I/O reads and writes. inp(PINC) to read port c, + outp (value, PORTC) to write port c. +- in serial.c, changed recchar() return value type to UNSIGNED char. If it is + treated as signed char, you have big problems in the line in main.c + address=(address<<8)|recchar(); + Sign extension of recchar() can wipe out all high bits from address<<8. + +Version Information: +These are the packages I am using to compile and test this code. +- gcc version 3.0 compiled with ./configure --target=avr --enable-languages=c +- binutils 2.11 compiled with ./configure --target=avr +- avr-libc 2001-10-29 +- uisp 2001-10-25 in linux, using serial port interface + +You will need to set the fuses on your atmega so that it jumps to the +boot loader. There is one bit that tells it to jump to the boot loader, +and a few bits that control the size of the boot loader. + +Results: +- ATmega163: everything compiles and programming works. I tested with + uisp in Linux, at 2400 baud. +- ATmega161: won't compile because libc is missing PGERS, SPMEN, PGWRT. + On my machine these are missing from the include file + /usr/local/avr/include/iom161.h. If you are missing them, add + the following lines to defines.h: + /* define SPMCR bits for mega161 */ + #define BLBSET 3 + #define PGWRT 2 + #define PGERS 1 + #define SPMEN 0 +- ATmega32: linker error: unrecognised emulation mode: avr5 + ??? +- ATmega128: compiler error: MCU `atmega128' not supported + ??? diff -urN avr109-dist/assembly.S avr109-gcc/assembly.S --- avr109-dist/assembly.S Wed Dec 31 19:00:00 1969 +++ avr109-gcc/assembly.S Mon Mar 4 03:15:56 2002 @@ -0,0 +1,115 @@ +; NAME assembly(16) +; RSEG CODE(0) +; RSEG UDATA0(0) +; PUBLIC fill_temp_buffer +; PUBLIC write_page +; PUBLIC write_lock_bits +; PUBLIC read_program_memory +; EXTERN ?CL0T_1_40_L08 +; RSEG CODE + +#include "defines.h" + +#define _SPM .word 0x95E8 ;Workaround for not having enhanced core Assembler in EWAAVR 2.25 + +.global write_page +write_page: + RCALL WAIT_SPMEN ;Wait for SPMEN flag cleared + MOV R31,R25 + MOV R30,R24 ;move adress to z pointer (R31=ZH R30=ZL) +#ifdef _ATMEGA104 + STS SPMCSR,R22 ;argument 2 decides function +#else + OUT SPMCR,R22 ;argument 2 decides function +#endif + _SPM ;Store program memory + .word 0xFFFF ;For future part compatibility, instruction alignment + NOP + RJMP WAIT_SPMEN ;Wait for SPMEN flag cleared + +.global fill_temp_buffer +fill_temp_buffer: +// fixed parameters + + RCALL WAIT_SPMEN ;Wait for SPMEN flag cleared + + MOV R31,R23 ;move adress to z pointer (R31=ZH R30=ZL) + MOV R30,R22 + MOV R1,R25 ;move data to reg 0 and 1 + MOV R0,R24 + + LDI R18,(1<64K) ELPM is needed to use RAMPZ + ELPM ;read LSB + #else + LPM + #endif + + MOV R24,R0 ;read LSB + INC R30 + + #ifdef LARGE_MEMORY //If large memory (>64K) ELPM is needed to use RAMPZ + ELPM ;read LSB + #else + LPM + #endif + + MOV R25,R0 ;read MSB (ignored when reading lockbits) + + RET + +.global write_lock_bits +write_lock_bits: +// fixed parameter passing + RCALL WAIT_SPMEN ;Wait for SPMEN flag cleared + + MOV R0,R24 + LDI R17,((1<64K) ELPM is needed to use RAMPZ - ELPM ;read LSB - #else - LPM - #endif - - MOV R16,R0 ;read LSB - INC R30 - - #ifdef LARGE_MEMORY ;If large memory (>64K) ELPM is needed to use RAMPZ - ELPM ;read LSB - #else - LPM - #endif - - MOV R17,R0 ;read MSB (ignored when reading lockbits) - - RET - -write_lock_bits: - RCALL WAIT_SPMEN ;Wait for SPMEN flag cleared - - MOV R0,R16 - LDI R17,((1< 1 - LDI R16,HIGH(SFE(RSTACK)) - SBCI R16,0x00 - OUT 0x3E,R16 -#endif - - ;; Data stack (CSTACK) - LDI Y0,LOW(SFE(CSTACK)) -#if A90_POINTER_REG_SIZE > 1 - LDI Y1,HIGH(SFE(CSTACK)) -#if A90_POINTER_REG_SIZE > 2 - LDI Z0,HWRD(SFE(CSTACK)) - OUT RAMPY,Z0 -#endif -#endif - - REQUIRE ?call_low_level_init - -;---------------------------------------------------------------------------- -; Clear R15 so that it can be used as zero register by the code generator. -; The compiler will emit a "REQUIRE ?zero_reg_initialization" statement if -; this optimization has been enabled. -;---------------------------------------------------------------------------- - RSEG CODE:CODE:NOROOT(1) - PUBLIC ?zero_reg_initialization - -?zero_reg_initialization: - CLR R15 - -;---------------------------------------------------------------------------- -; Call __low_level_init to do low level initializatons. Modify the supplied -; __low_level_init module to add your own initialization code or to -; remove segment initialization (by returning 0). -;---------------------------------------------------------------------------- - RSEG CODE:CODE:NOROOT(1) - PUBLIC ?call_low_level_init - -?call_low_level_init: - XCALL __low_level_init - - REQUIRE ?cstartup_call_main - -;---------------------------------------------------------------------------- -; Call __segment_init to initialize segments. -;---------------------------------------------------------------------------- - RSEG CODE:CODE:NOROOT(1) - PUBLIC ?need_segment_init - -?need_segment_init: - TST P0 - BREQ ?skip_segment_init - XCALL __segment_init -?skip_segment_init: - -;---------------------------------------------------------------------------- -; Call the constructors of all global objects. This code will only -; be used if any EC++ modules defines global objects that need to -; have its constructor called before main. -;---------------------------------------------------------------------------- -#ifdef _ECLIB - RSEG DIFUNCT(0) -#endif /* _ECLIB */ - RSEG CODE:CODE:NOROOT(1) - - PUBLIC ?call_ctors - -?call_ctors: -#ifdef _ECLIB - LDI P0,LOW(SFB(DIFUNCT)) - LDI P1,SFB(DIFUNCT) >> 8 - - LDI P2,LOW(SFE(DIFUNCT)) - LDI P3,SFE(DIFUNCT) >> 8 - - XCALL __call_ctors -#endif /* _ECLIB */ - -;---------------------------------------------------------------------------- -; Call main -;---------------------------------------------------------------------------- - RSEG CODE:CODE:NOROOT(1) - - PUBLIC ?cstartup_call_main - -?cstartup_call_main: -#if MEMORY_MODEL != LARGE_MEMORY_MODEL -#if A90_PROC_OPTION > 1 - LDI R16,0 - OUT RAMPZ,R16 -#if A90_POINTER_REG_SIZE > 2 - OUT RAMPY,R16 - OUT RAMPX,R16 -#endif /* A90_POINTER_REG_SIZE > 2 */ -#endif /* A90_PROC_OPTION > 1 */ -#endif /* MEMORY_MODEL != LARGE_MEMORY_MODEL */ - - XCALL main - XCALL exit - XJMP _exit - - END diff -urN avr109-dist/defines.h avr109-gcc/defines.h --- avr109-dist/defines.h Thu Aug 16 12:54:42 2001 +++ avr109-gcc/defines.h Mon Mar 4 03:15:58 2002 @@ -1,7 +1,7 @@ /* Select Device (Select one, comment out the others) */ -#define _ATMEGA32 +//#define _ATMEGA32 //#define _ATMEGA161 -//#define _ATMEGA163 +#define _ATMEGA163 //#define _ATMEGA128 /* Select Boot Size (select one, comment out the others). @@ -17,8 +17,8 @@ // Define pin for enter selfprogramming mode #define PROGPORT PORTD #define PROGPIN PIND -#define PROGCTRL (1< #include "defines.h" #include "serial.h" #include "assembly.h" -__C_task void main(void) +int main(void) { void (*funcptr)( void ) = 0x0000; // Set up function pointer @@ -47,30 +48,29 @@ unsigned char val, ldata; #ifdef _ATMEGA32 - UBRRL = 1; // 115200bps @ 3.69 MHz -// UBRRL = 11; // 19200bps @ 3.69 MHz - UCSRB = (1<> 8); + outp (address, EEARL); + outp (address >> 8, EEARH); address++; - EEDR = recchar(); - EECR |= (1<> 8); + outp (address, EEARL); + outp (address >> 8, EEARH); address++; - EECR |= (1< #include "defines.h" void sendchar(char c) { #ifdef _ATMEGA32 - UDR=c; - while (!(UCSRA & (1<