Version 0.4 (20040406)

This commit is contained in:
Olaf Rempel 2006-05-01 19:12:13 +02:00
parent 744684bb88
commit 85f5e95b07
10 changed files with 946 additions and 320 deletions

View File

@ -0,0 +1,81 @@
:103800000C942A1C0C94451C0C94451C0C94451CCF
:103810000C94451C0C94451C0C94451C0C94451CA4
:103820000C94451C0C94451C0C94451C0C94451C94
:103830000C94451C0C94451C0C94451C0C94451C84
:103840000C94451C0C94451C0C94451C0C94451C74
:103850000C94451C11241FBECFE5D4E0DEBFCDBFC4
:1038600010E0A0E6B0E0E6EEFCE302C005900D92A9
:10387000A036B107D9F710E0A0E6B0E001C01D9274
:10388000A33EB107E1F70C945D1C0C94001C81E48D
:103890000E94401E86E50E94401E82E50E94401E56
:1038A00082E40E94401E8FE40E94401E8FE40E942A
:1038B000401E84E50E94401E0895CFE5D4E0DEBF9F
:1038C000CDBFC0E0D0E001E005BF82E085BF60E091
:1038D0008BE090E00E94361E8FEF8BBBCF9B07C022
:1038E0001BBA81E085BF15BEFE0109950FC00E947D
:1038F000551E8B3141F40E94551E8335E1F70E941D
:10390000471C00E003C08FE30E94401E002331F7F4
:103910000E94551E682F813611F489E5C3C0813499
:10392000A9F40E94551E99279093E1008093E0002E
:10393000182F00270E94551E9927082B192B000FBE
:10394000111F1093E1000093E00052C0823641F451
:1039500089E50E94401E80E00E94401E80E8A2C0CF
:10396000823489F40E94551E9927182F00270E943F
:10397000551E9927082B192B0E94551E682FC80128
:103980000E94551D8FC0873689F40E94551E9927C5
:10399000182F00270E94551E9927082B192B0E94CB
:1039A000551E682FC8010E94F41DB2CF853611F54F
:1039B0008091E2008537C1F41092E1001092E0009E
:1039C00020E030E083E0F90180935700E89507B6E6
:1039D00000FCFDCF20583F4F88E32030380790F39C
:1039E0003093E1002093E00081E180935700E89557
:1039F0008DE058C0853451F488E190E028E00FB69E
:103A0000F894A89581BD0FBE21BDF2CF803581F31A
:103A10008C3471F3803711F483E544C0863421F48B
:103A200069E080E090E005C0823731F469E081E030
:103A300090E00E94691E36C08E3421F469E083E074
:103A400090E0F7CF813569F1843729F485E70E944A
:103A5000401E80E027C08857823018F40E94551E0F
:103A6000C7CF643529F40E94551E8093E200C0CF71
:103A7000633519F40E94471C4BCF663529F480E367
:103A80000E94401E84E30EC0633741F483E00E942D
:103A9000401E84E90E94401E8EE104C06B3109F48F
:103AA00037CF8FE30E94401E33CFDF92EF92FF9219
:103AB0000F931F93CF93DF938C01D62E60E070E0BD
:103AC000EB01C05ADF4F7B010894E11CF11C601729
:103AD000710718F40E94551E01C08FEF8883B7014B
:103AE0006038710568F360E070E0C091E000D0914B
:103AF000E1008CB399279C012270307081FDF9CFD1
:103B00008091E200853709F066C0FFB6F89486E43C
:103B1000D81609F03EC04091E0005091E100DB0171
:103B2000A05ABF4F8D91282F33278D919927982F19
:103B30008827282B392B6E5F7F4F81E00901FA011E
:103B400080935700E89511244E5F5F4F025010405C
:103B500049F75093E1004093E000C07885E0FE0112
:103B600080935700E89507B600FCFDCF81E1809374
:103B70005700E8958091E0009091E1009C01207849
:103B80008217930731F020583F4F3093E100209384
:103B9000E00085E4D816D9F4FB01E05AFF4F80918C
:103BA000E0008EBB8091E0009091E100292F332747
:103BB0002FBB01969093E1008093E00081918DBB33
:103BC000E29AE19AE199FECF0150104041F7FFBE21
:103BD0008DE090E001C0C901DF91CF911F910F915D
:103BE000FF90EF90DF900895FF920F931F93CF9374
:103BF000DF93EC01FFB6F894E199FECF6534B1F4A0
:103C00008091E0008EBB8091E0009091E100292F2F
:103C100033272FBB01969093E1008093E000E09A58
:103C20008DB30E94401E219759F719C060E0809122
:103C3000E0009091E1000E94691E8C010E94401EEC
:103C4000812F99270E94401E8091E0009091E10011
:103C500002969093E1008093E000229739F7FFBE2F
:103C6000DF91CF911F910F91FF9008959C01832FB9
:103C7000992780BD29B988E18AB986E880BD089571
:103C800020E030E08CB90FB607FE0BC05E990BC088
:103C90002F5F3F4F5E9907C087E220313807C4F39A
:103CA00002C05E9BFECF5E9A089580E090E00FB662
:103CB00007FE0AC05F990AC001965F9907C027E214
:103CC00080319207CCF302C05F9BFECF8CB1992765
:103CD0000895FC0160FD60935700C895802DE39521
:063CE000C895902D089527
:0400000300003800C1
:00000001FF

View File

@ -0,0 +1,77 @@
:103800000C942A1C0C94451C0C94451C0C94451CCF
:103810000C94451C0C94451C0C94451C0C94451CA4
:103820000C94451C0C94451C0C94451C0C94451C94
:103830000C94451C0C94451C0C94451C0C94451C84
:103840000C94451C0C94451C0C94451C0C94451C74
:103850000C94451C11241FBECFE5D4E0DEBFCDBFC4
:1038600010E0A0E6B0E0EAEAFCE302C005900D92A9
:10387000A036B107D9F710E0A0E6B0E001C01D9274
:10388000A33EB107E1F70C945D1C0C94001C81E48D
:103890000E94221E86E50E94221E82E50E94221EB0
:1038A00082E40E94221E8FE40E94221E8FE40E9466
:1038B000221E84E50E94221E0895CFE5D4E0DEBFDB
:1038C000CDBF81E085BF82E085BF60E087E190E009
:1038D0000E94181E0E94371E682F813611F489E558
:1038E000C3C08134A9F40E94371E99279093E10048
:1038F0008093E000182F00270E94371E9927082B7D
:10390000192B000F111F1093E1000093E00052C02B
:10391000823641F489E50E94221E80E00E94221E28
:1039200080E8A2C0823489F40E94371E9927182F9C
:1039300000270E94371E9927082B192B0E94371E3B
:10394000682FC8010E94371D8FC0873689F40E94F6
:10395000371E9927182F00270E94371E9927082BFA
:10396000192B0E94371E682FC8010E94D61DB2CFA6
:10397000853611F58091E2008537C1F41092E1009F
:103980001092E00020E030E083E0F90180935700DE
:10399000E89507B600FCFDCF20583F4F88E3203064
:1039A000380790F33093E1002093E00081E18093A9
:1039B0005700E8958DE058C0853451F488E190E0D7
:1039C00028E00FB6F894A89581BD0FBE21BDF2CFB7
:1039D000803581F38C3471F3803711F483E544C072
:1039E000863421F469E080E090E005C0823731F44C
:1039F00069E081E090E00E944B1E36C08E3421F4D5
:103A000069E083E090E0F7CF813569F1843729F4EC
:103A100085E70E94221E80E027C08857823018F474
:103A20000E94371EC7CF643529F40E94371E809349
:103A3000E200C0CF633519F40E94471C4BCF6635B6
:103A400029F480E30E94221E84E30EC0633741F410
:103A500083E00E94221E84E90E94221E8EE104C09F
:103A60006B3109F437CF8FE30E94221E33CFDF92F0
:103A7000EF92FF920F931F93CF93DF938C01D62E7B
:103A800060E070E0EB01C05ADF4F7B010894E11C5D
:103A9000F11C6017710718F40E94371E01C08FEFE8
:103AA0008883B7016038710568F360E070E0C09109
:103AB000E000D091E1008CB399279C012270307016
:103AC00081FDF9CF8091E200853709F066C0FFB62D
:103AD000F89486E4D81609F03EC04091E000509179
:103AE000E100DB01A05ABF4F8D91282F33278D9124
:103AF0009927982F8827282B392B6E5F7F4F81E0DD
:103B00000901FA0180935700E89511244E5F5F4F39
:103B10000250104049F75093E1004093E000C07814
:103B200085E0FE0180935700E89507B600FCFDCFC5
:103B300081E180935700E8958091E0009091E10049
:103B40009C0120788217930731F020583F4F309323
:103B5000E1002093E00085E4D816D9F4FB01E05A97
:103B6000FF4F8091E0008EBB8091E0009091E100DA
:103B7000292F33272FBB01969093E1008093E0001B
:103B800081918DBBE29AE19AE199FECF01501040FC
:103B900041F7FFBE8DE090E001C0C901DF91CF91F8
:103BA0001F910F91FF90EF90DF900895FF920F9378
:103BB0001F93CF93DF93EC01FFB6F894E199FECF0A
:103BC0006534B1F48091E0008EBB8091E00090916B
:103BD000E100292F33272FBB01969093E1008093BA
:103BE000E000E09A8DB30E94221E219759F719C078
:103BF00060E08091E0009091E1000E944B1E8C01FA
:103C00000E94221E812F99270E94221E8091E0008F
:103C10009091E10002969093E1008093E00022975A
:103C200039F7FFBEDF91CF911F910F91FF9008955B
:103C30009C01832F992780BD29B988E18AB986E83C
:103C400080BD089520E030E08CB90FB607FE0BC0B0
:103C50005E990BC02F5F3F4F5E9907C087E220310E
:103C60003807C4F302C05E9BFECF5E9A089580E0E1
:103C700090E00FB607FE0AC05F990AC001965F99EF
:103C800007C027E280319207CCF302C05F9BFECFD2
:103C90008CB199270895FC0160FD60935700C89589
:0A3CA000802DE395C895902D08953E
:0400000300003800C1
:00000001FF

View File

@ -1,79 +0,0 @@
: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

View File

@ -2,6 +2,11 @@
#ifndef CHIPDEF_H
#define CHIPDEF_H
#include <avr/io.h>
// TODO: make use of RAMEND in the avr-libc io-files and
// avoid a lot of by-device definitions here
#if defined(__AVR_ATmega169__)
#define sig_byte3 0x1E
#define sig_byte2 0x94
@ -9,23 +14,23 @@
#define devtype 0x79 // Mega 169 device code
#define PAGESIZE 128 // 2*64 Words = Size in Bytes
// #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
#define APP_PAGES ((2*8192 / SPM_PAGESIZE)- (2*128 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B256
#define APP_PAGES ((2*8192 / PAGESIZE)- (2*256 / PAGESIZE ))
#define APP_END APP_PAGES * PAGESIZE
#define APP_PAGES ((2*8192 / SPM_PAGESIZE)- (2*256 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B512
#define APP_PAGES ((2*8192 / PAGESIZE)- (2*512 / PAGESIZE ))
#define APP_END APP_PAGES * PAGESIZE
#define APP_PAGES ((2*8192 / SPM_PAGESIZE)- (2*512 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B1024
#define APP_PAGES ((2*8192 / PAGESIZE)- (2*1024 / PAGESIZE ))
#define APP_END APP_PAGES * PAGESIZE
#define APP_PAGES ((2*8192 / SPM_PAGESIZE)- (2*1024 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B2048
#error "_B2048 not suppoted on this device"
@ -39,23 +44,23 @@
#define devtype 0x75 // Mega16 device code
#define PAGESIZE 128 // Size in Bytes
// #define PAGESIZE 128 // Size in Bytes
#ifdef _B128
#define APP_PAGES ((2*8192 / PAGESIZE)- (2*128 / PAGESIZE ))
#define APP_END APP_PAGES * PAGESIZE
#define APP_PAGES ((2*8192 / SPM_PAGESIZE)- (2*128 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B256
#define APP_PAGES ((2*8192 / PAGESIZE)- (2*256 / PAGESIZE ))
#define APP_END APP_PAGES * PAGESIZE
#define APP_PAGES ((2*8192 / SPM_PAGESIZE)- (2*256 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B512
#define APP_PAGES ((2*8192 / PAGESIZE)- (2*512 / PAGESIZE ))
#define APP_END APP_PAGES * PAGESIZE
#define APP_PAGES ((2*8192 / SPM_PAGESIZE)- (2*512 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B1024
#define APP_PAGES ((2*8192 / PAGESIZE)- (2*1024 / PAGESIZE ))
#define APP_END APP_PAGES * PAGESIZE
#define APP_PAGES ((2*8192 / SPM_PAGESIZE)- (2*1024 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B2048
#error "_B2048 not suppoted on this device"
@ -69,23 +74,23 @@
#define devtype 0x77 // Mega8 boot device code
#define PAGESIZE 64 // Size in Bytes
// #define PAGESIZE 64 // Size in Bytes
#ifdef _B128
#define APP_PAGES ((2*4096 / PAGESIZE)- (2*128 / PAGESIZE ))
#define APP_END APP_PAGES * PAGESIZE
#define APP_PAGES ((2*4096 / SPM_PAGESIZE)- (2*128 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B256
#define APP_PAGES ((2*4096 / PAGESIZE)- (2*256 / PAGESIZE ))
#define APP_END APP_PAGES * PAGESIZE
#define APP_PAGES ((2*4096 / SPM_PAGESIZE)- (2*256 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B512
#define APP_PAGES ((2*4096 / PAGESIZE)- (2*512 / PAGESIZE ))
#define APP_END APP_PAGES * PAGESIZE
#define APP_PAGES ((2*4096 / SPM_PAGESIZE)- (2*512 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B1024
#define APP_PAGES ((2*4096 / PAGESIZE)- (2*1024 / PAGESIZE ))
#define APP_END APP_PAGES * PAGESIZE
#define APP_PAGES ((2*4096 / SPM_PAGESIZE)- (2*1024 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B2048
#error "_B2048 not suppoted on this device"
@ -99,27 +104,27 @@
#define devtype 0x73 // Mega32 device code
#define PAGESIZE 128 // Size in Bytes
// #define PAGESIZE 128 // Size in Bytes
#ifdef _B128
#define APP_PAGES ((2*16384 / PAGESIZE)- (2*128 / PAGESIZE ))
#define APP_END APP_PAGES * PAGESIZE
#define APP_PAGES ((2*16384 / SPM_PAGESIZE)- (2*128 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B256
#define APP_PAGES ((2*16384 / PAGESIZE)- (2*256 / PAGESIZE ))
#define APP_END APP_PAGES * PAGESIZE
#define APP_PAGES ((2*16384 / SPM_PAGESIZE)- (2*256 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B512
#define APP_PAGES ((2*16384 / PAGESIZE)- (2*512 / PAGESIZE ))
#define APP_END APP_PAGES * PAGESIZE
#define APP_PAGES ((2*16384 / SPM_PAGESIZE)- (2*512 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B1024
#define APP_PAGES ((2*16384 / PAGESIZE)- (2*1024 / PAGESIZE ))
#define APP_END APP_PAGES * PAGESIZE
#define APP_PAGES ((2*16384 / SPM_PAGESIZE)- (2*1024 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#ifdef _B2048
#define APP_PAGES ((2*16384 / PAGESIZE)- (2*2048 / PAGESIZE ))
#define APP_END APP_PAGES * PAGESIZE
#define APP_PAGES ((2*16384 / SPM_PAGESIZE)- (2*2048 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
#endif
#else

