master_pablo -> cosik pięknego ;) - musiałem aż włączyć porównywanie plików żeby zobaczyć co żeś zmajstrował iż ubyło parę bajtów kodu .... widzę że pozbyłeś się sprawdzania lierki 'q' i kilka innych drobiazgów - jak np dla wersji bootloadera sama jedynka bez apostrofów i już dwa bajty mniej. jedno tylko sobie poprawiłem - bo jak dla mnie to nazwa procka MUSI przylatywać do PC'ta .... a tu przyleciał napis MCU - ale to dlatego, że w makefile zabrakło linijki: COMDEFS += -DMCU=$(MCU) , którą sobie dodałem. Po prostu wyrzucam, co niepotrzebne :). Poprawiona wersja w zalaczniku. ok ale skoro już sam wspomniałeś o procku ATmega128 (to że ma najmniejszy BLS = 1024 to już pestka - tu na bajtach już nie zależy ;) - ale ..... swego czasu któryś z kolegów pisał tu na forum, że dla ATmega128 ten bootloader nie będzie działał dla całej pamięci - a teraz??? teraz z tymi biblitekami z GCC to chyba będzie co ? ;) Jestem przekonany, ze tak. Adres strony jest 32-bitowy, te biblioteki sa uniwersalne, nic wiecej nie potrzeba.
W wykorzystywanym mikrokontrolerze nale¿y zaprogramowaæ (wartoæ 0) bit BOOTRST i ustawiæ bity BOOTSZ tak, by sekcja bootloadera mia³a co najmniej 256 s³ów.
Adres s³owa startowego bootloadera podany przy opisie fusebitów nale¿y pomno¿yæ przez dwa, by uzyskaæ adres bajtu startowego, który nale¿y przypisaæ do zmiennej BLS_START w makefile. Nale¿y równie¿ zmieniæ nazwê (MCU) i czêstotliwoæ pracy (F_CPU [Hz]) mikrokontrolera, a w razie potrzeby szybkoæ portu szeregowego (BAUD_RATE [bps]) i czas oczekiwania przed uruchomieniem za³adowanego programu (BOOT_WAIT [s]).
////////////////////////////////////////////////////////////////////////////////
/* Bootloader
* Autor: Miros³aw Karda (2009-06-16)
* Modyfikacje: Pawe³ Szramowski (2009-06-30)
* Wersja: 2009-07-01 22:00 */
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/* Do³¹czenie bibliotek */
////////////////////////////////////////////////////////////////////////////////
/* biblioteki avr-libc */
#include & lt; stdint.h & gt;
#include & lt; avr/boot.h & gt;
#include & lt; avr/io.h & gt;
#include & lt; avr/pgmspace.h & gt;
#include & lt; avr/wdt.h & gt;
#include & lt; util/delay.h & gt;
#include & lt; util/setbaud.h & gt;
////////////////////////////////////////////////////////////////////////////////
/* Definicje sta³ych programowych i makr */
////////////////////////////////////////////////////////////////////////////////
/* wersja bootloadera */
#define BOOTLOADER_VERSION 1
/* ustawienia UART */
#define UART_DATA_BITS 8
#define UART_PARITY 'n'
#define UART_STOP_BITS 1
/* czas przesy³ania jednego znaku przez UART [us] */
#if UART_PARITY == 'n'
#define UART_BYTE_TIME \
( 1000000UL / ( BAUD / ( 1 + UART_DATA_BITS + UART_STOP_BITS ) ) )
#elif ( UART_PARITY == 'e' ) || ( UART_PARITY == 'o' )
#define UART_BYTE_TIME \
( 1000000UL / ( BAUD / ( 1 + UART_DATA_BITS + 1 + UART_STOP_BITS ) ) )
#endif
/* podstawienie nazwa rejestrów UART */
#ifndef UCSRA
#define UCSRA UCSR0A
#endif
#ifndef UCSRB
#define UCSRB UCSR0B
#endif
#ifndef UCSRC
#define UCSRC UCSR0C
#endif
#ifndef UBRRL
#define UBRRL UBRR0L
#endif
#ifndef UBRRH
#define UBRRH UBRR0H
#endif
#ifndef UDR
#define UDR UDR0
#endif
/* podstawienie nazw bitów w rejestrze UCSRA */
#ifndef RXC
#define RXC RXC0
#endif
#ifndef TXC
#define TXC TXC0
#endif
#ifndef UDRE
#define UDRE UDRE0
#endif
#ifndef FE
#define FE FE0
#endif
#ifndef DOR
#define DOR DOR0
#endif
#ifndef UPE
#define UPE UPE0
#endif
#ifndef U2X
#define U2X U2X0
#endif
#ifndef MPCM
#define MPCM MPCM0
#endif
/* podstawienie nazw bitów w rejestrze UCSRB */
#ifndef RXCIE
#define RXCIE RXCIE0
#endif
#ifndef TXCIE
#define TXCIE TXCIE0
#endif
#ifndef UDRIE
#define UDRIE UDRIE0
#endif
#ifndef RXEN
#define RXEN RXEN0
#endif
#ifndef TXEN
#define TXEN TXEN0
#endif
#ifndef UCSZ2
#define UCSZ2 UCSZ02
#endif
#ifndef RXB8
#define RXB8 RXB80
#endif
#ifndef TXB8
#define TXB8 TXB80
#endif
/* podstawienie nazw bitów w rejestrze UCSRC */
#ifndef UMSEL
#ifdef UMSEL0
#define UMSEL UMSEL0
#else
#define UMSEL UMSEL00
#define UMSEL0 UMSEL00
#define UMSEL1 UMSEL01
#endif
#endif
#ifndef UPM1
#define UPM1 UPM01
#endif
#ifndef UPM0
#define UPM0 UPM00
#endif
#ifndef USBS
#define USBS USBS0
#endif
#ifndef UCSZ1
#define UCSZ1 UCSZ01
#endif
#ifndef UCSZ0
#define UCSZ0 UCSZ00
#endif
#ifndef UCPOL
#define UCPOL UCPOL0
#endif
#if UART_DATA_BITS == 5
#define UCSRB_DATA_BITS ( 0 & lt; & lt; UCSZ2 )
#define UCSRC_DATA_BITS ( 0 & lt; & lt; UCSZ1 | 0 & lt; & lt; UCSZ0 )
#elif UART_DATA_BITS == 6
#define UCSRB_DATA_BITS ( 0 & lt; & lt; UCSZ2 )
#define UCSRC_DATA_BITS ( 0 & lt; & lt; UCSZ1 | 1 & lt; & lt; UCSZ0 )
#elif UART_DATA_BITS == 7
#define UCSRB_DATA_BITS ( 0 & lt; & lt; UCSZ2 )
#define UCSRC_DATA_BITS ( 1 & lt; & lt; UCSZ1 | 0 & lt; & lt; UCSZ0 )
#elif UART_DATA_BITS == 8
#define UCSRB_DATA_BITS ( 0 & lt; & lt; UCSZ2 )
#define UCSRC_DATA_BITS ( 1 & lt; & lt; UCSZ1 | 1 & lt; & lt; UCSZ0 )
#elif UART_DATA_BITS == 9
#define UCSRB_DATA_BITS ( 1 & lt; & lt; UCSZ2 )
#define UCSRC_DATA_BITS ( 1 & lt; & lt; UCSZ1 | 1 & lt; & lt; UCSZ0 )
#endif
#if UART_PARITY == 'n'
#define UCSRC_PARITY ( 0 & lt; & lt; UPM1 | 0 & lt; & lt; UPM0 )
#elif UART_PARITY == 'e'
#define UCSRC_PARITY ( 1 & lt; & lt; UPM1 | 0 & lt; & lt; UPM0 )
#elif UART_PARITY == 'o'
#define UCSRC_PARITY ( 1 & lt; & lt; UPM1 | 1 & lt; & lt; UPM0 )
#endif
#if UART_STOP_BITS == 1
#define UCSRC_STOP_BITS ( 0 & lt; & lt; USBS )
#elif UART_STOP_BITS == 2
#define UCSRC_STOP_BITS ( 1 & lt; & lt; USBS )
#endif
/* makro zamieniaj¹ce podany argument na ³añcuch znaków */
#define TOSTRING( x ) STRINGIFY( x )
#define STRINGIFY( x ) #x
////////////////////////////////////////////////////////////////////////////////
/* Deklaracje funkcji statycznych */
////////////////////////////////////////////////////////////////////////////////
static void UART_TX_Byte(
const uint8_t Data );
static void UART_TX_String_P(
const prog_char *String_Ptr );
static uint8_t _UART_RX_Wait(
uint16_t Timeout );
/* Makro przeliczaj¹ce argument w milisekundach na przyjmowan¹ przez funkcjê
* _UART_RX_Wait wielokrotnoæ czasu przesy³ania jednego znaku. */
#define UART_RX_Wait( x ) _UART_RX_Wait( ( x * 1000UL ) / UART_BYTE_TIME )
////////////////////////////////////////////////////////////////////////////////
/* Definicje funkcji */
////////////////////////////////////////////////////////////////////////////////
static void __vectors(
void )
__attribute__ (( section( " .vectors " ), naked, used ));
static void __vectors(
void )
{
/* skok do sekcji .init2 (konieczny ze wzglêdu na umieszczanie sta³ych z
* pamiêci programu pomiêdzy sekcjami .vectors a .init0, a wiêc na samym
* pocz¹tku programu w przypadku wykorzystania opcji -nostartfiles */
asm (
" rjmp __init2 " " \n\t "
: : );
}
static void __init2(
void )
__attribute__ (( section( " .init2 " ), naked, used ));
static void __init2(
void )
{
/* inicjalizacja wskanika stosu, rejestru z zerem i rejestru flag */
asm volatile (
" out __SP_L__, %A0 " " \n\t "
" out __SP_H__, %B0 " " \n\t "
" clr __zero_reg__ " " \n\t "
" out __SREG__, __zero_reg__ " " \n\t "
: : " r " ( ( uint16_t )( RAMEND ) ) );
}
#ifdef WDIFr
static void __init3(
void )
__attribute__ (( section( " .init3 " ), naked, used ));
static void __init3(
void )
{
/* wy³¹czenie watchdoga (w tych mikrokontrolerach, w których watchdog
* ma mo¿liwoæ generowania przerwania pozostaje on te¿ aktywny po
* resecie) */
MCUSR = 0;
_WD_CONTROL_REG = 1 & lt; & lt; _WD_CHANGE_BIT | 1 & lt; & lt; WDE;
_WD_CONTROL_REG = 0;
}
#endif
static void __init9(
void )
__attribute__ (( section( " .init9 " ), naked, used ));
static void __init9(
void )
{
/* skok do funkcji main */
asm (
" rjmp main " " \n\t "
: : );
}
int main(
void )
__attribute__ (( noreturn ));
int main(
void )
{
/* konfiguracja i w³¹czenie interfejsu UART */
UBRRH = UBRRH_VALUE;
UBRRL = UBRRL_VALUE;
#if USE_2X
UCSRA = 1 & lt; & lt; U2X;
#else
UCSRA = 0;
#endif
#ifdef URSEL
UCSRC = 1 & lt; & lt; URSEL | UCSRC_DATA_BITS | UCSRC_PARITY | UCSRC_STOP_BITS;
#else
UCSRC = UCSRC_DATA_BITS | UCSRC_PARITY | UCSRC_STOP_BITS;
#endif
UCSRB = 1 & lt; & lt; RXEN | 1 & lt; & lt; TXEN | UCSRB_DATA_BITS;
/* deklaracja zmiennych */
uint8_t Received_Char;
/* wysy³anie znaku '?' do odebrania znaku 'u' lub up³yniêcia czasu
* oczekiwania */
for ( uint8_t Retries_Left = BOOT_WAIT * 10; Retries_Left & gt; 0;
--Retries_Left )
{
if ( ( Received_Char = UART_RX_Wait( 100 ) ) == 'u' )
break;
UART_TX_Byte( '?' );
}
if ( Received_Char == 'u' )
{
while ( 1 )
{
/* odebranie znaku */
Received_Char = UART_RX_Wait( 1000 );
if ( Received_Char == 'i' )
{
/* jeli odebrano znak 'i', to wys³anie ci¹gu znaków
* identyfikuj¹cych mikrokontroler i bootloader */
UART_TX_String_P( PSTR( " \r\n " " & "
TOSTRING( SPM_PAGESIZE ) " , "
TOSTRING( BLS_START ) " , "
TOSTRING( MCU ) " , "
TOSTRING( XTAL ) " , "
TOSTRING( BOOTLOADER_VERSION )
" * " " \r\n " ) );
}
else if ( Received_Char == 'w' )
{
/* odczekanie do zakoñczenia operacji na pamiêci EEPROM
* i Flash */
eeprom_busy_wait();
boot_spm_busy_wait();
/* kasowanie ca³ej pamiêci programu */
for ( uint32_t Page_Address = 0; Page_Address & lt; BLS_START;
Page_Address += SPM_PAGESIZE )
{
/* skasowanie strony pamiêci */
boot_page_erase( Page_Address );
boot_spm_busy_wait();
}
/* programowanie pamiêci programu */
for ( uint32_t Page_Address = 0; Page_Address & lt; BLS_START;
Page_Address += SPM_PAGESIZE )
{
/* wys³anie znaku '+' */
UART_TX_Byte( '+' );
/* jeli odebrano zero lub up³yn¹³ czas oczekiwania na
* odpowied, to zakoñczenie pracy bootloadera */
if ( !UART_RX_Wait( 500 ) )
break;
/* zape³nienie bufora strony */
for ( uint16_t Byte_Address = 0;
Byte_Address & lt; SPM_PAGESIZE; Byte_Address += 2 )
{
/* przygotowanie instrukcji */
uint16_t Instruction = ( uint16_t )UART_RX_Wait( 500 );
Instruction += UART_RX_Wait( 500 ) & lt; & lt; 8;
/* zapisanie instrukcji do bufora */
boot_page_fill( Byte_Address, Instruction );
}
/* zapisanie strony pamiêci */
boot_page_write( Page_Address );
boot_spm_busy_wait();
}
/* odblokowanie sekcji Read-While-Write */
boot_rww_enable();
/* zakoñczenie pracy bootloadera */
break;
}
else
{
/* jeli odebrano inny znak lub up³yn¹³ czas oczekiwania na
* odpowied, to zakoñczenie pracy bootloadera */
break;
}
}
}
/* wy³¹czenie interfejsu UART (dzieje siê to dopiero po zakoñczeniu
* wysy³ania) i odczekanie do koñca ewentualnej transmisji */
UCSRB = 0;
_delay_us( UART_BYTE_TIME );
/* skok do w³aciwego programu */
#ifdef __AVR_HAVE_JMP_CALL__
asm volatile (
" jmp 0 " " \n\t "
: : );
#else
asm volatile (
" clr r30 " " \n\t "
" clr r31 " " \n\t "
" ijmp " " \n\t "
: : );
#endif
/* nieskoñczona pêtla (konieczna, by kompilator nie wygenerowa³
* niepotrzebnego kodu) */
while ( 1 )
{}
}
static void UART_TX_Byte(
const uint8_t Data )
{
while ( !( UCSRA & 1 & lt; & lt; UDRE ) )
{}
UDR = Data;
}
static void UART_TX_String_P(
const prog_char *String_Ptr )
{
uint8_t Single_Char;
while ( ( Single_Char = pgm_read_byte( String_Ptr++ ) ) )
UART_TX_Byte( Single_Char );
}
static uint8_t _UART_RX_Wait(
uint16_t Timeout )
{
do
{
if ( UCSRA & 1 & lt; & lt; RXC )
return UDR;
_delay_us( UART_BYTE_TIME );
} while ( Timeout-- );
return 0;
}