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

📄 avr-bootloader.c

📁 ATMEG128在线升级程序,运行稳定可靠
💻 C
字号:
#include <iom128v.h>
#define SPM_PAGESIZE 256

#define BAUD_H 0x00
#define BAUD_L 0x17
#define DATA_BUFFER_SIZE SPM_PAGESIZE

//定义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_RECIEVING_WAIT_CHAR 'C'

//定义全局变量
//const char startupString[]="Type 'd' download,Others run app.\n\r\0";
const char startupString[]="Please press 'd' to bootloader within 3 seconds![Encrypted!]\n\r\0";
char data[DATA_BUFFER_SIZE];
long address=0;

//擦除(code==0x03)和写入(code==0x05)一个Flash页
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");
}
//填充Flash缓冲页中的一个字
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");
}
//等待一个Flash页的写完成
void wait_page_rw_ok(void)
{
	while(SPMCSR&0x40)
	{
		while(SPMCSR&0x01);
		SPMCSR=0x11;
		asm("spm\n");
	}
}
///对BIN文件的数据进行解密
char de_encryptdata(char i)
{	
	char chr,tmpchrH,tmpchrL;
	chr=data[i];
	tmpchrH=0xf0&chr;
	tmpchrL=0x0f&chr;
	chr=tmpchrH/16+tmpchrL*16;
	return (0xff-0x86^chr);		
}
//更新一个Flash页的完整处理
void write_one_page(void)
{
	int i;
	boot_page_ew(address,0x03);
	wait_page_rw_ok();
	for(i=0;i<SPM_PAGESIZE;i+=2)
	{
		boot_page_fill(i,de_encryptdata(i)+(de_encryptdata(i+1)<<8));
	} 
	boot_page_ew(address,0x05);
	wait_page_rw_ok();
}
//从RS232发送1个字节
void uart_putchar(char c)
{
	while(!(UCSR0A&0x20));
	UDR0=c;
}
//从RS232接收1个字节
int uart_getchar(void)
{
	unsigned char status,res;
	if(!(UCSR0A&0x80)) return -1;
	status=UCSR0A;
	res=UDR0;
	res=res;
	if(status&0x1c) return -1;
	return res;
}
//等待从RS232接收1个有效字节
char uart_waitchar(void)
{
	int c;
	while((c=uart_getchar())==-1);
	return (char)c;
}
//计算CRC
int calcrc(char *ptr,int count)
{
	int crc=0;
	char i;
	while(--count>=0)
	{
		crc=crc^(int)*ptr++<<8;
		i=8;
		do
		{
			if(crc&0x8000)
				crc=crc<<1^0x1021;
			else
				crc=crc<<1;
		}
		while(--i);
	}
	return (crc);
}
//退出Bootloader程序,从0x0000处执行应用程序
void quit(void)
{
	uart_putchar('O');uart_putchar('K');uart_putchar('?');
	uart_putchar(0x0d);uart_putchar(0x0a);
	while(!(UCSR0A&0x20));
	MCUCR=0x01;
	MCUCR=0x00;
	RAMPZ=0x00;
	asm("jmp 0x0000\n");
 }

 //主程序
 void main(void)
 {
	int i=0;
	unsigned char timercount=0;
	unsigned char packNO=1;
	int bufferPoint=0;
	unsigned int crc;
	//初始化M128的USART0
	UBRR0H=BAUD_H; 
	UBRR0L=BAUD_L;
	UCSR0B=0x18;
	UCSR0C=0x0E;  
	OCR0=0xEA;
	//////////
	MCUCR = 0x00;
	EICRA = 0x00; //extended ext ints
	EICRB = 0x00; //extended ext ints
	EIMSK = 0x00;
	TIMSK = 0x00; //timer interrupt sources
	ETIMSK = 0x00; //extended timer interrupt sources

	TCCR0 = 0x00; //stop
	ASSR  = 0x00; //set async mode
	TCNT0 = 0x29; //set count
	OCR0  = 0xD7;
	//TCCR0 = 0x07; //start timer
	/////////// 
	while(startupString[i]!='\0')
	{
		uart_putchar(startupString[i]);
		i++;
	}  
	TCCR0 = 0x07; //start timer
	//////3秒等待PC机发'd',否则退出Bootloader程序,从0x0000处执行应用程序
	while(1)
	{
		if(uart_getchar()=='d')break;
		if(TIFR&0x02)
		{
   			if(++timercount>200) quit();	//3秒
	//		if(++timercount>20) quit();		//1秒 林树亮 2007-6-25改

			TCNT0 = 0x29; //set count
			TIFR=TIFR|0x02;
		}
	}
  
 ////每秒向PC机发送一个控制字符C,等待控制字
 while(uart_getchar()!=XMODEM_SOH)
 {
	if(TIFR&0x02)
	{
		if(++timercount>67)
		{
   			uart_putchar(XMODEM_RECIEVING_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)
		{
   			while(bufferPoint>=SPM_PAGESIZE)
			{
				write_one_page();
				address+=SPM_PAGESIZE;
				bufferPoint=0;
			} 
			uart_putchar(XMODEM_ACK);
			packNO++;
		}
		else
		{
   			uart_putchar(XMODEM_NAK);
		}
	}
	else
	{
		uart_putchar(XMODEM_NAK);
	}
 }
 while(uart_waitchar()!=XMODEM_EOT);
 uart_putchar(XMODEM_ACK);
 if(bufferPoint)
	 write_one_page();
 quit();

 }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -