commit 744684bb8862e36e205f7b6e9836f536ee8c8c47 Author: Olaf Rempel Date: Mon May 1 19:10:39 2006 +0200 Version 0.2 (20040324) diff --git a/bin/m16_uart_boot_3_9.hex b/bin/m16_uart_boot_3_9.hex new file mode 100644 index 0000000..15d8c29 --- /dev/null +++ b/bin/m16_uart_boot_3_9.hex @@ -0,0 +1,79 @@ +:103800000C942A1C0C94451C0C94451C0C94451CCF +:103810000C94451C0C94451C0C94451C0C94451CA4 +:103820000C94451C0C94451C0C94451C0C94451C94 +:103830000C94451C0C94451C0C94451C0C94451C84 +:103840000C94451C0C94451C0C94451C0C94451C74 +:103850000C94451C11241FBECFE5D4E0DEBFCDBFC4 +:1038600010E0A0E6B0E0E4ECFCE302C005900D92AD +:10387000A036B107D9F710E0A0E6B0E001C01D9274 +:10388000A336B107E1F70C945D1C0C94001C81E495 +:103890000E94391E86E50E94391E82E50E94391E6B +:1038A00082E40E94391E8FE40E94391E8FE40E9438 +:1038B000391E84E50E94391E0895CFE5D4E0DEBFAD +:1038C000CDBFC0E0D0E001E08FEF8BBB60E08BE0CC +:1038D00090E00E942F1E05BF82E085BFCF9B06C0EF +:1038E00081E085BF15BEFE0109950FC00E944E1EE6 +:1038F0008B3141F40E944E1E8335E1F70E94471C34 +:1039000000E003C08FE30E94391E002339F70E94B4 +:103910004E1E682F813611F489E5B7C08134A9F4B1 +:103920000E944E1E99279093610080936000182F8B +:1039300000270E944E1E9927082B192B000F111FDC +:1039400010936100009360005CC0823641F489E509 +:103950000E94391E80E00E94391E80E896C08234A1 +:1039600089F40E944E1E9927182F00270E944E1E90 +:103970009927082B192B0E944E1E682FC8010E9400 +:10398000481D83C0873689F40E944E1E9927182F40 +:1039900000270E944E1E9927082B192B0E944E1EAD +:1039A000682FC8010E94C31DB2CF853661F5809192 +:1039B00062008537F9F4109261001092600063E0B4 +:1039C00080916000909161000E94FE1D61E18091F4 +:1039D0006000909161000E94FE1D809160009091B6 +:1039E000610080589F4F90936100809360008050E9 +:1039F000984328F361E180916000909161000E94FA +:103A0000FE1D8DE042C0853451F488E190E028E04D +:103A10000FB6F894A89581BD0FBE21BDF2CF8035B9 +:103A200081F38C3471F3803711F483E52EC0843731 +:103A300029F485E70E94391E80E027C0885782302C +:103A400018F40E944E1EDDCF643529F40E944E1EEC +:103A500080936200D6CF633519F40E94471C57CF7C +:103A6000663529F480E30E94391E82E30EC0633775 +:103A700041F483E00E94391E84E90E94391E8EE1E0 +:103A800004C06B3109F443CF8FE30E94391E3FCF4E +:103A9000DF92EF92FF920F931F93CF93DF937C01FE +:103AA000D62EC0916000D091610080916200853770 +:103AB00009F05FC086E46817D1F50E944E1E082FFA +:103AC00011270E944E1E9927982F8827082B192B03 +:103AD0006091600070916100C8010E940D1E80918C +:103AE0006000909161000296909361008093600065 +:103AF0008EEF9FEFE80EF91EE114F104F1F6C078A5 +:103B000065E0CE010E94FE1D61E1CE010E94FE1D16 +:103B100080916000909161009C012078821793074A +:103B200031F020583F4F309361002093600095E4BE +:103B3000D916E1F4809160008EBB80916000909175 +:103B40006100292F33272FBB01969093610080934A +:103B500060000E944E1E8DBBE29AE19AE199FECF71 +:103B60000894E108F108E114F10421F78DE090E0F8 +:103B700002C080E090E0DF91CF911F910F91FF9004 +:103B8000EF90DF9008950F931F93CF93DF93EC0195 +:103B90006534B1F4809160008EBB8091600090919B +:103BA0006100292F33272FBB0196909361008093EA +:103BB0006000E09A8DB30E94391E219759F719C011 +:103BC00060E080916000909161000E94201E8C0155 +:103BD0000E94391E812F99270E94391E8091600012 +:103BE000909161000296909361008093600022970B +:103BF00039F7DF91CF911F910F91089507B600FC1F +:103C0000FDCFE199FECFFC0160935700E895FFFFDF +:103C1000000007B600FCFDCF08959C0107B600FC2C +:103C2000FDCFE199FECF81E00901FB0180935700B0 +:103C3000E895FFFF0000112407B600FCFDCF0895B2 +:103C400007B600FCFDCFE199FECFFC0160FD60935B +:103C50005700C895802DE395C895902D08959C0137 +:103C6000832F992780BD29B988E18AB986E880BD6C +:103C7000089520E030E08CB90FB607FE0BC05E99C6 +:103C80000BC02F5F3F4F5E9907C087E22031380796 +:103C9000C4F302C05E9BFECF5E9A089580E090E080 +:103CA0000FB607FE0AC05F990AC001965F9907C068 +:103CB00027E280319207CCF302C05F9BFECF8CB12C +:043CC00099270895A3 +:0400000300003800C1 +:00000001FF diff --git a/chipdef.h b/chipdef.h new file mode 100644 index 0000000..a1d9280 --- /dev/null +++ b/chipdef.h @@ -0,0 +1,129 @@ + +#ifndef CHIPDEF_H +#define CHIPDEF_H + +#if defined(__AVR_ATmega169__) + #define sig_byte3 0x1E + #define sig_byte2 0x94 + #define sig_byte1 0x05 + + #define devtype 0x79 // Mega 169 device code + + #define PAGESIZE 128 // 2*64 Words = Size in Bytes + + #ifdef _B128 + #define APP_PAGES ((2*8192 / PAGESIZE)- (2*128 / PAGESIZE )) + #define APP_END APP_PAGES * PAGESIZE + #endif + #ifdef _B256 + #define APP_PAGES ((2*8192 / PAGESIZE)- (2*256 / PAGESIZE )) + #define APP_END APP_PAGES * PAGESIZE + #endif + #ifdef _B512 + #define APP_PAGES ((2*8192 / PAGESIZE)- (2*512 / PAGESIZE )) + #define APP_END APP_PAGES * PAGESIZE + #endif + #ifdef _B1024 + #define APP_PAGES ((2*8192 / PAGESIZE)- (2*1024 / PAGESIZE )) + #define APP_END APP_PAGES * PAGESIZE + #endif + #ifdef _B2048 + #error "_B2048 not suppoted on this device" + #endif + +#elif defined(__AVR_ATmega16__) + + #define sig_byte3 0x1E + #define sig_byte2 0x94 + #define sig_byte1 0x03 + + #define devtype 0x75 // Mega16 device code + + #define PAGESIZE 128 // Size in Bytes + + #ifdef _B128 + #define APP_PAGES ((2*8192 / PAGESIZE)- (2*128 / PAGESIZE )) + #define APP_END APP_PAGES * PAGESIZE + #endif + #ifdef _B256 + #define APP_PAGES ((2*8192 / PAGESIZE)- (2*256 / PAGESIZE )) + #define APP_END APP_PAGES * PAGESIZE + #endif + #ifdef _B512 + #define APP_PAGES ((2*8192 / PAGESIZE)- (2*512 / PAGESIZE )) + #define APP_END APP_PAGES * PAGESIZE + #endif + #ifdef _B1024 + #define APP_PAGES ((2*8192 / PAGESIZE)- (2*1024 / PAGESIZE )) + #define APP_END APP_PAGES * PAGESIZE + #endif + #ifdef _B2048 + #error "_B2048 not suppoted on this device" + #endif + +#elif defined(__AVR_ATmega8__) + + #define sig_byte3 0x1E + #define sig_byte2 0x93 + #define sig_byte1 0x07 + + #define devtype 0x77 // Mega8 boot device code + + #define PAGESIZE 64 // Size in Bytes + + #ifdef _B128 + #define APP_PAGES ((2*4096 / PAGESIZE)- (2*128 / PAGESIZE )) + #define APP_END APP_PAGES * PAGESIZE + #endif + #ifdef _B256 + #define APP_PAGES ((2*4096 / PAGESIZE)- (2*256 / PAGESIZE )) + #define APP_END APP_PAGES * PAGESIZE + #endif + #ifdef _B512 + #define APP_PAGES ((2*4096 / PAGESIZE)- (2*512 / PAGESIZE )) + #define APP_END APP_PAGES * PAGESIZE + #endif + #ifdef _B1024 + #define APP_PAGES ((2*4096 / PAGESIZE)- (2*1024 / PAGESIZE )) + #define APP_END APP_PAGES * PAGESIZE + #endif + #ifdef _B2048 + #error "_B2048 not suppoted on this device" + #endif + +#elif defined(__AVR_ATmega32__) + + #define sig_byte3 0x1E + #define sig_byte2 0x95 + #define sig_byte1 0x02 + + #define devtype 0x73 // Mega32 device code + + #define PAGESIZE 128 // Size in Bytes + + #ifdef _B128 + #define APP_PAGES ((2*16384 / PAGESIZE)- (2*128 / PAGESIZE )) + #define APP_END APP_PAGES * PAGESIZE + #endif + #ifdef _B256 + #define APP_PAGES ((2*16384 / PAGESIZE)- (2*256 / PAGESIZE )) + #define APP_END APP_PAGES * PAGESIZE + #endif + #ifdef _B512 + #define APP_PAGES ((2*16384 / PAGESIZE)- (2*512 / PAGESIZE )) + #define APP_END APP_PAGES * PAGESIZE + #endif + #ifdef _B1024 + #define APP_PAGES ((2*16384 / PAGESIZE)- (2*1024 / PAGESIZE )) + #define APP_END APP_PAGES * PAGESIZE + #endif + #ifdef _B2048 + #define APP_PAGES ((2*16384 / PAGESIZE)- (2*2048 / PAGESIZE )) + #define APP_END APP_PAGES * PAGESIZE + #endif + +#else + #error "no definition for MCU available in chipdef.h" +#endif + +#endif diff --git a/lowlevel.c b/lowlevel.c new file mode 100644 index 0000000..61b7843 --- /dev/null +++ b/lowlevel.c @@ -0,0 +1,156 @@ +// +// Low-level bootloader routines to replace "assembly.s90" +// from the original ATMEL code. +// +// See avr-libc's boot-module for more information +// Thanks to Eric B. Weddington author of boot.h. +// +// 3/2004 Martin Thomas, Kaiserslautern, Germany +// +// todo: extend functions with espm + +#include + +// There are some #ifdefs in avr/boot.h V1.0 that do not "know" +// about the ATmega169. So some functions have been copied here +// and small modifications have been done to avoid problems. + +#include "chipdef.h" + +/* Check for SPM Control Register in processor. */ +#if defined (SPMCSR) +# define SPM_REG SPMCSR +#elif defined (SPMCR) +# define SPM_REG SPMCR +#else +# error AVR processor does not provide bootloader support! +#endif + +#define BOOT_PAGE_FILL _BV(SPMEN) +#define BOOT_LOCK_BITS_SET (_BV(SPMEN) | _BV(BLBSET)) + +#define boot_spm_busy() (SPM_REG & (unsigned char)_BV(SPMEN)) +#define boot_spm_busy_wait() do{}while(boot_spm_busy()) +#define eeprom_is_ready() bit_is_clear(EECR, EEWE) +#define eeprom_is_ready_wait() do{}while(!eeprom_is_ready()) + +// from avr/boot.h +// added "func" parameter and spm-busy check at end +#define _boot_page_write_alternate_bf(address,func) \ +({ \ + boot_spm_busy_wait(); \ + eeprom_is_ready_wait(); \ + asm volatile \ + ( \ + "movw r30, %2\n\t" \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + ".word 0xffff\n\t" \ + "nop\n\t" \ + : "=m" (SPM_REG) \ + : "r" ((unsigned char)func), \ + "r" ((unsigned short)address) \ + : "r30", "r31", "r0" \ + ); \ + boot_spm_busy_wait(); \ +}) + +// from avr/boot.h +// added spm-busy check at end +#define _boot_page_fill_alternate_bf(address, data)\ +({ \ + boot_spm_busy_wait(); \ + eeprom_is_ready_wait(); \ + asm volatile \ + ( \ + "movw r0, %3\n\t" \ + "movw r30, %2\n\t" \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + ".word 0xffff\n\t" \ + "nop\n\t" \ + "clr r1\n\t" \ + : "=m" (SPM_REG) \ + : "r" ((unsigned char)BOOT_PAGE_FILL), \ + "r" ((unsigned short)address), \ + "r" ((unsigned short)data) \ + : "r0", "r30", "r31" \ + ); \ + boot_spm_busy_wait(); \ +}) + +// from avr/boot.h +// added spm-busy check at end, removed lockbit-masking, +// removed r30/r31 init - maybe wrong TODO: test this + +#ifdef ENABLEREADFUSELOCK +#define _boot_lock_bits_set_alternate_bf(lock_bits) \ +({ \ + boot_spm_busy_wait(); \ + eeprom_is_ready_wait(); \ + asm volatile \ + ( \ + "mov r0, %2\n\t" \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + ".word 0xffff\n\t" \ + "nop\n\t" \ + : "=m" (SPM_REG) \ + : "r" ((unsigned char)BOOT_LOCK_BITS_SET), \ + "r" ((unsigned char) lock_bits) \ + : "r0" \ + ); \ + boot_spm_busy_wait(); \ +}) + +void write_lock_bits (unsigned char val) +{ + _boot_lock_bits_set_alternate_bf(val); +} +#endif + +void write_page (unsigned int adr, unsigned char function) +{ + _boot_page_write_alternate_bf(adr,function); +} + +void fill_temp_buffer (unsigned int data,unsigned int adr) +{ + _boot_page_fill_alternate_bf(adr, data); +} + +unsigned int read_program_memory(unsigned int adr ,unsigned char param) +// to read lockbits give param=0x09, if param!=0 it is written to SPMCSR +// this is a "translation" from the original code to gcc-inline-assembler +{ + unsigned int retval; + + boot_spm_busy_wait(); + eeprom_is_ready_wait(); + asm volatile + ( + "movw r30, %3\n\t" + "sbrc %2,0x00\n\t" + "sts %0, %2\n\t" + #ifdef LARGE_MEMORY // If large memory (>64K) ELPM is needed to use RAMPZ + "elpm\n\t" // read LSB + #else + "lpm\n\t" // R0 is now the LSB of the return value + #endif + "mov %A1,r0\n\t" + "inc r30\n\t" + #ifdef LARGE_MEMORY // If large memory (>64K) ELPM is needed to use RAMPZ + "elpm\n\t" // read MSB + #else + "lpm\n\t" // R0 is now the MSB of the return value + #endif + "mov %B1,r0\n\t" + : "=m" (SPM_REG), + "=r" (retval) + : "r" ((unsigned char)param), + "r" ((unsigned short)adr) + : "r30", "r31", "r0" + ); + return retval; +} + diff --git a/lowlevel.h b/lowlevel.h new file mode 100644 index 0000000..07f213a --- /dev/null +++ b/lowlevel.h @@ -0,0 +1,9 @@ +#ifndef LOWLEVEL_H +#define LOWLEVEL_H +void write_page (unsigned int adr, unsigned char function); +unsigned int read_program_memory (unsigned int,unsigned char); +void fill_temp_buffer (unsigned int data,unsigned int adr); +#ifdef ENABLEREADFUSELOCK +void write_lock_bits (unsigned char val); +#endif +#endif diff --git a/main.c b/main.c new file mode 100644 index 0000000..233f52f --- /dev/null +++ b/main.c @@ -0,0 +1,446 @@ +/***************************************************************************** +* +* AVRPROG compatible boot-loader +* Version : 0.2 (24. March 2004) +* Compiler : avr-gcc 3.3.1 / avr-libc 1.0 +* size : ca. 610 word ( larger than 512 words :-( ) +* by : Martin Thomas, Kaiserslautern, Germany +* eversmith@heizung-thomas.de +* +* based on the Butterfly Bootloader-Code +* Copyright (C) 1996-1998 Atmel Corporation +* Author(s) : BBrandal, PKastnes, ARodland, LHM +* +* The orignal code has been made available by ATMEL together with the +* Butterfly application code. Since ATMEL.NO had no problem with +* the application gcc-port they hopefully will not have any concerns about +* publishing this port. Make sure to keep the copyright notice in derived +* work to avoid trouble. +**************************************************************************** +* +* Many functions used by "AVRPROG" (fuses) have been disabled by ATMEL in +* the original source code of the Butterfly Boot-loader not by me. +* Please 'diff' against the original source to see everything that has been +* changed for the gcc port. +* +* The boot interrupt vector is included (this bootloader is completly in +* ".text" section). If you need this space for further functions you have to +* add a separate section for the bootloader-functions and add an attribute +* for this section to _all_ function prototypes of functions in the loader. +* With this the interrupt vector will be placed at .0000 and the bootloader +* code (without interrupt vector) at the adress you define in the linker +* options for the newly created section. See the avr-libc FAQ and the avr- +* libc's avr/boot.h documentation for further details. +* +* For this bootloader a Boot-Size of at least 0x4C4 (1220) bytes = +* 610 words is needed. Sorry, so far efforts to shrink to 512 words failed. +* See the makefile for information how to adopt the linker-settings to +* the selected Boot Size (_Bxxx below) +* +****************************************************************************/ + + +#include +#include +#include +#include + + +/* READFUSELOCK is untested, will not work for Mega169 since not + supported by AVRPROG 1.37 */ +// #define ENABLEREADFUSELOCK + +#define BAUDRATE 19200 +#define XTAL 3686400 + +/* Select Boot Size (select one, comment out the others) + select at least _B1024 */ +// NO! #define _B128 +// NO! #define _B256 +// NO! #define _B512 +#define _B1024 +//#define _B2048 + +#include "chipdef.h" + +#define UART_RX_BUFFER_SIZE PAGESIZE + +#include "lowlevel.h" +#include "uart.h" + +unsigned char BufferLoad(unsigned int , unsigned char ) ; +void BlockRead(unsigned int , unsigned char ) ; + +unsigned int address; +unsigned char device; + +void send_boot(void) +{ + sendchar('A'); + sendchar('V'); + sendchar('R'); + sendchar('B'); + sendchar('O'); + sendchar('O'); + sendchar('T'); +} + +int main(void) +{ + void (*funcptr)( void ) = 0x0000; // Set up function pointer + + unsigned int tempi; + char val; + char OK = 1; + + PORTA = 0xFF; // Enable pullups on Port A + + USART_Init(UART_BAUD_SELECT(BAUDRATE,XTAL),UARTSINGLE); + // USART_Init(UART_BAUD_SELECT(BAUDRATE/2,XTAL),UARTDOUBLE); + + MCUCR = (1<> 8) & 0xFF); + // Report buffer size in bytes + sendchar(UART_RX_BUFFER_SIZE & 0xFF); + } + + else if(val=='B') // Start buffer load + { + tempi = recchar() << 8; // Load high byte of buffersize + tempi |= recchar(); // Load low byte of buffersize + val = recchar(); // Load memory type ('E' or 'F') + sendchar (BufferLoad(tempi,val)); + // Start downloading of buffer + } + + else if(val == 'g') // Block read + { + tempi = (recchar() << 8) | recchar(); + + val = recchar(); // Get memtype + BlockRead(tempi,val); // Perform the block read + } +/* + else if(val=='c') //Write program memory, low byte + { + ldata=recchar(); + sendchar('\r'); + } + + else if(val== 'C') //Write program memory, high byte + { + data=ldata|(recchar()<<8); + if (device == devtype) + { + fill_temp_buffer(data,(address)); //call asm routine. + } + address=address+2; + sendchar('\r'); + } +*/ + else if(val=='e') //Chip erase + { + if (device == devtype) + { + for(address=0;address < APP_END;address += PAGESIZE) //Application section = 60 pages + { + write_page(address,(1<>8)); //send MSB + sendchar((char)intval); //send LSB + address=address+2; + } + + else if (val == 'D') // write EEPROM + { + if (device == devtype) + { + EEARL = address; + EEARH = (address >> 8); + address++; + EEDR = recchar(); + EECR |= (1<> 8); + address++; + EECR |= (1<> 8); + address++; // Select next byte + EEDR = recchar(); // Load data to write + EECR |= (1<> 8); + address++; // Select next EEPROM byte + EECR |= (1<> 8)); //send MSB + address += 2; // Select next word in memory + size -= 2; // Subtract two bytes from number of bytes to read + } while (size); // Repeat until all block has been read + } +} + diff --git a/makefile b/makefile new file mode 100644 index 0000000..8034b72 --- /dev/null +++ b/makefile @@ -0,0 +1,405 @@ +# WinAVR makefile written by Eric B. Weddington, Jörg Wunsch, et al. +# Released to the Public Domain +# Please read the make user manual! +# +# Additional material for this makefile was submitted by: +# Tim Henigan +# Peter Fleury +# Reiner Patommel +# Sander Pool +# Frederik Rouleau +# Markus Pfaff +# +# On command line: +# +# make all = Make software. +# +# make clean = Clean out built project files. +# +# make coff = Convert ELF to AVR COFF (for use with AVR Studio 3.x or VMLAB). +# +# make extcoff = Convert ELF to AVR Extended COFF (for use with AVR Studio +# 4.07 or greater). +# +# make program = Download the hex file to the device, using avrdude. Please +# customize the avrdude settings below first! +# +# make filename.s = Just compile filename.c into the assembler code only +# +# To rebuild project do "make clean" then "make all". +# + + +# MCU name +MCU = atmega16 + +# Output format. (can be srec, ihex, binary) +FORMAT = ihex + +# Target file name (without extension). +TARGET = main + +# Optimization level, can be [0, 1, 2, 3, s]. 0 turns off optimization. +# (Note: 3 is not always the best optimization level. See avr-libc FAQ.) +OPT = s + +# List C source files here. (C dependencies are automatically generated.) +SRC = $(TARGET).c + +# If there is more than one source file, append them above, or modify and +# uncomment the following: +# mt: the file test.c can be omitted (remove #inc test.h and test() in main.c) +SRC += lowlevel.c \ +uart.c + + +# You can also wrap lines by appending a backslash to the end of the line: +#SRC += baz.c \ +#xyzzy.c + +# List Assembler source files here. +# Make them always end in a capital .S. Files ending in a lowercase .s +# will not be considered source files but generated files (assembler +# output from the compiler), and will be deleted upon "make clean"! +# Even though the DOS/Win* filesystem matches both .s and .S the same, +# it will preserve the spelling of the filenames, and gcc itself does +# care about how the name is spelled on its command-line. +ASRC = + + +# List any extra directories to look for include files here. +# Each directory must be seperated by a space. +EXTRAINCDIRS = + + +# Optional compiler flags. +# -g: generate debugging information (for GDB, or for COFF conversion) +# -O*: optimization level +# -f...: tuning, see gcc manual and avr-libc documentation +# -Wall...: warning level +# -Wa,...: tell GCC to pass this to the assembler. +# -ahlms: create assembler listing +CFLAGS = -g -O$(OPT) \ +-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums \ +-Wall -Wstrict-prototypes \ +-Wa,-adhlns=$(<:.c=.lst) \ +$(patsubst %,-I%,$(EXTRAINCDIRS)) + + +# Set a "language standard" compiler flag. +# Unremark just one line below to set the language standard to use. +# gnu99 = C99 + GNU extensions. See GCC manual for more information. +#CFLAGS += -std=c89 +#CFLAGS += -std=gnu89 +#CFLAGS += -std=c99 +CFLAGS += -std=gnu99 + + +# Optional assembler flags. +# -Wa,...: tell GCC to pass this to the assembler. +# -ahlms: create listing +# -gstabs: have the assembler create line number information; note that +# for use in COFF files, additional information about filenames +# and function names needs to be present in the assembler source +# files -- see avr-libc docs [FIXME: not yet described there] +ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs + + + +# Optional linker flags. +# -Wl,...: tell GCC to pass this to linker. +# -Map: create map file +# --cref: add cross reference to map file +LDFLAGS = -Wl,-Map=$(TARGET).map,--cref + +# Additional libraries + +# Minimalistic printf version +#LDFLAGS += -Wl,-u,vfprintf -lprintf_min + +# Floating point printf version (requires -lm below) +#LDFLAGS += -Wl,-u,vfprintf -lprintf_flt + +# -lm = math library +LDFLAGS += -lm + +################## BOOTLOADER ###################### +# mt: Boot loader support. So far not done with a separate section +# to get the interrupt vector into the bootloader area. +# bootloader address in datasheet and stk500 is given as +# "word", gcc toolchain needs "byte"-address (here: 0x1C00*2) +MT_BOOTLOADER_ADDRESS = 3800 +LDFLAGS += -Wl,--section-start=.text=$(MT_BOOTLOADER_ADDRESS) + +# Programming support using avrdude. Settings and variables. + +# Programming hardware: alf avr910 avrisp bascom bsd +# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500 +# +# Type: avrdude -c ? +# to get a full listing. +# +AVRDUDE_PROGRAMMER = stk500 + + +AVRDUDE_PORT = com1 # programmer connected to serial device +#AVRDUDE_PORT = lpt1 # programmer connected to parallel port + +AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex +#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep + +AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) + +# Uncomment the following if you want avrdude's erase cycle counter. +# Note that this counter needs to be initialized first using -Yn, +# see avrdude manual. +#AVRDUDE_ERASE += -y + +# Uncomment the following if you do /not/ wish a verification to be +# performed after programming the device. +#AVRDUDE_FLAGS += -V + +# Increase verbosity level. Please use this when submitting bug +# reports about avrdude. See +# to submit bug reports. +#AVRDUDE_FLAGS += -v -v + + + + +# --------------------------------------------------------------------------- + +# Define directories, if needed. +DIRAVR = c:/winavr +DIRAVRBIN = $(DIRAVR)/bin +DIRAVRUTILS = $(DIRAVR)/utils/bin +DIRINC = . +DIRLIB = $(DIRAVR)/avr/lib + + +# Define programs and commands. +SHELL = sh + +CC = avr-gcc + +OBJCOPY = avr-objcopy +OBJDUMP = avr-objdump +SIZE = avr-size + + +# Programming support using avrdude. +AVRDUDE = avrdude + + +REMOVE = rm -f +COPY = cp + +HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex +#mt - use hexadezimal output-fromat // org: ELFSIZE = $(SIZE) -A $(TARGET).elf +ELFSIZE = $(SIZE) -x -A $(TARGET).elf + + +# Define Messages +# English +MSG_ERRORS_NONE = Errors: none +MSG_BEGIN = -------- begin -------- +MSG_END = -------- end -------- +MSG_SIZE_BEFORE = Size before: +MSG_SIZE_AFTER = Size after: +MSG_COFF = Converting to AVR COFF: +MSG_EXTENDED_COFF = Converting to AVR Extended COFF: +MSG_FLASH = Creating load file for Flash: +MSG_EEPROM = Creating load file for EEPROM: +MSG_EXTENDED_LISTING = Creating Extended Listing: +MSG_SYMBOL_TABLE = Creating Symbol Table: +MSG_LINKING = Linking: +MSG_COMPILING = Compiling: +MSG_ASSEMBLING = Assembling: +MSG_CLEANING = Cleaning project: + + + + +# Define all object files. +OBJ = $(SRC:.c=.o) $(ASRC:.S=.o) + +# Define all listing files. +LST = $(ASRC:.S=.lst) $(SRC:.c=.lst) + +# Combine all necessary flags and optional flags. +# Add target processor to flags. +ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) +ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) + + + +# Default target. +all: begin gccversion sizebefore $(TARGET).elf $(TARGET).hex $(TARGET).eep \ + $(TARGET).lss $(TARGET).sym sizeafter finished end + + +# Eye candy. +# AVR Studio 3.x does not check make's exit code but relies on +# the following magic strings to be generated by the compile job. +begin: + @echo + @echo $(MSG_BEGIN) + +finished: + @echo $(MSG_ERRORS_NONE) + +end: + @echo $(MSG_END) + @echo + + +# Display size of file. +sizebefore: + @if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi + +sizeafter: + @if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi + + + +# Display compiler version information. +gccversion : + @$(CC) --version + + + + +# Convert ELF to COFF for use in debugging / simulating in +# AVR Studio or VMLAB. +COFFCONVERT=$(OBJCOPY) --debugging \ + --change-section-address .data-0x800000 \ + --change-section-address .bss-0x800000 \ + --change-section-address .noinit-0x800000 \ + --change-section-address .eeprom-0x810000 + + +coff: $(TARGET).elf + @echo + @echo $(MSG_COFF) $(TARGET).cof + $(COFFCONVERT) -O coff-avr $< $(TARGET).cof + + +extcoff: $(TARGET).elf + @echo + @echo $(MSG_EXTENDED_COFF) $(TARGET).cof + $(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof + + + + +# Program the device. +program: $(TARGET).hex $(TARGET).eep + $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) + + + + +# Create final output files (.hex, .eep) from ELF output file. +%.hex: %.elf + @echo + @echo $(MSG_FLASH) $@ + $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ + +%.eep: %.elf + @echo + @echo $(MSG_EEPROM) $@ + -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ + --change-section-lma .eeprom=0 -O $(FORMAT) $< $@ + +# Create extended listing file from ELF output file. +%.lss: %.elf + @echo + @echo $(MSG_EXTENDED_LISTING) $@ + $(OBJDUMP) -h -S $< > $@ + +# Create a symbol table from ELF output file. +%.sym: %.elf + @echo + @echo $(MSG_SYMBOL_TABLE) $@ + avr-nm -n $< > $@ + + + +# Link: create ELF output file from object files. +.SECONDARY : $(TARGET).elf +.PRECIOUS : $(OBJ) +%.elf: $(OBJ) + @echo + @echo $(MSG_LINKING) $@ + $(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS) + + +# Compile: create object files from C source files. +%.o : %.c + @echo + @echo $(MSG_COMPILING) $< + $(CC) -c $(ALL_CFLAGS) $< -o $@ + + +# Compile: create assembler files from C source files. +%.s : %.c + $(CC) -S $(ALL_CFLAGS) $< -o $@ + + +# Assemble: create object files from assembler source files. +%.o : %.S + @echo + @echo $(MSG_ASSEMBLING) $< + $(CC) -c $(ALL_ASFLAGS) $< -o $@ + + + + + + +# Target: clean project. +clean: begin clean_list finished end + +clean_list : + @echo + @echo $(MSG_CLEANING) + $(REMOVE) $(TARGET).hex + $(REMOVE) $(TARGET).eep + $(REMOVE) $(TARGET).obj + $(REMOVE) $(TARGET).cof + $(REMOVE) $(TARGET).elf + $(REMOVE) $(TARGET).map + $(REMOVE) $(TARGET).obj + $(REMOVE) $(TARGET).a90 + $(REMOVE) $(TARGET).sym + $(REMOVE) $(TARGET).lnk + $(REMOVE) $(TARGET).lss + $(REMOVE) $(OBJ) + $(REMOVE) $(LST) + $(REMOVE) $(SRC:.c=.s) + $(REMOVE) $(SRC:.c=.d) + + +# Automatically generate C source code dependencies. +# (Code originally taken from the GNU make user manual and modified +# (See README.txt Credits).) +# +# Note that this will work with sh (bash) and sed that is shipped with WinAVR +# (see the SHELL variable defined above). +# This may not work with other shells or other seds. +# +%.d: %.c + set -e; $(CC) -MM $(ALL_CFLAGS) $< \ + | sed 's,\(.*\)\.o[ :]*,\1.o \1.d : ,g' > $@; \ + [ -s $@ ] || rm -f $@ + + +# Remove the '-' if you want to see the dependency files generated. +-include $(SRC:.c=.d) + + + +# Listing of phony targets. +.PHONY : all begin finish end sizebefore sizeafter gccversion coff extcoff \ + clean clean_list program + diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..d4ad021 --- /dev/null +++ b/readme.txt @@ -0,0 +1,119 @@ + +====================================================== + + ATMEL AVR UART Bootloader for AVR-GCC/avr-libc + based on the AVR Butterfly bootloader code + + by Martin Thomas, Kaiserslautern, Germany + mthomas@rhrk.uni-kl.de + eversmith@heizung-thomas.de + + This is an adapted version which has been tested + with the ATmega16 but should work with the ATmega8, + ATmega169 and ATmega32. The bootloader uses block/ + page write and is fast. + +====================================================== + + +24. Mar 2004 - Version 0.2 + +During the development of a data-logger application +with the AVR-Butterfly there was a need to make +some changes in the bootloader. The same problem +again: no IAR compiler. The same way to solve the +problem: a port of the code to avr-gcc/avr-libc. +So this code is based on the ATMEL Butterfly +bootloader source code Rev 0.2 for IAR. + +The bootloader-port for the Butterfly which mimics +the complete functionality of the original +BF-bootloader is availabe at: +www.siwawi.arubi.uni-kl.de/avr_projects + +Atmel used a separate "lib" written in "pure" +assembly to access the low-level functions +for flash and eeprom read/write. Well, so far I +don't know how to use "mixed language sources" +with the avr-gcc toolchain, so the low-level +routines have been implemented as inline assembler. +The avr-libc boot.h module written by Eric +Weddington served as a template Three of the four +low-level routines found in lowlevel.c come from +boot.h with minimal changes. The read routine has +been developed based on the ATMEL assembler code. + +Ignore the fuse and lock-bit readout. Read and Set is +not enabled (TODO). + + +--------------- Installation ----------------- + +- Change the MCU type in the makefile (so far + ATmega16 has been tested, ATmega169, ATmega8 + and ATmega32 should be o.k. too. + +- Change the boot(loader)-size in main.c, this + bootloader is larger than 512 words (1024 bytes), + so select at least _B1024! + +- Change the XTAL in main.c to the clock-frequency + of your board (keep BAUDRATE at 19200). See + the datasheet for frequencies with minimum + error at 19200bps and select Crystal/Oscillator + to get minimum errors. + +- Change the start-condition in main.c. Default + is: enter bootloader if Pin A7 is connected to + GND during reset/startup + +- Edit the value MT_BOOTLOADER_ADDRESS in the + makefile according to the selected bootloader + size. Keep in mind that this value has to be + given in bytes (not words) in the linker options. + + i.e. ATMega16, boot-size 1024 words, see + datasheet and find "Boot Reset Adress" for + "Boot Size" 1024 words is 1C00. 1C00 is given + in words, so set MT_BOOTLOADER_ADDRESS to + 3800 (=2*1C00) + +- Please use at least avr-gcc 3.3.1/avr-libc 1.0 + or WINAVR Sept. 2003 or later to compile and link + the bootloader. + +- upload the hex-File to the AVR (STK500, STK200, SP12 + etc.) + +- program the "Boot Flash section size" (BOOTSZ fuses) + according to the boot-size selected in main.c + i.e. BOOTSZ=00 for boot-size 1024 words on ATmega16 + +- enable the BOOT Reset Vector (BOOTTRST=0) + +- Set the lock bits to protect the bootloader from + SPM-writes (Boot Loader Protection Mode 2 in STK500- + plugin) + +- Connect the AVR UART Pins via level-shifter/inverter + (i.e. MAX232) to you PCs Com-Port. + +- Reset the AVR while fullfilling the bootloader start- + condition. Which means connect PA7 to GND in the default + config during reste/power-cycle. Keep the connection + or hold the key down until you see the AVRPROG dialog! + +- Start AVRPROG (AVRStuido/Tools or stand-alone) - + keep PA7 grounded! + +- AVRPROG will detect the bootloader, you may release + PA7 now + +- see AVRStuido online-help for more information how + to use AVRPROG + +- make sure to EXIT from AVRPROG (button) to start + your main-application (or toogle power/reset) + +good luck, feedback welcome. +Martin diff --git a/uart.c b/uart.c new file mode 100644 index 0000000..2bb991c --- /dev/null +++ b/uart.c @@ -0,0 +1,151 @@ + +#include + +/* most of the definitions borrowed from Peter Fleury's UART-Library + extende for control-register C and ATmega169 */ + +#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) \ + || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__) \ + || defined(__AVR_ATmega323__) + /* ATMega with one USART */ + #define ATMEGA_USART + #define UART0_UBRR_HIGH UBRRH + #define UART0_UBRR_LOW UBRRL + #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV + #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA + #define UART0_STATUS UCSRA + #define UART0_CONTROL UCSRB + #define UART0_DATA UDR + #define UART0_UDRIE UDRIE +#elif defined(__AVR_ATmega162__) + /* ATMega with two USART */ + #define ATMEGA_USART0 + #define ATMEGA_USART1 + #define UART0_UBRR_HIGH UBRR0H + #define UART0_UBRR_LOW UBRR0L + #define UART1_UBRR_HIGH UBRR1H + #define UART1_UBRR_LOW UBRR1L + #define UART0_RECEIVE_INTERRUPT SIG_USART0_RECV + #define UART1_RECEIVE_INTERRUPT SIG_USART1_RECV + #define UART0_TRANSMIT_INTERRUPT SIG_USART0_DATA + #define UART1_TRANSMIT_INTERRUPT SIG_USART1_DATA + #define UART0_STATUS UCSR0A + #define UART0_CONTROL UCSR0B + #define UART0_CONTROL2 UCSR0C + #define UART0_DATA UDR0 + #define UART0_UDRIE UDRIE0 + #define UART1_STATUS UCSR1A + #define UART1_CONTROL UCSR1B + #define UART1_CONTROL2 UCSR1C + #define UART1_DATA UDR1 + #define UART1_UDRIE UDRIE1 +#elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) + /* ATMega with two USART */ + #define ATMEGA_USART0 + #define ATMEGA_USART1 + #define UART0_UBRR_HIGH UBRR0H + #define UART0_UBRR_LOW UBRR0L + #define UART1_UBRR_HIGH UBRR1H + #define UART1_UBRR_LOW UBRR1L + #define UART0_RECEIVE_INTERRUPT SIG_UART0_RECV + #define UART1_RECEIVE_INTERRUPT SIG_UART1_RECV + #define UART0_TRANSMIT_INTERRUPT SIG_UART0_DATA + #define UART1_TRANSMIT_INTERRUPT SIG_UART1_DATA + #define UART0_STATUS UCSR0A + #define UART0_CONTROL UCSR0B + #define UART0_CONTROL2 UCSR0C + #define UART0_DATA UDR0 + #define UART0_UDRIE UDRIE0 + #define UART1_STATUS UCSR1A + #define UART1_CONTROL UCSR1B + #define UART1_CONTROL2 UCSR1C + #define UART1_DATA UDR1 + #define UART1_UDRIE UDRIE1 +#elif defined(__AVR_ATmega169__) + #define ATMEGA_USART + #define UART0_UBRR_HIGH UBRR0H + #define UART0_UBRR_LOW UBRR0L + // TODO #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV + // TODO #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA + #define UART0_STATUS UCSR0A + #define UART0_CONTROL UCSR0B + #define UART0_CONTROL2 UCSR0C + #define UART0_DATA UDR0 + #define UART0_DOUBLEAVAIL + // TODO #define UART0_UDRIE UDRIE +#else + #error "Processor type not supported in uart.c !" +#endif + +void USART_Init(unsigned int baudrate, unsigned char doublespeed) +{ + // Set baud rate + UART0_UBRR_HIGH = (unsigned char)(baudrate>>8); + UART0_UBRR_LOW = (unsigned char)baudrate; + + // Enable 2x speed - TODO adopt to all uCs + #ifdef UART0_DOUBLEAVAIL + if (doublespeed) UCSR0A = (1<