---------------------------------------------------------------------- Patch name: patch.port-to-gcc version 1.1 Author: Bryce Denney <bryce at tlw dot com> 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<<SPMEN) + #ifdef _ATMEGA104 + STS SPMCSR,R18 ;argument 2 decides function + #else + OUT SPMCR,R18 ;argument 2 decides function + #endif + _SPM ;Store program memory + .word 0xFFFF ;For future part compatibility, instruction alignment + NOP + RCALL WAIT_SPMEN ;Wait for SPMEN flag cleared + +.global read_program_memory +read_program_memory: +// fix parameter passing + RCALL WAIT_SPMEN + + MOV R31,R25 ;R31=ZH R30=ZL + MOV R30,R24 ;move adress to z pointer + SBRC R22,0 ;read lockbits? (second argument=0x09) + ;if so, place second argument in SPMEN register + #ifdef _ATMEGA104 + STS SPMCSR,R22 ;argument 2 decides function + #else + OUT SPMCR,R22 ;argument 2 decides function + #endif + + #ifdef LARGE_MEMORY + ;If large memory (>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<<BLBSET)|(1<<SPMEN)) + + #ifdef _ATMEGA104 + STS SPMCSR,R17 ;argument 2 decides function + #else + OUT SPMCR,R17 ;argument 2 decides function + #endif + + _SPM ;write lockbits + + .word 0xFFFF ;For future part compatibility, instruction alignment + NOP + + RCALL WAIT_SPMEN ;Wait for SPMEN flag cleared + +WAIT_SPMEN: + #ifdef _ATMEGA104 + LDS R19,SPMCSR + SBRC R19,SPMEN + RJMP WAIT_SPMEN ;Wait for SPMEN flag cleared + #endif + + RET diff -urN avr109-dist/assembly.s90 avr109-gcc/assembly.s90 --- avr109-dist/assembly.s90 Fri Jul 13 12:10:52 2001 +++ avr109-gcc/assembly.s90 Wed Dec 31 19:00:00 1969 @@ -1,109 +0,0 @@ - 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 DW 0x95E8 ;Workaround for not having enhanced core Assembler in EWAAVR 2.25 - -write_page: - RCALL WAIT_SPMEN ;Wait for SPMEN flag cleared - MOV R31,R17 - MOV R30,R16 ;move adress to z pointer (R31=ZH R30=ZL) - #ifdef _ATMEGA104 - STS SPMCSR,R18 ;argument 2 decides function - #else - OUT SPMCR,R18 ;argument 2 decides function - #endif - _SPM ;Store program memory - DW 0xFFFF ;For future part compatibility, instruction alignment - NOP - RJMP WAIT_SPMEN ;Wait for SPMEN flag cleared - -fill_temp_buffer: - - RCALL WAIT_SPMEN ;Wait for SPMEN flag cleared - - MOV R31,R19 ;move adress to z pointer (R31=ZH R30=ZL) - MOV R30,R18 - MOV R1,R17 ;move data to reg 0 and 1 - MOV R0,R16 - - LDI R18,(1<<SPMEN) - #ifdef _ATMEGA104 - STS SPMCSR,R18 ;argument 2 decides function - #else - OUT SPMCR,R18 ;argument 2 decides function - #endif - _SPM ;Store program memory - DW 0xFFFF ;For future part compatibility, instruction alignment - NOP - RCALL WAIT_SPMEN ;Wait for SPMEN flag cleared - -read_program_memory: - RCALL WAIT_SPMEN - - MOV R31,R17 ;R31=ZH R30=ZL - MOV R30,R16 ;move adress to z pointer - SBRC R18,0 ;read lockbits? (second argument=0x09) - ;if so, place second argument in SPMEN register - #ifdef _ATMEGA104 - STS SPMCSR,R18 ;argument 2 decides function - #else - OUT SPMCR,R18 ;argument 2 decides function - #endif - - #ifdef LARGE_MEMORY ;If large memory (>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<<BLBSET)|(1<<SPMEN)) - - #ifdef _ATMEGA104 - STS SPMCSR,R17 ;argument 2 decides function - #else - OUT SPMCR,R17 ;argument 2 decides function - #endif - - _SPM ;write lockbits - - DW 0xFFFF ;For future part compatibility, instruction alignment - NOP - - RCALL WAIT_SPMEN ;Wait for SPMEN flag cleared - -WAIT_SPMEN: - #ifdef _ATMEGA104 - LDS R19,SPMCSR - SBRC R19,SPMEN - RJMP WAIT_SPMEN ;Wait for SPMEN flag cleared - #endif - - RET - - END \ No newline at end of file diff -urN avr109-dist/cstartup.s90 avr109-gcc/cstartup.s90 --- avr109-dist/cstartup.s90 Thu Aug 16 11:42:32 2001 +++ avr109-gcc/cstartup.s90 Wed Dec 31 19:00:00 1969 @@ -1,180 +0,0 @@ -;---------------------------------------------------------------------------- -; CSTARTUP.S90 -; -; This module contains the AVR C and EC++ startup -; routine and must usually be tailored to suit -; customer's hardware. -; -; File version: $Revision: 1.5 $ -; -;---------------------------------------------------------------------------- -#include "macros.m90" - -;---------------------------------------------------------------------------- -; Set up the INTVEC segment with a reset vector -;---------------------------------------------------------------------------- - NAME ?RESET -; NAME C_STARTUP - - EXTERN ?C_STARTUP -; PUBLIC __RESTART - - COMMON INTVEC:CODE:ROOT(1) ; Align at an even address - -; EXTERN ?C_STARTUP - - ORG $0 -;__RESTART: - XJMP ?C_STARTUP - - ENDMOD - -;---------------------------------------------------------------------------- -; Forward declarations of segments used in initialization -;---------------------------------------------------------------------------- - RSEG CSTACK(0) - RSEG RSTACK(0) - -;---------------------------------------------------------------------------- -; Perform C initialization -;---------------------------------------------------------------------------- - MODULE ?C_STARTUP - - EXTERN __low_level_init - EXTERN __segment_init -#ifdef _ECLIB - EXTERN __call_ctors -#endif /* _ECLIB */ - EXTERN main - EXTERN exit - EXTERN _exit - -;---------------------------------------------------------------------------- -; If the return address stack is located in external SRAM, make sure that -; you have uncommented the correct code in __low_level_init!!! -;---------------------------------------------------------------------------- - RSEG CODE:CODE:NOROOT(1) - PUBLIC ?C_STARTUP - PUBLIC __RESTART - -__RESTART: -?C_STARTUP: - REQUIRE ?SETUP_STACK - - RSEG CODE:CODE:NOROOT(1) - PUBLIC __RSTACK_in_external_ram - -__RSTACK_in_external_ram: - LDI R16,0xC0 - OUT 0x35,R16 ;Enable the external SRAM with a wait state - -;---------------------------------------------------------------------------- -; Set up the CSTACK and RSTACK pointers. -;---------------------------------------------------------------------------- - RSEG CODE:CODE:NOROOT(1) -?SETUP_STACK: - ;; Return address stack (RSTACK) - LDI R16,LOW(SFE(RSTACK)) - SUBI R16,0x03 - OUT 0x3D,R16 -#if A90_POINTER_REG_SIZE > 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<<PD4) -#define PROGMODE !(PROGPIN & PROGCTRL) // TRUE if PROGCTRL on PROGPIN is low +#define PROGCTRL PD4 +#define PROGMODE !(inp(PROGPIN) & (1<<PROGCTRL)) // TRUE if PROGCTRL on PROGPIN is low #ifdef _ATMEGA32 #include "iom32.h" diff -urN avr109-dist/lnk3s.xcl avr109-gcc/lnk3s.xcl --- avr109-dist/lnk3s.xcl Wed Aug 15 14:32:24 2001 +++ avr109-gcc/lnk3s.xcl Wed Dec 31 19:00:00 1969 @@ -1,52 +0,0 @@ -/* - lnk3s.xcl - - * - * XLINK command file for the ICCAVR C-compiler - * - * - * File version: $Name: $ - */ - -/* - * Modify the lines below to alter the size of the RSTACK, CSTACK and HEAP - * segments. These need to be fine tuned to suit your specific application. - * The '_..X_' prefix is used by C-SPY as an indication that the label should - * not be displayed in the dissassembly window. - */ --D_..X_CSTACK_SIZE=100 /* 256 bytes for auto variables and saved registers. */ --D_..X_RSTACK_SIZE=40 /* 64 bytes for return addresses, equivalent to 32 */ - /* levels of calls, including interrupts. */ --D_..X_HEAP_SIZE=80 /* 128 bytes of heap. */ - -/* Define CPU */ --ca90 - -/* - * The following segments are located in the internal memory. - * Do not change these lines. - */ - -/* Code memory */ - -// Program address space (internal Flash memory) ATmega161,ATmega163 w. 512 word boot block -//-Z(CODE)INTVEC,FAR_F,SWITCH,CODE=3C00-3FFF - -// Program address space (internal Flash memory) ATmega323 w. 512 word boot block --Z(CODE)INTVEC,FAR_F,SWITCH,CODE=7C00-7FFF - -// Program address space (internal Flash memory) ATmega128 w. 512 word boot block -//-Z(CODE)INTVEC,FAR_F,SWITCH,CODE=1FC00-1FFFF - - -/* Internal data memory */ --Z(DATA)TINY_I,TINY_Z,TINY_N=100-10FF --Z(DATA)NEAR_I,NEAR_Z=100-45F --Z(DATA)RSTACK+_..X_RSTACK_SIZE=100-45F --Z(DATA)CSTACK+_..X_CSTACK_SIZE=100-45F --Z(DATA)HEAP+_..X_HEAP_SIZE=100-45F - -/* Internal eeprom memory */ --Z(XDATA)EEPROM_I,EEPROM_N,EEPROM_AN=0-1FF - -/* Suppress one warning which is not relevant for this processor */ --w29 - diff -urN avr109-dist/main.c avr109-gcc/main.c --- avr109-dist/main.c Thu Aug 16 12:49:42 2001 +++ avr109-gcc/main.c Mon Mar 4 03:18:37 2002 @@ -35,11 +35,12 @@ * the used part's boot address and size. Note that memory size * is specified in bytes in the linker file. ****************************************************************************/ +#include <io.h> #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<<RXEN) | (1<<TXEN); // Enable recieve and transmit UART1 + outp (1, UBRRL); // 115200bps @ 3.69 MHz +// outp(11, UBRRL); // 19200bps @ 3.69 MHz + outp ((1<<RXEN) | (1<<TXEN), UCSRB); // Enable receive and transmit UART1 #endif #ifdef _ATMEGA161 - UBRR0 = 11; // 19200bps @ 3.69 MHz - UCSR0B = (1<<RXEN0) | (1<<TXEN0); // Enable recieve and transmit UART1 + outp (11, UBRR0); // 19200bps @ 3.69 MHz + outp ((1<<RXEN0) | (1<<TXEN0), UCSR0B); // Enable receive and transmit UART1 #endif #ifdef _ATMEGA163 - UBRRLO = 11; // 19200bps @ 3.69 MHz - UCSRB = (1<<RXEN) | (1<<TXEN); // Enable recieve and transmit + outp (11, UBRR); // 19200bps @ 3.69 MHz + outp ((1<<RXEN) | (1<<TXEN), UCSRB); // Enable receive and transmit #endif #ifdef _ATMEGA128 - UBRR1L = 1; // 115200bps @ 3.69 MHz -// UBRR1L = 11; // 19200bps @ 3.69 MHz - UCSR1B = (1<<RXEN) | (1<<TXEN); // Enable recieve and transmit + outp (1, UBRR1L); // 115200bps @ 3.69 MHz +// outp (11, UBRR1L); // 19200bps @ 3.69 MHz + outp ((1<<RXEN) | (1<<TXEN), UCSR1B); // Enable receive and transmit #endif - PROGPORT |= PROGCTRL; //enable pull-up on PROGCTRL line on PROGPORT - if(PROGMODE) //If PROGPIN is pulled low: programmingmode. - { + sbi (PROGPORT, PROGCTRL); //enable pull-up on PROGCTRL line on PROGPORT + if (PROGMODE) { //If PROGPIN is pulled low: programming mode. for(;;) { val=recchar(); @@ -183,25 +183,24 @@ } else if (val == 'D') { - EEARL = address; - EEARH = (address >> 8); + outp (address, EEARL); + outp (address >> 8, EEARH); address++; - EEDR = recchar(); - EECR |= (1<<EEMWE); - EECR |= (1<<EEWE); - while (EECR & (1<<EEWE)) + outp (recchar(), EEDR); + sbi (EECR, EEMWE); + while (inp (EECR) & (1<<EEWE)) ; sendchar('\r'); } else if (val == 'd') { - EEARL = address; - EEARH = (address >> 8); + outp (address, EEARL); + outp (address >> 8, EEARH); address++; - EECR |= (1<<EERE); - sendchar(EEDR); - } + outp ((1<<EERE) | inp (EECR), EECR); + sendchar(inp (EEDR)); + } else if(val=='F') // read fuse bits { #ifdef LARGE_MEMORY @@ -272,4 +271,5 @@ { funcptr(); // Jump to Reset vector 0x0000 in Application Section } + return 0; } diff -urN avr109-dist/main.lcf avr109-gcc/main.lcf --- avr109-dist/main.lcf Wed Dec 31 19:00:00 1969 +++ avr109-gcc/main.lcf Mon Mar 4 03:15:59 2002 @@ -0,0 +1,7 @@ +/* linker control file for main.c */ + +MEMORY +{ + /* put everything at word address 0x1e00 (linker is in units of bytes) */ + text (rx) : ORIGIN = 0x3c00, LENGTH = 0x400 +} diff -urN avr109-dist/serial.c avr109-gcc/serial.c --- avr109-dist/serial.c Mon Jul 9 15:17:30 2001 +++ avr109-gcc/serial.c Mon Mar 4 03:15:59 2002 @@ -1,31 +1,38 @@ +#include <io.h> #include "defines.h" void sendchar(char c) { #ifdef _ATMEGA32 - UDR=c; - while (!(UCSRA & (1<<TXC))); //wait until byte sendt - UCSRA |= (1<<TXC); //delete TXCflag + outp (c, UDR); + while (!(inp(UCSRA) & (1<<TXC))); //wait until byte sendt + sbi (UCSRA, TXC); //delete TXCflag #endif #ifdef _ATMEGA161 - UDR0=c; - while (!(UCSR0A & (1<<TXC0))); //wait until byte sendt - UCSR0A |= (1<<TXC0); //delete TXCflag + outp (c, UDR0); + while (!(inp(UCSR0A) & (1<<TXC0))); //wait until byte sendt + sbi (UCSR0A, TXC0); //delete TXCflag #endif #ifdef _ATMEGA163 - UDR=c; - while (!(UCSRA & (1<<TXC))); //wait until byte sendt - UCSRA |= (1<<TXC); //delete TXCflag + outp (c, UDR); + while (!(inp(UCSRA) & (1<<TXC))); //wait until byte sendt + sbi (UCSRA, TXC); //delete TXCflag #endif #ifdef _ATMEGA104 - UDR1=c; - while (!(UCSR1A & (1<<TXC))); //wait until byte sendt - UCSR1A |= (1<<TXC); //delete TXCflag + outp (c, UDR1); + while (!(inp(UCSR1A) & (1<<TXC))); //wait until byte sendt + sbi (UCSR1A, TXC); //delete TXCflag #endif } -char recchar(void) +// recchar must be unsigned char, or the compiler will sign extend its +// result, and the address code in main.c is trashed. +// address=recchar(); +// address=(address<<8)|recchar(); +// With signed char, the second recchar() is sign extended so that 0x80 +// turns into 0xff80, and the high order address bits are lost. +unsigned char recchar(void) { #ifdef _ATMEGA32 while(!(UCSRA & (1<<RXC))); // Wait for data to come @@ -36,8 +43,8 @@ return UDR0; #endif #ifdef _ATMEGA163 - while(!(UCSRA & (1<<RXC))); // Wait for data to come - return UDR; + while(!(inp(UCSRA) & (1<<RXC))); // Wait for data to come + return inp(UDR); #endif #ifdef _ATMEGA104 while(!(UCSR1A & (1<<RXC))); // Wait for data to come diff -urN avr109-dist/serial.h avr109-gcc/serial.h --- avr109-dist/serial.h Thu Jun 17 16:18:34 1999 +++ avr109-gcc/serial.h Mon Mar 4 03:15:59 2002 @@ -1,2 +1,2 @@ void sendchar( char ); -char recchar( void ); +unsigned char recchar( void );