View File

@ -1,132 +1,20 @@
//
// 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.
// from the original ATMEL Butterfly bootloader code
// which are not included in avr-libc's boot.h by the
// time of writing this.
//
// 3/2004 Martin Thomas, Kaiserslautern, Germany
//
// todo: extend functions with espm
#include <avr/io.h>
#include "lowlevel.h"
// 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)
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"

View File

@ -1,9 +1,18 @@
#ifndef LOWLEVEL_H
#define LOWLEVEL_H
void write_page (unsigned int adr, unsigned char function);
#include <avr/io.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
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

245
main.c
View File

@ -1,27 +1,36 @@
/*****************************************************************************
*
* AVRPROG compatible boot-loader
* Version : 0.2 (24. March 2004)
* Version : 0.4 (6. Apr. 2004)
* Compiler : avr-gcc 3.3.1 / avr-libc 1.0
* size : ca. 610 word ( larger than 512 words :-( )
* size : ( 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
* 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.
*
* - 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. A lot of things have been change but the ATMEL
* "skeleton" is still in this code. Make sure to keep the copyright notice
* in derived work to avoid trouble.
*
* - based on boot.h from the avr-libc (c) Eric Weddington
*
* 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.
* 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
@ -29,29 +38,57 @@
* 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.
* options for the newly created section. See the avr-libc FAQ, the avr-
* libc's avr/boot.h documentation and the makefile 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.
* 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)
*
****************************************************************************/
/*
Does not work so far:
- fuse high byte read (or parse in AVRPROG?)
- lock bits set
*/
// programmers-notepad tabsize 4
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/wdt.h>
/* BOOTICE-Mode - to flash the JTAGICE upgrade.ebn file.
No startup-sequence in this mode. Jump directly to the
parser-loop on reset
XTAL in BOOTICEMODE must be 7372800 Hz to be compatible
with the org. JTAGICE-Firmware */
// #define BOOTICEMODE
/* READFUSELOCK is untested, will not work for Mega169 since not
supported by AVRPROG 1.37 */
// #define ENABLEREADFUSELOCK
// UART handling - some definitions from P. Fleury's Library - thanks
#define BAUDRATE 19200
#ifndef BOOTICEMODE
#define XTAL 3686400
#else
#warning "BOOTICE mode - External Crystal/Oszillator must be 7,3728 MHz"
#define XTAL 7372800
#endif
#include "uart.h"
/* enable/disable readout of fuse and lock-bits
(will not work for Mega169 since not supported by AVRPROG 1.37 */
#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)
*/
// #define WRITELOCKBITS
/* Select Boot Size (select one, comment out the others)
select at least _B1024 */
@ -63,15 +100,24 @@
#include "chipdef.h"
#define UART_RX_BUFFER_SIZE PAGESIZE
// 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"
#include "uart.h"
#define UART_RX_BUFFER_SIZE SPM_PAGESIZE
unsigned char gBuffer[UART_RX_BUFFER_SIZE];
#define eeprom_is_ready() bit_is_clear(EECR, EEWE)
#define my_eeprom_busy_wait() do{}while(!eeprom_is_ready())
unsigned char BufferLoad(unsigned int , unsigned char ) ;
void BlockRead(unsigned int , unsigned char ) ;
unsigned int address;
unsigned short address;
unsigned char device;
void send_boot(void)
@ -89,29 +135,33 @@ int main(void)
{
void (*funcptr)( void ) = 0x0000; // Set up function pointer
unsigned int tempi;
unsigned short 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<<IVCE);
MCUCR = (1<<IVCE);
MCUCR = (1<<IVSEL); //move interruptvectors to the Boot sector
/* This is an adoption of the Butterfly Bootloader startup-sequence.
It may look a little strange but separating the login-loop from
the main parser-loop gives a lot a possibilities (timeout, sleep-modes
etc.).
USART_Init(UART_BAUD_SELECT(BAUDRATE,XTAL),UARTSINGLE); // single speed
// USART_Init(UART_BAUD_SELECT(BAUDRATE/2,XTAL),UARTDOUBLE); // double speed
/*
This is an adoption of the Butterfly Bootloader startup-sequence.
It may look a little strange but separating the login-loop from
the main parser-loop gives a lot a possibilities (timeout, sleep-modes
etc.).
*/
#ifndef BOOTICEMODE
PORTA = 0xFF; // Enable pullups on Port A
for(;OK;)
{
if((PINA & (1<<PINA7)))
{
// jump to main app if PIN A0 is not grounded
// jump to main app if PIN A7 is not grounded
PORTA = 0x00; // set to default
MCUCR = (1<<IVCE);
MCUCR = (0<<IVSEL); //move interruptvectors to the Application sector
funcptr(); // Jump to application sector
@ -133,6 +183,9 @@ int main(void)
sendchar('?');
}
}
#else
#warning "BOOTICE mode - no startup-condition"
#endif
for(;;)
{
@ -198,13 +251,16 @@ int main(void)
{
if (device == devtype)
{
for(address=0;address < APP_END;address += PAGESIZE) //Application section = 60 pages
// erase only main section (bootloader protection)
for(address=0;address < APP_END;address += SPM_PAGESIZE) //Application section = 60 pages
{
write_page(address,(1<<PGERS) + (1<<SPMEN)); //Perform page erase
write_page(address,(1<<RWWSRE) + (1<<SPMEN)); //Re-enable the RWW section
//write_page(address,(1<<PGERS) + (1<<SPMEN)); //Perform page erase
boot_page_erase(address);
boot_spm_busy_wait(); // Wait until the memory is erased.
}
}
write_page(address,(1<<RWWSRE) + (1<<SPMEN)); //Re-enable the RWW section
// write_page(address,(1<<RWWSRE) + (1<<SPMEN)); //Re-enable the RWW section
boot_rww_enable();
sendchar('\r');
}
@ -214,16 +270,23 @@ int main(void)
wdt_enable(WDTO_15MS);
sendchar('\r');
}
/*
#ifdef WRITELOCKBITS
#warning "Extension 'WriteLockBits' enabled"
// TODO: does not work
else if(val=='l') // write lockbits
{
if (device == devtype)
{
write_lock_bits(recchar());
// write_lock_bits(recchar());
boot_lock_bits_set(recchar()); // boot.h takes care of mask
boot_spm_busy_wait();
}
sendchar('\r');
}
#endif
/*
else if(val== 'm') // write page
{
if (device == devtype)
@ -246,10 +309,9 @@ int main(void)
sendchar('\r');
}
else if (val=='p') // mt: return programmer type
{
sendchar('S'); // serial programmer
sendchar('S'); // always serial programmer
}
/*
@ -265,7 +327,8 @@ int main(void)
sendchar((char)intval); //send LSB
address=address+2;
}
*/
/*
else if (val == 'D') // write EEPROM
{
if (device == devtype)
@ -281,7 +344,8 @@ int main(void)
}
sendchar('\r');
}
*/
/*
else if (val == 'd') // read eeprom
{
EEARL = address;
@ -293,29 +357,25 @@ int main(void)
*/
#ifdef ENABLEREADFUSELOCK
#warning "Extension 'ReadFuseLock' enabled"
// mt TODO: Read fuse bit seems to work for clock speed, other settings are not
// interpreted correctly. Locks and high fuse do not work at all (in AVRPROG 1.37)
// Reason for this should be the difference between ATmega16 and ATmega169.
// AVRPROG interprets the results as from an ATmega16 while they are from an ATmega169
else if(val=='F') // read fuse bits
{
sendchar(read_program_memory(0x0000,0x09)); // 0x09 for (1<<BLBSET)|(1<<SPMEN)
sendchar((unsigned char) read_program_memory(0x0000,_BV(BLBSET)|_BV(SPMEN))); // 0x09 for (1<<BLBSET)|(1<<SPMEN)
}
else if(val=='r') // read lock bits
{
sendchar(read_program_memory(0x0001,0x09));
sendchar((unsigned char) read_program_memory(0x0001,_BV(BLBSET)|_BV(SPMEN)));
}
else if(val=='N') // read high fuse bits
// TODO: does not work
{
// mt sendchar(read_program_memory(0x0003));
sendchar(read_program_memory(0x0003,0x09));
sendchar((unsigned char) read_program_memory(0x0003,_BV(BLBSET)|_BV(SPMEN)));
}
else if(val=='Q') // read extended fuse bits
{
sendchar(read_program_memory(0x0002,0x09));
sendchar('?'); // TODO see ATmega128 datasheet
}
#endif
// end of ENABLEREADFUSELOCK section
@ -345,8 +405,8 @@ int main(void)
else if (val=='V') // Return Software Version
{
sendchar('0'); // mt: changed from 2;0 to 0;1
sendchar('2');
sendchar('0');
sendchar('4');
}
else if (val=='s') // Return Signature Byte
@ -360,26 +420,42 @@ int main(void)
{
sendchar('?');
}
} // "parser" for-loop
} // end of "parser" for-loop
return 0;
}
unsigned char BufferLoad(unsigned int size, unsigned char mem)
{
int data, tempaddress;
unsigned int data, tempaddress, cnt;
unsigned char sreg;
for (cnt=0; cnt<UART_RX_BUFFER_SIZE; cnt++) {
if (cnt<size) gBuffer[cnt]=recchar();
else gBuffer[cnt]=0xFF;
}
cnt=0;
tempaddress = address; // Store address in page
my_eeprom_busy_wait();
if (device == devtype)
{
if (mem == 'F')
{
// Disable interrupts.
sreg = SREG;
cli();
if (mem == 'F') // Flash
{
do {
data = recchar();
data |= (recchar() << 8);
fill_temp_buffer(data,(address));
// 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
@ -387,14 +463,17 @@ unsigned char BufferLoad(unsigned int size, unsigned char mem)
} while(size); // Loop until all bytes written
tempaddress &= 0xFF80; // Ensure the address points to the first byte in the page
write_page((tempaddress),0x05); // Program page contents
write_page(tempaddress,(1<<RWWSRE) + (1<<SPMEN));
//Re-enable the RWW section
//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
if (address != (address & 0xFF80))
{ // Ensure that the address points to the beginning of the next page
address &= 0xFF80;
address += PAGESIZE;
address += SPM_PAGESIZE;
}
} // End FLASH
@ -403,23 +482,39 @@ unsigned char BufferLoad(unsigned int size, unsigned char mem)
do {
EEARL = address; // Setup EEPROM address
EEARH = (address >> 8);
address++; // Select next byte
EEDR = recchar(); // Load data to write
address++; // Select next byte
// EEDR = recchar(); // Load data to write
EEDR=gBuffer[cnt++];
EECR |= (1<<EEMWE); // Write data into EEPROM
EECR |= (1<<EEWE);
while (EECR & (1<<EEWE)) // Wait for EEPROM write to finish
;
while (EECR & (1<<EEWE)); // Wait for EEPROM write to finish
size--; // Decreas number of bytes to write
} while(size); // Loop until all bytes written
}
return '\r'; // Report programming OK
// Re-enable interrupts (if they were ever enabled).
SREG = sreg;
return '\r'; // Report programming OK
}
return 0; // Report programming failed
}
void BlockRead(unsigned int size, unsigned char mem)
{
unsigned int data;
unsigned char sreg;
// Disable interrupts.
sreg = SREG;
cli();
my_eeprom_busy_wait();
if (mem == 'E') // Read EEPROM
{
@ -442,5 +537,7 @@ void BlockRead(unsigned int size, unsigned char mem)
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;
}

View File

@ -49,8 +49,7 @@ 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
SRC += uart.c lowlevel.c
# You can also wrap lines by appending a backslash to the end of the line:

520
myboot.h Normal file
View File

@ -0,0 +1,520 @@
/* 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

@ -11,10 +11,39 @@
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.
page write for flash and is fast.
======================================================
6. Apr. 2004 - Version 0.4
* Buffered read of chars from UART during programming
since eeprom-write is too slow for unbuffered
operation. So EEPROM-upload does work now.
* Added BOOTICE-mode to flash JTAGICE-compatible
hardware (ATmega16@7,3Mhz) (if you know about BOOTICE,
you may unterstand why this has been added, if not
just keep the option disabled)
* small changes in (my)boot.h (lock-bit-mask) found
out during the development of the STK-500-compatible
bootloader. But setting lock-bits still does not
work with this bootloader.
* read of the low-fuse byte works (high byte still TODO)
* read of the lock-byte works (wirte still TODO)
27. Mar 2004 - Version 0.3
Felt that as much functions from avr-libc's boot.h
as possible should be used without modifications.
Latest CVS-version of boot.h is included.
Only the read-routine is still "self-made" based
on ATMELs assembler-code.
EEPROM write on Mega16 does not work (and did not
work with V0.2 too). May be caused by my old Mega16
chip. Needs testing. Flash read/write and EEPROM
read works. Still only tested with ATmega16.
This version may not work with the ATmega169 any
more.
24. Mar 2004 - Version 0.2
@ -33,7 +62,7 @@ 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
for flash 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.