📄 bootloader.bu.c
字号:
/**************************** IsoJTAG Bootloader* For ATmega16***************************/#include <inttypes.h>#include <avr/io.h>#include <avr/interrupt.h>#include <avr/wdt.h>#include <avr/boot.h>#include <avr/pgmspace.h>
#include "crystal.h"
#include "memory.h"
#define BOOTDDR DDRC#define BOOTPIN PINC#define BOOTPORT PORTC#define BOOTPNUM 6
#define LEDDDR DDRB
#define LEDPORT PORTB
#define LEDBIT 3
#define devtype 0x75 // Mega16 device code
#define APP_PAGES ((2*8192 / SPM_PAGESIZE)- (2*1024 / SPM_PAGESIZE ))
#define APP_END APP_PAGES * SPM_PAGESIZE
// Prototypes
int main(void) __attribute__ ((section (".bloader")));
void send_boot(void) __attribute__ ((section (".bloader")));
void send_usart (unsigned char) __attribute__ ((section (".bloader")));void USART_Init (void) __attribute__ ((section (".bloader")));unsigned char read_usart (void) __attribute__ ((section (".bloader")));
void jump_to_jtag(void) __attribute__ ((section (".bloader")));
extern void isp_start(void) __attribute__ ((section ("text")));
unsigned int baddress;
unsigned int waddress;unsigned char device;
unsigned char vals[200];
unsigned char valscnt = 0;
int main(void){
asm volatile("clr r1"::);
unsigned int temp_int = 0; unsigned char val;
unsigned int patch = 0;
unsigned int patch2 = 0;
unsigned char wait_time_x2 = 0;
cli(); MCUCR = (1<<IVCE); // move interruptvectors to the Boot sector MCUCR = (1<<IVSEL); // device specific ! BOOTDDR &= ~(1<<BOOTPNUM); // set as Input BOOTPORT |= (1<<BOOTPNUM); // Enable pullup
LEDDDR |= (1 << LEDBIT); // set as Output USART_Init(); //TCCR1A = 0; // timer setup #define WAIT_VALUE ((FREQ / 1024) * 5) // *2 seconds
TCCR1B |= _BV(CS10); // .
TCCR1B |= _BV(CS12); // .. /1024
TCNT1 = 0x00; int pulseCount = 0;
while(1) { if (pulseCount == ((FREQ / 1000)+3000))
{
LEDPORT ^= (1 << LEDBIT); // Pulse the LED, show in waiting mode.
pulseCount = 0;
}
pulseCount++;
if ((BOOTPIN & (1<<BOOTPNUM)) == 0) // If in ISP mode don't enter bootloader { LEDPORT |= (1 << LEDBIT); // Turn LED OFF
MCUCR = (1<<IVCE); MCUCR = (0<<IVSEL); //move interruptvectors to the Application sector TCCR1B = 0; // timer off BOOTPORT &= ~(1<<BOOTPNUM); // set to default isp_start(); // Jump to application sector } if(UCSRA & (1<<RXC)) { unsigned char data = UDR;
if (data == 'S') // If the Prog Start command is received start bootloader break; }
if (TCNT1 >= WAIT_VALUE) // If the start command timeout runs out start main program {
if (wait_time_x2 != 1)
{
wait_time_x2 = 1;
}
else
{
LEDPORT |= (1 << LEDBIT); // Turn LED OFF
MCUCR = (1<<IVCE); MCUCR = (0<<IVSEL); //move interruptvectors to the Application sector TCCR1B = 0; // timer off if ((BOOTPIN & (1<<BOOTPNUM)) != 0) { BOOTPORT &= ~(1<<BOOTPNUM); // set to default jump_to_jtag(); // Jump to application sector } else { BOOTPORT &= ~(1<<BOOTPNUM); // set to default isp_start(); // Jump to application sector } }
} }
LEDPORT |= (1 << LEDBIT); // Turn LED OFF TCCR1B = 0; // timer off send_boot(); while(1) {
val=read_usart();
switch (val) { //No Data
case 0:
break;
// Return Programmer Type case 'p': send_usart('S'); break; // Auto inc support case 'a': send_usart('Y'); break; // Return Software Identifier case 'S': send_boot(); break; // Return supported devices case 't': send_usart(0x74); send_usart(0x00); break; // Return Software Version case 'V': send_usart('1'); send_usart('0'); break; // set device case 'T': read_usart(); send_usart('\r'); break; // Set Address case 'A': baddress = (read_usart()<<8)|read_usart(); // get address waddress = baddress * 2; // convert word addr to byte send_usart('\r'); break; // Enter Programming Mode case 'P': send_usart('\r'); break; // Leave Programming mode case 'L': send_usart('\r'); break; // Read Signature case 's': send_usart(0x02); send_usart(0x94);
send_usart(0x1E); break; // Read Data case 'd' :
EEARL = baddress; // Setup EEPROM address. EEARH = (baddress >> 8); while(EECR & (1<<EEWE))
; EECR |= (1<<EERE); send_usart(EEDR); break; // Read Program memory case 'R' : // Send high byte, then low byte of flash word.
#ifdef PATCH
if (patch != 0)
{
if (waddress == patch)
{
send_usart(0xBD);
send_usart(0x10);
waddress +=2;
break;
}
if (waddress == patch2)
{
send_usart(0xB9);
send_usart(0x09);
waddress +=2;
break;
}
}
#endif
boot_spm_busy_wait(); boot_rww_enable(); send_usart( pgm_read_byte_near( waddress+1 ) ); send_usart( pgm_read_byte_near( waddress+0 ) ); waddress +=2; // Auto-advance to next Flash word. break; // Write Code low case 'c' : LEDPORT &= ~(1 << LEDBIT);
temp_int=read_usart(); // Get low byte for later boot_page_fill.
send_usart('\r'); // Send OK back. break; // Write Code high case 'C' :
temp_int |= (read_usart()<<8); // Get and insert high byte.
#ifdef PATCH
if (temp_int == 0xBD10)
{
temp_int = 0x940E;
patch = waddress;
}
if (temp_int == 0xB909)
{
temp_int = UBRRSTART;
patch2 = waddress;
}
#endif
LEDPORT |= (1 << LEDBIT);
boot_spm_busy_wait(); boot_page_fill( waddress, temp_int );
waddress +=2; // Auto-advance to next Flash word. send_usart('\r'); // Send OK back.
break; // Write Page case 'm' : if( baddress >= (ISPSTART) ) // Protect bootloader and ISP area. { send_usart('\r'); } else { boot_spm_busy_wait(); boot_page_write( waddress ); send_usart('\r'); // Send OK back.
} break; case 'e': //Chip erase // erase only main section (bootloader and isp protection) baddress = 0; while ( (ISPSTART - SPM_PAGESIZE) >= baddress ) { boot_page_erase(baddress); // Perform page erase boot_spm_busy_wait(); // Wait until the memory is erased. baddress += SPM_PAGESIZE; } boot_rww_enable(); send_usart('\r'); break; case 'x': read_usart();
LEDPORT &= ~(1 << LEDBIT); send_usart('\r'); break; case 'y': read_usart();
LEDPORT |= (1 << LEDBIT); send_usart('\r'); break; case 'E': //Exit upgrade wdt_enable(WDTO_15MS); // Enable Watchdog Timer to give reset send_usart('\r'); break; case 0x1b: // Reset
waddress = 0;
baddress = 0; break; default: send_usart('?'); break; } } return 0;}void send_boot(void){ send_usart('A'); send_usart('V'); send_usart('R'); send_usart('B'); send_usart('O'); send_usart('O'); send_usart('T');}
/*
void send_boot(void){ send_usart('I'); send_usart('S'); send_usart('O'); send_usart('J'); send_usart('T'); send_usart('A'); send_usart('G');}*/unsigned char read_usart(void){
while ( (UCSRA & (1<<RXC)) == 0)
;
unsigned char val = UDR;
// vals[valscnt] = val;
// valscnt ++;
// if ((valscnt) > 196)
// {
// valscnt = 0;
// }
return val;
}void send_usart(unsigned char data){
while ( ( UCSRA & (1<<UDRE)) == 0 ) ;
// vals[valscnt] = 0xFF;
// valscnt ++;
// vals[valscnt] = data;
// valscnt ++;
//
// if ((valscnt) > 196)
// {
// valscnt = 0;
// }
UDR = data;}void USART_Init(void){ //UBRRL = 23;
UBRRL = N19200;
UCSRB = (1<<RXEN) | (1<<TXEN); // Enable RX and TX UCSRC = (1<<URSEL)|(3<<UCSZ0); // Set Frame Formats }
void jump_to_jtag(void){ asm volatile ( "LDI r31,0 \n\t" "LDI r30,0 \n\t" "IJMP \n\t" ::);}
void bload_starter(void) __attribute__ ((naked)) __attribute__ ((section (".bload_start"))) ;
void bload_starter(void){ asm volatile ( "rjmp main"::);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -