📄 loader.c
字号:
#include <macros.h>
#include <stdio.h>
#ifndef _MEGA16_
#define _MEGA16_
#include <iom16v.h>
#endif
#ifndef _MEGA16_
#define _MEGA128_
#include <iom128v.h>
#endif
#define TCNT0_VALUE 0x16
#ifdef _MEGA16_
#define SPM_PAGESIZE 128 // 64 ???
#endif
#ifdef _MEGA128_
#define SPM_PAGESIZE 256
#endif
//#define BAUDRATE 19200
#define BAUDRATE 9600
#define CRYSTALFREQ 4000000
#define ERASE 0x03
#define WRITE 0x05
#define CR_ 0x0A
#define LR_ 0x0D
#ifdef _MEGA16_
#define DATA_BUFFER_SIZE 128
#endif
#ifdef _MEGA128_
#define DATA_BUFFER_SIZE SPM_PAGESIZE
#endif
// xmodem
#define XMODEM_NUL 0x00
#define XMODEM_SOH 0x01
#define XMODEM_STX 0x02
#define XMODEM_EOT 0x04
#define XMODEM_ACK 0x06
#define XMODEM_NAK 0x15
#define XMODEM_CAN 0x18
#define XMODEM_EOF 0x1A
#define XMODEM_RECEIVEING_WAIT_CHAR 'C'
const unsigned char MARK[]={"MEGA16 232 BOOT LOADER 4MHz 9600"};
unsigned char warning[]={"Download maybe destroy this device!Continue(Y/N)?\n\r"};
unsigned char data[DATA_BUFFER_SIZE];
long address = 0;
#ifdef _MEGA16_
void boot_page_ew(long p_address, char code)
{
asm("mov r30, r16\n"
"mov r31, r17\n"
"out 0x3b, r18\n");
SPMCR = code;
asm("spm\n");
}
//
void boot_page_fill(unsigned int address, int data)
{
asm("mov r30, r16\n"
"mov r31, r17\n"
"mov r0, r18\n"
"mov r1, r19\n");
SPMCR = 0x01;
asm("spm\n");
}
//
void wait_page_rw_ok(void)
{
while(SPMCR&0x40)
{
while(SPMCR&0x01)
{
}
SPMCR = 0x11;
asm("spm\n");
}
}
#endif
#ifdef _MEGA128_
void boot_page_ew(long p_address, char code)
{
asm("mov r30, r16\n"
"mov r31, r17\n"
"out 0x3b, r18\n");
SPMCSR = code;
asm("spm\n");
}
//
void boot_page_fill(unsigned int address, int data)
{
asm("mov r30, r16\n"
"mov r31, r17\n"
"mov r0, r18\n"
"mov r1, r19\n");
SPMCSR = 0x01;
asm("spm\n");
}
//
void wait_page_rw_ok(void)
{
while(SPMCSR&0x40)
{
while(SPMCSR&0x01)
{
}
SPMCSR = 0x11;
asm("spm\n");
}
}
#endif
void write_one_page(void)
{
int i;
boot_page_ew(address, ERASE); //erase one page
wait_page_rw_ok();
for(i = 0; i<SPM_PAGESIZE;i +=2)
{
boot_page_fill(i, data[i] + (data[i+1]<<8));
}
boot_page_ew(address, WRITE);//write one page
wait_page_rw_ok();
}
#ifdef _MEGA16_
void uart_putchar(char c)
{
while(!(UCSRA&0x20))
{
}
UDR = c;
}
int uart_getchar(void)
{
unsigned char status, res;
if(!(UCSRA&0x80))
{
return -1;
}
status = UCSRA;
res = UDR;
if(status&0x1C)
{
return -1;
}
return res;
}
#endif
#ifdef _MEGA128_
void uart_putchar(char c)
{
while(!(UCSR0A&0x20))
{
}
UDR0 = c;
}
int uart_getchar(void)
{
unsigned char status, res;
if(!(UCSR0A&0x80))
{
return -1;
}
status = UCSR0A;
res = UDR0;
if(status&0x1C)
{
return -1;
}
return res;
}
#endif
char uart_waitchar(void)
{
int c;
while((c=uart_getchar()) == -1)
{
}
return (char)c;
}
int calcrc(char *ptr, int len)
{
int crc = 0;
char i;
while(--len>=0)
{
crc = crc^(int) *ptr++<<8;
i = 8;
do
{
if(crc&0x8000)
{
crc = crc<<1^0x1021;
}
else
{
crc = crc<<1;
}
}while(--i);
}
return (crc);
}
void quit(void)
{
uart_putchar('O');
uart_putchar('K');
uart_putchar(LR_);
uart_putchar(CR_);
#ifdef _MEGA16_
while(!(UCSRA&0x20))
{
}
GICR |= 0<<IVSEL|1<<IVCE;
GICR &= ~(1<<IVSEL|1<<IVCE);
#endif
#ifdef _MEGA128_
while(!(UCSR0A&0x20))
{
}
MCUCR = 0x01;
MCUCR = 0x00;
RAMPZ = 0x00;
#endif
asm("jmp 0x0000\n");
}
#ifdef _MEGA16_
//UART0 initialisation
// desired baud rate: 9600
// actual: baud rate:9615 (0.2%)
// char size: 8 bit
// parity: Disabled
void uart0_init(void)
{
UCSRB = 0x00; //disable while setting baud rate
//UCSRA = (1<<U2X); //
UBRRL = (unsigned char)((CRYSTALFREQ / 16 /BAUDRATE)-1); //set baud rate lo
UBRRH = (unsigned char)(((CRYSTALFREQ / 16 /BAUDRATE)-1)>>8); //set baud rate hi
//UCSRC = 0x86;
UCSRC = (1<<URSEL)|\
(0<<UMSEL)|\
(0<<UPM1)|(0<<UPM0)|\
(0<<USBS)|\
(1<<UCSZ1)|(1<<UCSZ0)|\
(0<<UCPOL);
// UCSRB = 0x18;
UCSRB = (1<<RXEN)|(1<<TXEN)|(0<<RXCIE)|(0<<TXCIE);
}
void timer_init(void)
{
TIMSK |= 0<<OCIE2 | 0<<TOIE2 | /*timer 2*/\
0<<TICIE1 | 0<<OCIE1A | 0<<OCIE1B | 0<<TOIE1 | /*timer 1*/\
0<<OCIE0 | 1<<TOIE0; //timer 0
{
//TIMER0 initialisation - prescale:256
// WGM: Normal
// desired value: 15mSec
// actual value: 14.976mSec (0.2%)
TCCR0 = 0x00; //stop
ASSR = 0x00; //set async mode
TCNT0 = TCNT0_VALUE; //set count
OCR0 = 0xEA; //set compare
TCCR0 = 0<<FOC0 | 1<<WGM01 | 0<<WGM00 | 0<<COM01 | 0<<COM00 |\
1<<CS02 | 0<< CS01 | 0<<CS00;
}
}
#endif
void main(void)
{
int i = 0;
unsigned int timercount = 0;
unsigned char packNO = 1;
int bufferPoint = 0;
unsigned int crc;
CLI(); //disable all interrupts
#ifdef _MEGA128_
UBRR0L = 103; //set baud rate lo
UBRR0H = 0; //set baud rate hi
UCSR0B = 0x18;
UCSR0C = 0x06;
OCR0 = 0xEA;
TCCR0 = 0x0F;
#endif
#ifdef _MEGA16_// mega 16
timer_init();
uart0_init();
#endif
SEI(); //re-enable interrupts
while(1)
{
if(TIFR & 0x02)
{
if(++timercount>67)
{
break;
}
TIFR = TIFR|0x02;
}
}
uart_putchar(LR_);
uart_putchar(CR_);
uart_putchar('3');
uart_putchar(LR_);
timercount = 0;
while(1)
{
if(uart_getchar() == 'd')
{
break;
}
if(TIFR & 0x02)
{
if(timercount==67)
{
uart_putchar('2');
uart_putchar(LR_);
}
else if(timercount==134)
{
uart_putchar('1');
uart_putchar(LR_);
}
if(++timercount > 200)
{
quit();
}
TIFR = TIFR|0x02;
}
}
uart_putchar(CR_);
puts(warning);
uart_putchar('5');
uart_putchar(LR_);
timercount = 0;
while(1)
{
i = uart_getchar();
if(i == 'Y')
{
break;
}
if(i != -1)
{
quit();
}
if(TIFR & 0x02)
{
if(timercount==67)
{
uart_putchar('4');
uart_putchar(LR_);
}
else if(timercount==134)
{
uart_putchar('3');
uart_putchar(LR_);
}
else if(timercount==200)
{
uart_putchar('2');
uart_putchar(LR_);
}
else if(timercount==267)
{
uart_putchar('1');
uart_putchar(LR_);
}
if(++timercount > 334)
{
quit();
}
TIFR = TIFR|0x02;
}
}
// send "c" to PC
while(uart_getchar()!=XMODEM_SOH)
{
if(TIFR&0x02)
{
if(++timercount>67)
{
uart_putchar(XMODEM_RECEIVEING_WAIT_CHAR);
timercount = 0;
}
TIFR = TIFR|0x02;
}
}
do
{
if((packNO == uart_waitchar())&&(packNO == (~ uart_waitchar())))
{
for(i=0; i<128; i++)
{
data[bufferPoint] = uart_waitchar();
bufferPoint++;
}
crc = uart_waitchar()<<8;
crc+=uart_waitchar();
if(calcrc(&data[bufferPoint-128],128)==crc)
{
#ifdef _MEGA16_
while(bufferPoint>=SPM_PAGESIZE)
{
write_one_page();
address += SPM_PAGESIZE;
bufferPoint -= SPM_PAGESIZE;
}
#endif
#ifdef _MEGA128_
while(bufferPoint>=SPM_PAGESIZE)
{
write_one_page();
address += SPM_PAGESIZE;
bufferPoint = 0;
}
#endif
uart_putchar(XMODEM_ACK);
packNO++;
#ifdef _MEGA16_
if(packNO>=112)
{
puts("LARGE IMAGE!");
quit();
break;
}
#endif
}
else
{
uart_putchar(XMODEM_NAK);
}
}
else
{
uart_putchar(XMODEM_NAK);
}
}while(uart_waitchar()!=XMODEM_EOT);
uart_putchar(XMODEM_ACK);
if(bufferPoint)
{
#ifdef _MEGA16_
write_one_page();
#endif
#ifdef _MEGA128_
write_one_page();
#endif
}
quit();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -