📄 megaload.c
字号:
/*************************************************************************************
MegaLoad引导程序
文件名:MegaLoad.c
编 译:WinAVR-20050214
*************************************************************************************/
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <avr/boot.h>
#include <util/delay.h>
typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;
//*********************************************************
//选择BOOT区大小
//#define BootSize 'a' //128
//#define BootSize 'b' //256
//#define BootSize 'c' //512
#define BootSize 'd' //1024
//#define BootSize 'e' //2048(不知道是否有2048字BOOT空间的芯片)
//选择BootLoad版本号
//#define BootVer 'f' //1.0版本
#define BootVer 'g' //1.1版本 pei
//#define BootVer 'h' //1.2版本
//#define BootVer 'i' //1.3版本
//#define BootVer 'j' //1.4版本
//#define BootVer 'k' //1.5版本
//#define BootVer 'l' //1.6版本
//#define BootVer 'm' //1.7版本
//#define BootVer 'n' //1.8版本
//#define BootVer 'o' //1.9版本
//#define BootVer 'p' //2.0版本(应该是最终版本了)
//**********************************************************
#if defined (__AVR_ATmega8__)
#define Atmega8 0x30
#define ChipType Atmega8
#elif defined (__AVR_ATmega16__)
#define Atmega16 0x31
#define ChipType Atmega16
#elif defined (__AVR_ATmega32__)
#define Atmega32 0x32
#define ChipType Atmega32
#elif defined (__AVR_ATmega64__)
#define Atmega64 0x33
#define ChipType Atmega64
#elif defined (__AVR_ATmega128__)
#define Atmega128 0x34
#define ChipType Atmega128
#elif defined (__AVR_ATmega8535__)
#define Atmega8535 0x35
#define ChipType Atmega8535
#else
#error Invalid ChipType
#endif
//*****************************************************************************
#define UART0_BAUD 57600 // 默认波特率,可以达到较快的烧写速度
#define BOOT_SIZE 1024 // 字节
#define PAGE_SIZE SPM_PAGESIZE
#define MAX_PAGE_COUNT ((ulong)FLASHEND+1-BOOT_SIZE)/PAGE_SIZE
#define PORT_CS PORTD
#define DDR_CS DDRD
#define P_CS PD2
#if PAGE_SIZE == 64
#define ADDR_SHIFT 6
#elif PAGE_SIZE == 128
#define ADDR_SHIFT 7
#elif PAGE_SIZE == 256
#define ADDR_SHIFT 8
#else
#error ADDR_SHIFT is Invalid , it's only 64 , 128 and 256.
#endif
/*以下用于Mega128(双串口的选择),若是所用uart为UDR1,则将下列标识中
所有R0替换为R1*/
#ifdef UDR0
#define UDR UDR0
#define UCSRA UCSR0A
#define UCSRB UCSR0B
#define UCSRC UCSR0C
#define UBRRL UBRR0L
#define UBRRH UBRR0H
#define GICR MCUCR
#endif
#define LP_FALSE 0
#define LP_TRUE 1
#define LP_OVER 2
void FlashLoad (void);
void GetPageNumber (void);
void ExecCode (void);
char GetPage (void);
void WriteFlash (void);
char CheckFlash (void);
void SendChar (unsigned char c);
void delay (void); //1ms延时函数
unsigned char RecChar (void);
unsigned char PageBuffer[PAGE_SIZE];
unsigned long PageAddress;
void FlashLoad(void)
{
SendChar('!');
while(1)
{
char stat = GetPage();
if(stat == LP_TRUE)
{
WriteFlash();
if(CheckFlash())
{
SendChar('!');
}
else
{
SendChar('@');
}
}
else if(stat == LP_FALSE)
{
SendChar('@');
}
else
{
return ;
}
}
}
char GetPage(void)
{
unsigned char AddH,AddL;
unsigned char LocalCheckSum = 0;
unsigned char CheckSum = 0;
unsigned int i;
AddH = RecChar();
AddL = RecChar();
PageAddress = (AddH << 8) + AddL;
if((PageAddress == 0xffff) || !(PageAddress < MAX_PAGE_COUNT))
{
return LP_OVER; // exit..
}
PageAddress = PageAddress << ADDR_SHIFT;
LocalCheckSum = AddH + AddL; // 考虑Page的效验
for (i=0;i<PAGE_SIZE;i++)
{
PageBuffer[i] = RecChar();
LocalCheckSum += PageBuffer[i];
}
CheckSum = RecChar();
if(LocalCheckSum == CheckSum)
{
return LP_TRUE;
}
else
{
return LP_FALSE;
}
}
void WriteFlash(void)
{
unsigned int i;
unsigned int TempInt;
// 页擦除操作
boot_page_erase(PageAddress);
while(boot_rww_busy())
boot_rww_enable();
// 填充缓冲页
for(i = 0 ; i < PAGE_SIZE ; i += 2)
{
TempInt = PageBuffer[i] + (PageBuffer[i+1]<<8);
boot_page_fill(i,TempInt);
}
// 页写入操作
boot_page_write(PageAddress);
while(boot_rww_busy())
boot_rww_enable();
}
char CheckFlash(void)
{
unsigned int i;
unsigned int TempInt;
unsigned int TempInt2;
for(i = 0 ; i < PAGE_SIZE ; i += 2)
{
#if (FLASHEND > USHRT_MAX)
TempInt = pgm_read_word_far(PageAddress + i);
#else
TempInt = pgm_read_word(PageAddress + i);
#endif
TempInt2 = PageBuffer[i] + (PageBuffer[i+1]<<8);
if (TempInt != TempInt2)
{
return 0;
}
}
return 1;
}
unsigned char RecChar(void)
{
while(!(UCSRA & (1<<RXC)));
return UDR;
}
void SendChar(unsigned char c)
{
PORT_CS |= (1<<P_CS); //485的cs线切换,置于发送状态
while (!(UCSRA&(1<<UDRE)));
UDR=c;
while(!(UCSRA & (1<<TXC)));
UCSRA |= (1<<TXC) ;
PORT_CS &= ~(1<<P_CS); //485置于接收状态
}
void delay(void)
{
_delay_ms(20);
}
void init_uart(void)
{
UCSRB = 0x00; // disable while setting baud rate
UCSRA = 0x00;
UCSRC = (1<<UCSZ1)|(1<<UCSZ0); // 8bit+1bit stop
UBRRL = (F_CPU/16/(UART0_BAUD+1))%256;
UBRRH = (F_CPU/16/(UART0_BAUD+1))/256;
UCSRB = (1<<RXEN)|(1<<TXEN); // RXCEN TXCEN
DDR_CS |= (1<<P_CS);
PORT_CS |= (1<<P_CS);
}
void ExecCode(void)
{
GICR=0X01; // 中断向量表移位允许
GICR=0X00; // 中断向量指向应用程序区
asm("jmp 0x0000");
}
/*****************************************************************************/
int main(void)
{
unsigned char BootFlag;
unsigned int TempInt;
char try_times = 10 ;
init_uart();
while(1)
{
SendChar('>'); // 通知PC机,BOOT下载准备就绪
delay(); // 延时等待PC机响应
BootFlag=UDR;
if(BootFlag == '<') // 0x3c
{
SendChar(ChipType); // 芯片版本信息
SendChar(BootSize);
SendChar(BootVer);
while (1)
{
switch (RecChar())
{
case 'W':
FlashLoad();
break;
case 'E':
SendChar('E'); // 通知PC机,进入运用程序区
ExecCode();
break;
default :
break;
}
}
}
else
{
SendChar('E'); // 0x45
TempInt = pgm_read_word(0); // 新芯片不使用超时处理
if (TempInt==0xFFFF)
{
continue;
}
else
{
if(--try_times > 0)
{
continue;
}
ExecCode();//执行用户区程序
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -