Простейший пример, для ATMega128. JTAG выключаю, ибо не нужен. Прерывания НЕ используются, флаг I сброшен.
Пишет по команде в первую страницу flash-памяти данные принимаемые с USART0... думаю, разберетесь.. остальное все (запуск программы затем основной и т.д.) делается просто, сюда писать не стал (и так пост здоровенный).
Дополнения к стандартному Makefile:
Код
# Bootloader start address (ATMega 128, 1024)
BOOTLOADER_ADDRESS = 0x1F800
#---------------- Linker Options ----------------
LDFLAGS += -Wl,--section-start=.text=$(BOOTLOADER_ADDRESS)
main.c:
Код
//UART0 initialize
// desired baud rate: 500000
// actual: baud rate:500000 (0,0%)
// char size: 8 bit
// parity: Disabled
void USART0_Initialize(void) // initialization
{
UCSR0B = 0x00; //disable while setting baud rate
UCSR0A = 0x00;
UCSR0C = (_BV(UCSZ01) | _BV(UCSZ00));
UBRR0L = 0x01; //set baud rate lo
UBRR0H = 0x00; //set baud rate hi
UCSR0B = (_BV(RXEN0) | _BV(TXEN0));
}
BYTE USART0_GetChar(void)
{
while(!(UCSR0A & _BV(RXC0)));
return UDR0;
}
void USART0_PutChar(BYTE data)
{
while(!( UCSR0A & _BV(UDRE0)));
UDR0 = data;
}
void Initialize(void)
{
ACSR |= _BV(ACD); // disable Analog Comparator
MCUCSR |= _BV(JTD); // disable JTAG; need to set JTD twice within a 4 cycles; refer to ATMega128 daatasheet for detais
MCUCSR |= _BV(JTD);
USART0_Initialize();
}
void boot_program_page(uint32_t page, uint8_t *buf)
{
uint16_t i;
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 ();
}
int main(void)
{
BYTE data, mode = 0;
WORD idx = 0;
uint8_t data_buf[SPM_PAGESIZE];
Initialize();
while(TRUE)
{
data = USART0_GetChar();
switch(data)
{
case 'S':
USART0_PutChar('D');
USART0_PutChar('a');
USART0_PutChar('t');
USART0_PutChar('a');
USART0_PutChar('>');
USART0_PutChar(' ');
idx = 0;
mode = 1;
break;
case 'W':
USART0_PutChar(' ');
USART0_PutChar('W');
USART0_PutChar('a');
USART0_PutChar('i');
USART0_PutChar('t');
USART0_PutChar('.');
USART0_PutChar('.');
USART0_PutChar('.');
mode = 0;
boot_program_page(0, data_buf);
USART0_PutChar('O');
USART0_PutChar('K');
USART0_PutChar('!');
USART0_PutChar(' ');
break;
default:
if(mode)
{
USART0_PutChar(data);
data_buf[idx++] = data;
if(idx >= SPM_PAGESIZE) idx = 0;
}
break;
}
}
return 0;
}