⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loader.c

📁 AVR MEGA16L上用的串口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 + -