Version 0.7 (20050226)

This commit is contained in:
Olaf Rempel 2006-05-01 19:15:27 +02:00
parent f32c7e3131
commit f2c227f428
9 changed files with 715 additions and 1182 deletions

1
avrprog_boot.pnproj Normal file
View File

@ -0,0 +1 @@
<Project name="avrprog_boot"><File path="uart.h"></File><File path="lowlevel.c"></File><File path="lowlevel.h"></File><File path="main.c"></File><File path="makefile"></File><File path="readme.txt"></File><File path="uart.c"></File><File path="chipdef.h"></File><File path="main.lss"></File></Project>

View File

@ -0,0 +1,93 @@
:107800000C942A3C0C94453C0C94453C0C94453C0F
:107810000C94453C0C94453C0C94453C0C94453CE4
:107820000C94453C0C94453C0C94453C0C94453CD4
:107830000C94453C0C94453C0C94453C0C94453CC4
:107840000C94453C0C94453C0C94453C0C94453CB4
:107850000C94453C11241FBECFE5D8E0DEBFCDBF60
:1078600010E0A0E6B0E0EEEAFDE702C005900D9260
:10787000A036B107D9F710E0A0E6B0E001C01D9234
:10788000A73EB107E1F70C94803D0C94003C81E4E5
:107890000E94A73E86E50E94A73E82E50E94A73E81
:1078A00082E40E94A73E8FE40E94A73E8FE40E94DC
:1078B000A73E84E50E94A73E0895BF92CF92DF9233
:1078C000EF92FF920F931F93CF93DF938C01B62E0D
:1078D00020E030E0E901CE59DF4F79010894E11C46
:1078E000F11C2017310718F40E94BC3E01C08FEF35
:1078F000888397012038310568F320E030E0C0909C
:10790000E200D090E300E090E400F090E5008CB35A
:10791000992796958795AC014170507080FDF7CFFF
:107920008091E600833709F08EC086E4B81609F02E
:1079300048C041E0C2E6D0E08991282F33278991E1
:107940009927982F8827282B392B07B600FCFDCFC5
:10795000E199FECF8091E2009091E3000901FC01E2
:1079600040935700E89511248091E2009091E30044
:10797000A091E400B091E5000296A11DB11D809395
:10798000E2009093E300A093E400B093E50002507E
:10799000104091F607B600FCFDCFE199FECF85E0DF
:1079A000F60180935700E89507B600FCFDCF07B6B7
:1079B00000FCFDCFE199FECF81E180935700E8956F
:1079C0003FC085E4B816E1F58091E2009091E300B4
:1079D000A091E400B091E500B695A795979587959D
:1079E0008093E2009093E300A093E400B093E5005D
:1079F000F901EF59FF4F8091E2008EBB8091E200C8
:107A00009091E300A091E400B091E500292F3A2F76
:107A10004B2F55272FBB0196A11DB11D8093E2006E
:107A20009093E300A093E400B093E5003196808149
:107A30008DBBE29AE19AE199FECF01501040D9F650
:107A40008DE090E001C0CA01DF91CF911F910F91AD
:107A5000FF90EF90DF90CF90BF9008950F931F930A
:107A6000CF93DF93EC01E199FECF653411F580915E
:107A7000E2008EBB8091E2009091E300A091E400CF
:107A8000B091E500292F3A2F4B2F55272FBB019698
:107A9000A11DB11D8093E2009093E300A093E40048
:107AA000B093E500E09A8DB30E94A73E2197F9F6C6
:107AB00022C0E091E200F091E30005911491802F43
:107AC0000E94A73E812F99270E94A73E8091E20045
:107AD0009091E300A091E400B091E5000296A11D11
:107AE000B11D8093E2009093E300A093E400B09373
:107AF000E5002297F1F6DF91CF911F910F91089544
:107B0000CFE5D8E0DEBFCDBFF89401E005BF82E04D
:107B100085BF60E08BE090E00E949D3EA098A89A0F
:107B2000989B08C0A89805BF15BEE0916000F09131
:107B3000610009950E94BC3E682F813611F489E5E9
:107B4000F9C0813439F50E94BC3E9927AA27BB278A
:107B50008093E2009093E300A093E400B093E500EB
:107B6000EE24F82E092F1A2F0E94BC3E9927AA272F
:107B7000BB27E82AF92A0A2B1B2BEE0CFF1C001F3F
:107B8000111FE092E200F092E3000093E4001093F2
:107B9000E50072C0823641F489E50E94A73E80E08C
:107BA0000E94A73E80E8C6C0823489F40E94BC3E91
:107BB0009927182F00270E94BC3E9927082B192BC4
:107BC0000E94BC3E682FC8010E945D3CB3C087364E
:107BD00089F40E94BC3E9927182F00270E94BC3EC2
:107BE0009927082B192B0E94BC3E682FC8010E94C0
:107BF0002E3DA0CF853609F041C08091E600833745
:107C000091F51092E2001092E3001092E4001092BD
:107C1000E50023E007B600FCFDCFE199FECF80919F
:107C2000E2009091E300FC0120935700E89507B62D
:107C300000FCFDCF8091E2009091E300A091E40070
:107C4000B091E50080589F4FAF4FBF4F8093E20047
:107C50009093E300A093E400B093E5008050984730
:107C6000A040B040B8F207B600FCFDCFE199FECFCE
:107C700081E180935700E8958DE05CC0853451F434
:107C800088E190E028E00FB6F894A89581BD0FBE7A
:107C900021BDF2CF803581F38C3471F3803711F43C
:107CA00083E548C0863421F469E080E090E005C0B7
:107CB000823731F469E081E090E00E94D03E3AC022
:107CC0008E3421F469E083E090E0F7CF813521F430
:107CD00069E082E090E0F1CF843729F483E70E94E5
:107CE000A73E80E027C08857823018F40E94BC3E2F
:107CF000C3CF643529F40E94BC3E8093E600BCCF1C
:107D0000633519F40E94473C15CF663529F480E3AA
:107D10000E94A73E87E30EC0633741F482E00E94D1
:107D2000A73E85E90E94A73E8EE104C06B3109F4AD
:107D300001CF8FE30E94A73EFDCE9C01832F9927A0
:107D400080BD29B988E18AB986E880BD089520E020
:107D500030E08CB90FB607FE0BC05E990BC02F5FE9
:107D60003F4F5E9907C087E220313807C4F302C055
:107D70005E9BFECF5E9A089580E090E00FB607FE0E
:107D80000AC05F990AC001965F9907C027E2803157
:107D90009207CCF302C05F9BFECF8CB19927089568
:0E7DA000FC0160935700C895802D9927089527
:040000030000780081
:00000001FF

View File

@ -107,23 +107,50 @@
// #define PAGESIZE 128 // Size in Bytes
#ifdef _B128
#define APP_PAGES ((2*16384 / SPM_PAGESIZE)- (2*128 / SPM_PAGESIZE ))
#define APP_PAGES ((2*16384UL / SPM_PAGESIZE)- (2*128 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B256
#define APP_PAGES ((2*16384 / SPM_PAGESIZE)- (2*256 / SPM_PAGESIZE ))
#define APP_PAGES ((2*16384UL / SPM_PAGESIZE)- (2*256 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B512
#define APP_PAGES ((2*16384 / SPM_PAGESIZE)- (2*512 / SPM_PAGESIZE ))
#define APP_PAGES ((2*16384UL / SPM_PAGESIZE)- (2*512 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B1024
#define APP_PAGES ((2*16384 / SPM_PAGESIZE)- (2*1024 / SPM_PAGESIZE ))
#define APP_PAGES ((2*16384UL / SPM_PAGESIZE)- (2*1024 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B2048
#define APP_PAGES ((2*16384 / SPM_PAGESIZE)- (2*2048 / SPM_PAGESIZE ))
#define APP_PAGES ((2*16384UL / SPM_PAGESIZE)- (2*2048 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#elif defined(__AVR_ATmega128__)
#define sig_byte3 0x1E
#define sig_byte2 0x97
#define sig_byte1 0x02
#define devtype 0x44 // Mega128 device code
// #define PAGESIZE 128 // Size in Bytes
#ifdef _B512
#define APP_PAGES ((2*65536UL / SPM_PAGESIZE)- (2*512 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B1024
#define APP_PAGES ((2*65536UL / SPM_PAGESIZE)- (2*1024 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B2048
#define APP_PAGES ((2*65536UL / SPM_PAGESIZE)- (2*2048 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B4096
#define APP_PAGES ((2*65536UL / SPM_PAGESIZE)- (2*4096 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif

View File

@ -1,42 +1,25 @@
//
// Low-level bootloader routines to replace "assembly.s90"
// from the original ATMEL Butterfly bootloader code
// which are not included in avr-libc's boot.h by the
// time of writing this.
// Low-level routines to read lock and fuse-bytes
//
// 3/2004 Martin Thomas, Kaiserslautern, Germany
// Copyright (C) 2/2005 Martin Thomas, Kaiserslautern, Germany
//
#include "lowlevel.h"
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 char read_fuse_lock(unsigned short addr, unsigned char mode)
{
unsigned int retval;
unsigned char retval;
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"
"movw r30, %3\n\t" /* Z to addr */ \
"sts %0, %2\n\t" /* set mode in SPM_REG */ \
"lpm\n\t" /* load fuse/lock value into r0 */ \
"mov %1,r0\n\t" /* save return value */ \
: "=m" (SPM_REG),
"=r" (retval)
: "r" ((unsigned char)param),
"r" ((unsigned short)adr)
: "r" (mode),
"r" (addr)
: "r30", "r31", "r0"
);
return retval;

View File

@ -12,7 +12,7 @@
# error AVR processor does not provide bootloader support!
#endif
unsigned int read_program_memory (unsigned int,unsigned char);
unsigned char read_fuse_lock(unsigned short addr, unsigned char mode);
#endif

216
main.c
View File

@ -1,17 +1,18 @@
/*****************************************************************************
*
* AVRPROG compatible boot-loader
* Version : 0.5 (7. Apr. 2004)
* Compiler : avr-gcc 3.3.1 / avr-libc 1.0
* Version : 0.7 (Feb. 2005)
* Compiler : avr-gcc 3.4.1 / avr-libc 1.0.2
* size : depends on features and startup ( minmal features < 512 words)
* by : Martin Thomas, Kaiserslautern, Germany
* eversmith@heizung-thomas.de
*
* License : none. free code and free to use and modify
* BUT: Please send me bug-reports if you find out that
* something has been done wrong. You may mention where
* you've got the source in the documention of your
* project if you're using this bootloader.
* License : Copyright (c) 2005 Martin Thomas
* Free to use. You have to mention the copyright
* owners in source-code and documentation of derived
* work. No warranty.
*
* Tested with ATmega8, ATmega16, ATmega32, ATmega128
*
* - based on the Butterfly Bootloader-Code
* Copyright (C) 1996-1998 Atmel Corporation
@ -27,11 +28,6 @@
*
****************************************************************************
*
* Many functions used by "AVRPROG" (fuses) have been disabled by ATMEL in
* the original source code of the Butterfly Boot-loader not by me.
* I will try to make all of them available in later versions but i.e the
* ATmega169 is not completly supported by AVRPROG 1.37.
*
* 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
@ -47,25 +43,32 @@
* With BOOT_SIMPLE this bootloader has 0x3DE bytes size and should fit
* into a 512word bootloader-section.
*
* Set AVR clock-frequency and the baudrate below, set MCU-type in
* makefile.
*
****************************************************************************/
/*
Does not work so far:
- fuse high byte read (or parse in AVRPROG?)
Does not work reliably so far:
- lock bits set
*/
// programmers-notepad tabsize 4
#define VERSION_HIGH '0'
#define VERSION_LOW '5'
#define VERSION_LOW '7'
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <avr/boot.h>
#include <avr/pgmspace.h>
// function not found in boot.h to read lock/fuses
#include "lowlevel.h"
/* Port and Pin in this port that has to grounded
/* Pin "BLPNUM" on port "BLPORT" in this port has to grounded
(active low) to start the bootloader */
#define BLPORT PORTC
#define BLDDR DDRC
#define BLPIN PINC
#define BLPNUM PINC0
@ -89,6 +92,7 @@
#ifndef START_BOOTICE
#define XTAL 3686400
// #define XTAL 8000000UL
#else
#warning "BOOTICE mode - External Crystal/Oszillator must be 7,3728 MHz"
#define XTAL 7372800
@ -100,13 +104,14 @@
/* enable/disable readout of fuse and lock-bits
(will not work for Mega169 since not supported by AVRPROG 1.37 */
// #define ENABLEREADFUSELOCK
#define ENABLEREADFUSELOCK
/* enable/disable write of lock-bits
WARNING: lock-bits can not be reseted by bootloader (as far as I know)
Only protection no unprotection, "chip erase" from bootloader only
clears the flash but does no real "chip erase" (this is not possible
with a bootloader as far as I know)
Keep this undefined!
*/
// #define WRITELOCKBITS
@ -119,14 +124,6 @@
#include "chipdef.h"
// this uses the latest version from avr-libc CVS not the one that comes
// with WINAVR Sep./03 (6.Apr.04: it's like the boot.h from the Apr/04
// WINAVR but the lock-bit-mask has been changed. Found out during the
// development of a STK500-plugin-compatible-bootloader)
#include "myboot.h"
// functions not found in boot.h
#include "lowlevel.h"
#define UART_RX_BUFFER_SIZE SPM_PAGESIZE
unsigned char gBuffer[UART_RX_BUFFER_SIZE];
@ -136,7 +133,7 @@ unsigned char gBuffer[UART_RX_BUFFER_SIZE];
unsigned char BufferLoad(unsigned int , unsigned char ) ;
void BlockRead(unsigned int , unsigned char ) ;
unsigned short address;
uint32_t address;
unsigned char device;
void send_boot(void)
@ -154,13 +151,15 @@ void (*jump_to_app)(void) = 0x0000;
int main(void)
{
unsigned short tempi;
unsigned tempi;
char val;
#ifdef START_POWERSAVE
char OK = 1;
#endif
cli();
MCUCR = (1<<IVCE);
MCUCR = (1<<IVSEL); //move interruptvectors to the Boot sector
@ -174,23 +173,24 @@ int main(void)
the main parser-loop gives a lot a possibilities (timeout, sleep-modes
etc.).
*/
BLPORT = 0xFF; // Enable pullups on Port C
BLDDR &= ~(1<<BLPNUM); // set as Input
BLPORT |= (1<<BLPNUM); // Enable pullup
for(;OK;)
{
if((BLPIN & (1<<BLPNUM)))
{
// jump to main app if PIN C0 is not grounded
BLPORT = 0x00; // set to default
// jump to main app if pin is not grounded
BLPORT &= ~(1<<BLPNUM); // set to default
MCUCR = (1<<IVCE);
MCUCR = (0<<IVSEL); //move interruptvectors to the Application sector
MCUCR = (0<<IVSEL); // move interruptvectors to the Application sector
jump_to_app(); // Jump to application sector
}
else
{
val = recchar();
if( val == 0x1B)
if( val == 0x1B ) /* ESC */
{ // AVRPROG connection
while (val != 'S') // Wait for signon
{
@ -206,11 +206,13 @@ int main(void)
}
#elif defined(START_SIMPLE)
BLPORT = 0xFF; // Enable pullups on Port C
BLDDR &= ~(1<<BLPNUM); // set as Input
BLPORT |= (1<<BLPNUM); // Enable pullup
if((BLPIN & (1<<BLPNUM)))
{
// jump to main app if PIN C0 is not grounded
BLPORT = 0x00; // set to default
// jump to main app if pin is not grounded
BLPORT &= ~(1<<BLPNUM); // set to default
MCUCR = (1<<IVCE);
MCUCR = (0<<IVSEL); //move interruptvectors to the Application sector
jump_to_app(); // Jump to application sector
@ -218,6 +220,7 @@ int main(void)
#elif defined(START_BOOTICE)
#warning "BOOTICE mode - no startup-condition"
#else
#error "Select START_ condition for bootloader in main.c"
#endif
@ -236,7 +239,7 @@ int main(void)
address=recchar(); //read address 8 MSB
address=(address<<8)|recchar();
address=address<<1; //convert from word address to byte address
address=address<<1; // !! convert from word address to byte address
sendchar('\r');
}
@ -264,51 +267,33 @@ int main(void)
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)
{
// erase only main section (bootloader protection)
for(address=0;address < APP_END;address += SPM_PAGESIZE) //Application section = 60 pages
address = 0;
while ( APP_END > address )
{
//write_page(address,(1<<PGERS) + (1<<SPMEN)); //Perform page erase
boot_page_erase(address);
boot_page_erase(address); // Perform page erase
boot_spm_busy_wait(); // Wait until the memory is erased.
address += SPM_PAGESIZE;
}
}
// write_page(address,(1<<RWWSRE) + (1<<SPMEN)); //Re-enable the RWW section
boot_rww_enable();
sendchar('\r');
}
else if(val=='E') //Exit upgrade
{
// WDTCR = (1<<WDTCE) | (1<<WDE); //Enable Watchdog Timer to give reset
wdt_enable(WDTO_15MS);
wdt_enable(WDTO_15MS); // Enable Watchdog Timer to give reset
sendchar('\r');
}
#ifdef WRITELOCKBITS
#warning "Extension 'WriteLockBits' enabled"
// TODO: does not work
// TODO: does not work reliably
else if(val=='l') // write lockbits
{
if (device == devtype)
@ -321,19 +306,6 @@ int main(void)
}
#endif
/*
else if(val== 'm') // write page
{
if (device == devtype)
{
write_page(address,(1<<PGERS) + (1<<SPMEN)); //Perform page erase
write_page((address),0x05);
write_page(address,(1<<RWWSRE) + (1<<SPMEN)); //Re-enable the RWW section
}
sendchar('\r');
}
*/
else if(val=='P') // Enter programming mode
{
sendchar('\r');
@ -344,73 +316,31 @@ int main(void)
sendchar('\r');
}
else if (val=='p') // mt: return programmer type
else if (val=='p') // return programmer type
{
sendchar('S'); // always serial programmer
}
/*
else if(val=='R') //Read program memory
{
write_page(0,(1<<RWWSRE) + (1<<SPMEN)); //Re-enable the RWW section
// SPMCSR = (1<<RWWSRE) | (1<<SPMEN);
// __store_program_memory();
// while((SPMCSR & 0x01));
intval=read_program_memory(address,0x00);
sendchar((char)(intval>>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<<EEMWE);
EECR |= (1<<EEWE);
while (EECR & (1<<EEWE))
;
}
sendchar('\r');
}
*/
/*
else if (val == 'd') // read eeprom
{
EEARL = address;
EEARH = (address >> 8);
address++;
EECR |= (1<<EERE);
sendchar(EEDR);
}
*/
#ifdef ENABLEREADFUSELOCK
#warning "Extension 'ReadFuseLock' enabled"
else if(val=='F') // read fuse bits
else if(val=='F') // read "low" fuse bits
{
sendchar((unsigned char) read_program_memory(0x0000,_BV(BLBSET)|_BV(SPMEN))); // 0x09 for (1<<BLBSET)|(1<<SPMEN)
sendchar( read_fuse_lock(0x0000, _BV(BLBSET)|_BV(SPMEN)) );
}
else if(val=='r') // read lock bits
{
sendchar((unsigned char) read_program_memory(0x0001,_BV(BLBSET)|_BV(SPMEN)));
sendchar( read_fuse_lock(0x0001, _BV(BLBSET)|_BV(SPMEN)) );
}
else if(val=='N') // read high fuse bits
// TODO: does not work
{
sendchar((unsigned char) read_program_memory(0x0003,_BV(BLBSET)|_BV(SPMEN)));
sendchar( read_fuse_lock(0x0003,_BV(BLBSET)|_BV(SPMEN)) );
}
else if(val=='Q') // read extended fuse bits
{
sendchar('?'); // TODO see ATmega128 datasheet
sendchar( read_fuse_lock(0x0002,_BV(BLBSET)|_BV(SPMEN)) );
}
#endif
// end of ENABLEREADFUSELOCK section
@ -427,7 +357,7 @@ int main(void)
sendchar('\r');
}
else if (val=='T') // set device/programmer type in bootloader (?)
else if (val=='T') // set device
{
device = recchar();
sendchar('\r');
@ -451,7 +381,7 @@ int main(void)
sendchar(sig_byte3);
}
else if(val!=0x1b) // if not esc
else if(val != 0x1b) /* ESC */
{
sendchar('?');
}
@ -463,8 +393,8 @@ int main(void)
unsigned char BufferLoad(unsigned int size, unsigned char mem)
{
unsigned int data, tempaddress, cnt;
unsigned char sreg;
unsigned int data, cnt;
uint32_t tempaddress;
for (cnt=0; cnt<UART_RX_BUFFER_SIZE; cnt++) {
if (cnt<size) gBuffer[cnt]=recchar();
@ -478,23 +408,15 @@ unsigned char BufferLoad(unsigned int size, unsigned char mem)
if (device == devtype)
{
// Disable interrupts.
sreg = SREG;
cli();
if (mem == 'F') // Flash
{
do {
// data = recchar();
// data |= (recchar() << 8);
// fill_temp_buffer(data,(address));
data=gBuffer[cnt++];
data|=(gBuffer[cnt++]<<8);
boot_page_fill(address,data);
//call asm routine.
address=address+2; // Select next word in memory
size -= 2; // Reduce number of bytes to write by two
} while(size); // Loop until all bytes written
/* commented out since not compatible with mega8 -
@ -502,10 +424,8 @@ unsigned char BufferLoad(unsigned int size, unsigned char mem)
tempaddress &= 0xFF80; // Ensure the address points to the first byte in the page
*/
//write_page((tempaddress),0x05); // Program page contents
boot_page_write(tempaddress);
boot_spm_busy_wait();
// write_page(tempaddress,(1<<RWWSRE) + (1<<SPMEN));
boot_rww_enable(); //Re-enable the RWW section
/* commented out since not compatible with mega8
@ -515,7 +435,6 @@ unsigned char BufferLoad(unsigned int size, unsigned char mem)
address += SPM_PAGESIZE;
}
*/
} // End FLASH
if (mem == 'E') // Start EEPROM
@ -525,7 +444,6 @@ unsigned char BufferLoad(unsigned int size, unsigned char mem)
EEARL = address; // Setup EEPROM address
EEARH = (address >> 8);
address++; // Select next byte
// EEDR = recchar(); // Load data to write
EEDR=gBuffer[cnt++];
EECR |= (1<<EEMWE); // Write data into EEPROM
@ -537,9 +455,6 @@ unsigned char BufferLoad(unsigned int size, unsigned char mem)
}
// Re-enable interrupts (if they were ever enabled).
SREG = sreg;
return '\r'; // Report programming OK
}
@ -551,14 +466,6 @@ void BlockRead(unsigned int size, unsigned char mem)
{
unsigned int data;
// Disable interrupts if needed
/*
unsigned char sreg;
sreg = SREG;
cli();
*/
my_eeprom_busy_wait();
if (mem == 'E') // Read EEPROM
@ -576,14 +483,15 @@ void BlockRead(unsigned int size, unsigned char mem)
else // Read Flash
{
do {
data = read_program_memory(address,0x00);
sendchar((char)data); //send LSB
sendchar((char)(data >> 8)); //send MSB
#if defined(RAMPZ)
data = pgm_read_word_far(address);
#else
data = pgm_read_word_near((uint16_t)address);
#endif
sendchar((unsigned char)data); //send LSB
sendchar((unsigned char)(data >> 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
}
// Re-enable interrupts (if they were ever enabled).
/*SREG=sreg;*/
}

241
makefile
View File

@ -1,4 +1,6 @@
# WinAVR makefile written by Eric B. Weddington, Jörg Wunsch, et al.
# Hey Emacs, this is a -*- makefile -*-
#
# WinAVR Sample makefile written by Eric B. Weddington, Jörg Wunsch, et al.
# Released to the Public Domain
# Please read the make user manual!
#
@ -32,7 +34,9 @@
# MCU name
## MCU = atmega16
MCU = atmega8
## MCU = atmega8
MCU = atmega32
## MCU = atmega128
################## BOOTLOADER ######################
# mt: Boot loader support. So far not done with a separate section
@ -43,8 +47,15 @@ MCU = atmega8
# 0x1C00*2=0x3800 for ATmega16 1024 words Boot Size
## MT_BOOTLOADER_ADDRESS = 3800
# 0x0C00*2=0x1800 for ATmega8 1024 words Boot Size
MT_BOOTLOADER_ADDRESS = 1800
## MT_BOOTLOADER_ADDRESS = 1800
# 0x3C00*2=0x7800 for ATmega32 1024 words Boot Size
MT_BOOTLOADER_ADDRESS = 7800
# 0xFC00*2=0x1F800 for ATmega128 1024 words Boot Size
##MT_BOOTLOADER_ADDRESS = 1F800
# Output format. (can be srec, ihex, binary)
@ -53,22 +64,10 @@ 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
SRC = $(TARGET).c uart.c lowlevel.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 += uart.c lowlevel.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
@ -80,35 +79,55 @@ SRC += uart.c lowlevel.c
ASRC =
# Optimization level, can be [0, 1, 2, 3, s].
# 0 = turn off optimization. s = optimize for size.
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT = s
# Debugging format.
# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
DEBUG = stabs
# 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)
# Compiler flag to set the C Standard level.
# c89 - "ANSI" C
# gnu89 - c89 plus GCC extensions
# c99 - ISO C99 standard (not yet fully implemented)
# gnu99 - c99 plus GCC extensions
CSTANDARD = -std=gnu99
# Place -D or -U options here
CDEFS =
# Place -I options here
CINCS =
# Compiler flags.
# -g*: generate debugging information
# -O*: optimization level
# -f...: tuning, see gcc manual and avr-libc documentation
# -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))
# -adhlns...: create assembler listing
CFLAGS = -g$(DEBUG)
CFLAGS += $(CDEFS) $(CINCS)
CFLAGS += -O$(OPT)
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
CFLAGS += -Wall -Wstrict-prototypes
CFLAGS += -Wa,-adhlns=$(<:.c=.lst)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
CFLAGS += $(CSTANDARD)
# 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.
# Assembler flags.
# -Wa,...: tell GCC to pass this to the assembler.
# -ahlms: create listing
# -gstabs: have the assembler create line number information; note that
@ -119,28 +138,53 @@ ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
# Optional linker flags.
#Additional libraries.
# Minimalistic printf version
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
# Floating point printf version (requires MATH_LIB = -lm below)
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
PRINTF_LIB =
# Minimalistic scanf version
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
SCANF_LIB =
MATH_LIB = -lm
# External memory options
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# used for variables (.data/.bss) and heap (malloc()).
#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# only used for heap (malloc()).
#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff
EXTMEMOPTS =
# 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
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
################## BOOTLOADER ######################
# MT_BOOTLOADER_ADDRESS (=Start of Boot Loader section
# in bytes - not words) is defined above.
LDFLAGS += -Wl,--section-start=.text=$(MT_BOOTLOADER_ADDRESS)
# Programming support using avrdude. Settings and variables.
# Programming hardware: alf avr910 avrisp bascom bsd
@ -149,31 +193,33 @@ LDFLAGS += -Wl,--section-start=.text=$(MT_BOOTLOADER_ADDRESS)
# Type: avrdude -c ?
# to get a full listing.
#
AVRDUDE_PROGRAMMER = stk500
AVRDUDE_PROGRAMMER = stk500v2
# com1 = serial port. Use lpt1 to connect to parallel port.
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
#AVRDUDE_ERASE_COUNTER = -y
# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
#AVRDUDE_FLAGS += -V
#AVRDUDE_NO_VERIFY = -V
# Increase verbosity level. Please use this when submitting bug
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
# to submit bug reports.
#AVRDUDE_FLAGS += -v -v
#AVRDUDE_VERBOSE = -v -v
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
@ -189,24 +235,16 @@ 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.
NM = avr-nm
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
@ -236,16 +274,31 @@ OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
# Define all listing files.
LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
# Compiler flags to generate dependency files.
### GENDEPFLAGS = -Wp,-M,-MP,-MT,$(*F).o,-MF,.dep/$(@F).d
GENDEPFLAGS = -MD -MP -MF .dep/$(@F).d
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
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
all: begin gccversion sizebefore build sizeafter finished end
build: elf hex eep lss sym
elf: $(TARGET).elf
hex: $(TARGET).hex
eep: $(TARGET).eep
lss: $(TARGET).lss
sym: $(TARGET).sym
# Eye candy.
@ -264,6 +317,8 @@ end:
# Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) -x -A $(TARGET).elf
sizebefore:
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi
@ -278,14 +333,19 @@ gccversion :
# Program the device.
program: $(TARGET).hex $(TARGET).eep
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
# Convert ELF to COFF for use in debugging / simulating in
# AVR Studio or VMLAB.
# 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
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000
coff: $(TARGET).elf
@ -301,14 +361,6 @@ extcoff: $(TARGET).elf
# 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
@ -331,7 +383,7 @@ program: $(TARGET).hex $(TARGET).eep
%.sym: %.elf
@echo
@echo $(MSG_SYMBOL_TABLE) $@
avr-nm -n $< > $@
$(NM) -n $< > $@
@ -364,9 +416,6 @@ program: $(TARGET).hex $(TARGET).eep
# Target: clean project.
clean: begin clean_list finished end
@ -388,28 +437,16 @@ clean_list :
$(REMOVE) $(LST)
$(REMOVE) $(SRC:.c=.s)
$(REMOVE) $(SRC:.c=.d)
$(REMOVE) .dep/*
# 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)
# Include the dependency files.
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter gccversion coff extcoff \
clean clean_list program
.PHONY : all begin finish end sizebefore sizeafter gccversion \
build elf hex eep lss sym coff extcoff \
clean clean_list program

520
myboot.h
View File

@ -1,520 +0,0 @@
/* Copyright (c) 2002, 2003, 2004 Eric B. Weddington
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of the copyright holders nor the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. */
#ifndef _AVR_BOOT_H_
#define _AVR_BOOT_H_ 1
/** \defgroup avr_boot Bootloader Support Utilities
\code
#include <avr/io.h>
#include <avr/boot.h>
\endcode
The macros in this module provide a C language interface to the
bootloader support functionality of certain AVR processors. These
macros are designed to work with all sizes of flash memory.
\note Not all AVR processors provide bootloader support. See your
processor datasheet to see if it provides bootloader support.
\todo From email with Marek: On smaller devices (all except ATmega64/128),
__SPM_REG is in the I/O space, accessible with the shorter "in" and "out"
instructions - since the boot loader has a limited size, this could be an
important optimization.
\par API Usage Example
The following code shows typical usage of the boot API.
\code
#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
void boot_program_page (uint32_t page, uint8_t *buf)
{
uint16_t i;
uint8_t sreg;
// Disable interrupts.
sreg = SREG;
cli();
eeprom_busy_wait ();
boot_page_erase (page);
boot_spm_busy_wait (); // Wait until the memory is erased.
for (i=0; i<SPM_PAGESIZE; i+=2)
{
// Set up little-endian word.
uint16_t w = *buf++;
w += (*buf++) << 8;
boot_page_fill (page + i, w);
}
boot_page_write (page); // Store buffer in flash page.
boot_spm_busy_wait(); // Wait until the memory is written.
// Reenable RWW-section again. We need this if we want to jump back
// to the application after bootloading.
boot_rww_enable ();
// Re-enable interrupts (if they were ever enabled).
SREG = sreg;
}\endcode */
#include <avr/eeprom.h>
#include <avr/io.h>
#include <inttypes.h>
#include <limits.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
/** \ingroup avr_boot
\def BOOTLOADER_SECTION
Used to declare a function or variable to be placed into a
new section called .bootloader. This section and its contents
can then be relocated to any address (such as the bootloader
NRWW area) at link-time. */
#define BOOTLOADER_SECTION __attribute__ ((section (".bootloader")))
/* Create common bit definitions. */
#ifdef ASB
#define __COMMON_ASB ASB
#else
#define __COMMON_ASB RWWSB
#endif
#ifdef ASRE
#define __COMMON_ASRE ASRE
#else
#define __COMMON_ASRE RWWSRE
#endif
/* Define the bit positions of the Boot Lock Bits. */
#define BLB12 5
#define BLB11 4
#define BLB02 3
#define BLB01 2
// mthomas:
#define LB2 1
#define LB1 0
#define LOCK6 6
#define LOCK7 7
/** \ingroup avr_boot
\def boot_spm_interrupt_enable()
Enable the SPM interrupt. */
#define boot_spm_interrupt_enable() (__SPM_REG |= (uint8_t)_BV(SPMIE))
/** \ingroup avr_boot
\def boot_spm_interrupt_disable()
Disable the SPM interrupt. */
#define boot_spm_interrupt_disable() (__SPM_REG &= (uint8_t)~_BV(SPMIE))
/** \ingroup avr_boot
\def boot_is_spm_interrupt()
Check if the SPM interrupt is enabled. */
#define boot_is_spm_interrupt() (__SPM_REG & (uint8_t)_BV(SPMIE))
/** \ingroup avr_boot
\def boot_rww_busy()
Check if the RWW section is busy. */
#define boot_rww_busy() (__SPM_REG & (uint8_t)_BV(__COMMON_ASB))
/** \ingroup avr_boot
\def boot_spm_busy()
Check if the SPM instruction is busy. */
#define boot_spm_busy() (__SPM_REG & (uint8_t)_BV(SPMEN))
/** \ingroup avr_boot
\def boot_spm_busy_wait()
Wait while the SPM instruction is busy. */
#define boot_spm_busy_wait() do{}while(boot_spm_busy())
#define __BOOT_PAGE_ERASE (_BV(SPMEN) | _BV(PGERS))
#define __BOOT_PAGE_WRITE (_BV(SPMEN) | _BV(PGWRT))
#define __BOOT_PAGE_FILL _BV(SPMEN)
#define __BOOT_RWW_ENABLE (_BV(SPMEN) | _BV(__COMMON_ASRE))
#define __BOOT_LOCK_BITS_SET (_BV(SPMEN) | _BV(BLBSET))
// mthomas - should be inverted
// #define __BOOT_LOCK_BITS_MASK (_BV(BLB01) | _BV(BLB02) | _BV(BLB11) | _BV(BLB12))
#define __BOOT_LOCK_BITS_MASK (_BV(LB1) | _BV(LB2) | _BV(LOCK6) | _BV(LOCK7))
#define __boot_page_fill_normal(address, data) \
({ \
__asm__ __volatile__ \
( \
"movw r0, %3\n\t" \
"movw r30, %2\n\t" \
"sts %0, %1\n\t" \
"spm\n\t" \
"clr r1\n\t" \
: "=m" (__SPM_REG) \
: "r" ((uint8_t)__BOOT_PAGE_FILL), \
"r" ((uint16_t)address), \
"r" ((uint16_t)data) \
: "r0", "r30", "r31" \
); \
})
#define __boot_page_fill_alternate(address, data)\
({ \
__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" ((uint8_t)__BOOT_PAGE_FILL), \
"r" ((uint16_t)address), \
"r" ((uint16_t)data) \
: "r0", "r30", "r31" \
); \
})
#define __boot_page_fill_extended(address, data) \
({ \
__asm__ __volatile__ \
( \
"movw r0, %4\n\t" \
"movw r30, %A3\n\t" \
"sts %1, %C3\n\t" \
"sts %0, %2\n\t" \
"spm\n\t" \
"clr r1\n\t" \
: "=m" (__SPM_REG), \
"=m" (RAMPZ) \
: "r" ((uint8_t)__BOOT_PAGE_FILL), \
"r" ((uint32_t)address), \
"r" ((uint16_t)data) \
: "r0", "r30", "r31" \
); \
})
#define __boot_page_erase_normal(address) \
({ \
__asm__ __volatile__ \
( \
"movw r30, %2\n\t" \
"sts %0, %1\n\t" \
"spm\n\t" \
: "=m" (__SPM_REG) \
: "r" ((uint8_t)__BOOT_PAGE_ERASE), \
"r" ((uint16_t)address) \
: "r30", "r31" \
); \
})
#define __boot_page_erase_alternate(address) \
({ \
__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" ((uint8_t)__BOOT_PAGE_ERASE), \
"r" ((uint16_t)address) \
: "r30", "r31" \
); \
})
#define __boot_page_erase_extended(address) \
({ \
__asm__ __volatile__ \
( \
"movw r30, %A3\n\t" \
"sts %1, %C3\n\t" \
"sts %0, %2\n\t" \
"spm\n\t" \
: "=m" (__SPM_REG), \
"=m" (RAMPZ) \
: "r" ((uint8_t)__BOOT_PAGE_ERASE), \
"r" ((uint32_t)address) \
: "r30", "r31" \
); \
})
#define __boot_page_write_normal(address) \
({ \
__asm__ __volatile__ \
( \
"movw r30, %2\n\t" \
"sts %0, %1\n\t" \
"spm\n\t" \
: "=m" (__SPM_REG) \
: "r" ((uint8_t)__BOOT_PAGE_WRITE), \
"r" ((uint16_t)address) \
: "r30", "r31" \
); \
})
#define __boot_page_write_alternate(address) \
({ \
__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" ((uint8_t)__BOOT_PAGE_WRITE), \
"r" ((uint16_t)address) \
: "r30", "r31" \
); \
})
#define __boot_page_write_extended(address) \
({ \
__asm__ __volatile__ \
( \
"movw r30, %A3\n\t" \
"sts %1, %C3\n\t" \
"sts %0, %2\n\t" \
"spm\n\t" \
: "=m" (__SPM_REG), \
"=m" (RAMPZ) \
: "r" ((uint8_t)__BOOT_PAGE_WRITE), \
"r" ((uint32_t)address) \
: "r30", "r31" \
); \
})
#define __boot_rww_enable() \
({ \
__asm__ __volatile__ \
( \
"sts %0, %1\n\t" \
"spm\n\t" \
: "=m" (__SPM_REG) \
: "r" ((uint8_t)__BOOT_RWW_ENABLE) \
); \
})
#define __boot_rww_enable_alternate() \
({ \
__asm__ __volatile__ \
( \
"sts %0, %1\n\t" \
"spm\n\t" \
".word 0xffff\n\t" \
"nop\n\t" \
: "=m" (__SPM_REG) \
: "r" ((uint8_t)__BOOT_RWW_ENABLE) \
); \
})
#define __boot_lock_bits_set(lock_bits) \
({ \
uint8_t value = (uint8_t)(lock_bits | __BOOT_LOCK_BITS_MASK); \
__asm__ __volatile__ \
( \
"ldi r30, 1\n\t" \
"ldi r31, 0\n\t" \
"mov r0, %2\n\t" \
"sts %0, %1\n\t" \
"spm\n\t" \
: "=m" (__SPM_REG) \
: "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
"r" (value) \
: "r0", "r30", "r31" \
); \
})
#define __boot_lock_bits_set_alternate(lock_bits) \
({ \
uint8_t value = (uint8_t)(lock_bits | __BOOT_LOCK_BITS_MASK); \
__asm__ __volatile__ \
( \
"ldi r30, 1\n\t" \
"ldi r31, 0\n\t" \
"mov r0, %2\n\t" \
"sts %0, %1\n\t" \
"spm\n\t" \
".word 0xffff\n\t" \
"nop\n\t" \
: "=m" (__SPM_REG) \
: "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
"r" (value) \
: "r0", "r30", "r31" \
); \
})
/** \ingroup avr_boot
\def boot_page_fill(address, data)
Fill the bootloader temporary page buffer for flash
address with data word.
\note The address is a byte address. The data is a word. The AVR
writes data to the buffer a word at a time, but addresses the buffer
per byte! So, increment your address by 2 between calls, and send 2
data bytes in a word format! The LSB of the data is written to the lower
address; the MSB of the data is written to the higher address.*/
/** \ingroup avr_boot
\def boot_page_erase(address)
Erase the flash page that contains address.
\note address is a byte address in flash, not a word address. */
/** \ingroup avr_boot
\def boot_page_write(address)
Write the bootloader temporary page buffer
to flash page that contains address.
\note address is a byte address in flash, not a word address. */
/** \ingroup avr_boot
\def boot_rww_enable()
Enable the Read-While-Write memory section. */
/** \ingroup avr_boot
\def boot_lock_bits_set(lock_bits)
Set the bootloader lock bits. */
/* Normal versions of the macros use 16-bit addresses.
Extended versions of the macros use 32-bit addresses.
Alternate versions of the macros use 16-bit addresses and require special
instruction sequences after LPM.
FLASHEND is defined in the ioXXXX.h file.
USHRT_MAX is defined in <limits.h>. */
#if defined(__AVR_ATmega161__) || defined(__AVR_ATmega163__) \
|| defined(__AVR_ATmega323__)
/* Alternate: ATmega161/163/323 and 16 bit address */
#define boot_page_fill(address, data) __boot_page_fill_alternate(address, data)
#define boot_page_erase(address) __boot_page_erase_alternate(address)
#define boot_page_write(address) __boot_page_write_alternate(address)
#define boot_rww_enable() __boot_rww_enable_alternate()
#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_alternate(lock_bits)
#elif (FLASHEND > USHRT_MAX) && !defined(__USING_MINT8)
/* Extended: >16 bit address */
#define boot_page_fill(address, data) __boot_page_fill_extended(address, data)
#define boot_page_erase(address) __boot_page_erase_extended(address)
#define boot_page_write(address) __boot_page_write_extended(address)
#define boot_rww_enable() __boot_rww_enable()
#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set(lock_bits)
#else
/* Normal: 16 bit address */
#define boot_page_fill(address, data) __boot_page_fill_normal(address, data)
#define boot_page_erase(address) __boot_page_erase_normal(address)
#define boot_page_write(address) __boot_page_write_normal(address)
#define boot_rww_enable() __boot_rww_enable()
#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set(lock_bits)
#endif
#define __boot_eeprom_spm_safe(func, address, data) \
do { \
boot_spm_busy_wait(); \
eeprom_busy_wait(); \
func (address, data); \
} while (0)
/** \ingroup avr_boot
Same as boot_page_fill() except it waits for eeprom and spm operations to
complete before filling the page. */
#define boot_page_fill_safe(address, data) \
__boot_eeprom_spm_safe (boot_page_fill, address, data)
/** \ingroup avr_boot
Same as boot_page_erase() except it waits for eeprom and spm operations to
complete before erasing the page. */
#define boot_page_erase_safe(address, data) \
__boot_eeprom_spm_safe (boot_page_erase, address, data)
/** \ingroup avr_boot
Same as boot_page_write() except it waits for eeprom and spm operations to
complete before writing the page. */
#define boot_page_write_safe(address, data) \
__boot_eeprom_spm_safe (boot_page_wrte, address, data)
/** \ingroup avr_boot
Same as boot_rww_enable() except waits for eeprom and spm operations to
complete before enabling the RWW mameory. */
#define boot_rww_enable_safe(address, data) \
__boot_eeprom_spm_safe (boot_rww_enable, address, data)
/** \ingroup avr_boot
Same as boot_lock_bits_set() except waits for eeprom and spm operations to
complete before setting the lock bits. */
#define boot_lock_bits_set_safe(address, data) \
__boot_eeprom_spm_safe (boot_lock_bits_set, address, data)
#endif /* _AVR_BOOT_H_ */

View File

@ -8,13 +8,17 @@
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 for flash and is fast.
http://www.siwawi.arubi.uni-kl.de/avr_projects
======================================================
23. Feb. 2005 - Version 0.7
* (Version 0.6 has never been available on the web-page)
* ATmega128 support
* code cleanup
* Tested with ATmega8, ATmega32 and ATmega128
7. Apr. 2004 - Version 0.5
* added different startup-methods