From 744684bb8862e36e205f7b6e9836f536ee8c8c47 Mon Sep 17 00:00:00 2001 From: Olaf Rempel Date: Mon, 1 May 2006 19:10:39 +0200 Subject: [PATCH] Version 0.2 (20040324) --- bin/m16_uart_boot_3_9.hex | 79 +++++++ chipdef.h | 129 +++++++++++ lowlevel.c | 156 +++++++++++++ lowlevel.h | 9 + main.c | 446 ++++++++++++++++++++++++++++++++++++++ makefile | 405 ++++++++++++++++++++++++++++++++++ readme.txt | 119 ++++++++++ uart.c | 151 +++++++++++++ uart.h | 13 ++ 9 files changed, 1507 insertions(+) create mode 100644 bin/m16_uart_boot_3_9.hex create mode 100644 chipdef.h create mode 100644 lowlevel.c create mode 100644 lowlevel.h create mode 100644 main.c create mode 100644 makefile create mode 100644 readme.txt create mode 100644 uart.c create mode 100644 uart.h 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<