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

📄 megaload.c

📁 mega128的bootloader程序,上位机采用vb,下位机采用gcc编译
💻 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 + -