avr bootloader source code

Publisher:光明2599Latest update time:2021-06-18 Source: eefocusKeywords:avr  bootloader Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

assembly.s


  .text
  
SPMCR = 0x57 ; RWW area busy flag, read RWW area allowed, allow write program storage area

; void write_page (unsigned int adr, unsigned char function);
; bits 8:15 adr addresses the page...(must setup RAMPZ beforehand!!!)
_write_page::
    XCALL __WAIT_SPMEN__
    movw    r30, r16        ;move address to z pointer (R31 = ZH, R30 = ZL)
    STS     SPMCR, R18      ;argument 2 decides function
    SPM                     ;perform pagewrite
    RET

;-----------------------------------------

; void fill_temp_buffer (unsigned int data, unsigned int adr);
; bits 7:1 in adr addresses the word in the page... (2=first word, 4=second word etc..)
_fill_temp_buffer::
    XCALL __WAIT_SPMEN__
    movw    r30, r18        ;move adress to z pointer (R31=ZH R30=ZL)
    movw    r0, r16         ;move data to reg 0 and 1
    LDI     R19, 0x01
    STS     SPMCR, R19
    SPM                     ;Store program memory
    RET     
 
;----------------------------------------- 

;unsigned char read_flash(unsigned int add);
_read_flash::
    mov r31,r17
    mov r30,r16
    lpm r16,z
    clr r17
    ret 
  
;unsigned int read_program_memory (unsigned int adr ,unsigned char cmd);
_read_program_memory::
    movw    r30, r16        ;move adress to z pointer
    SBRC    R18, 0          ;read lockbits? (second argument = 0x09)
    STS     SPMCR, R18      ;if so, place second argument in SPMEN register
    LPM     r16, Z+
    LPM     r17, Z
    RET
 
;-----------------------------------------
       
_enableRWW::
 XCALL __WAIT_SPMEN__
    LDI R27,0x11
    STS SPMCR,R27
    SPM
    RET  
 
;-----------------------------------------          

__WAIT_SPMEN__:
    LDS     R27,SPMCR       ; load SPMCR to R27
    SBRC    R27,0           ; check SPMEN flag
    RJMP    __WAIT_SPMEN__  ; wait for SPMEN flag cleared       
    RET
 
;-----------------------------------------



assembly.h



void write_page (unsigned int adr, unsigned char function);
void fill_temp_buffer (unsigned int data,unsigned int adr);
unsigned int read_program_memory (unsigned int adr,unsigned char cmd);
//void write_lock_bits (unsigned char val);
void enableRWW(void);
unsigned char read_flash(unsigned int add);




main.c


/******************************************************************************
Atmega16 BootLoader program 
date: the last day of 2004

/****************************************************************************/
#include
#include
#include "assembly.h"//Include assembly code header file

//××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
//Please select the chip model according to the target board
//#define ChipType Atmega8      
#define ChipType Atmega16      
//#define ChipType Atmega32      
//#define ChipType Atmega64      
//#define ChipType Atmega128      
//#define ChipType Atmega8535      
//*************************************************************
//Select the BOOT area size
//#define BootSize 'a' //128  
//#define BootSize 'b' //256
//#define BootSize 'c' //512
//#define BootSize 'd' //1024
//#define BootSize 'e' //2048 (Not sure if there is a chip with 2048 words of BOOT space)
//Select BootLoad version number
//#define BootVer 'f' //Version 1.0
//#define BootVer 'g' //Version 1.1
//#define BootVer 'h' //Version 1.2
//#define BootVer 'i' //Version 1.3
//#define BootVer 'j' //Version 1.4
//#define BootVer 'k' //Version 1.5
//#define BootVer 'l' //Version 1.6
//#define BootVer 'm' //Version 1.7
//#define BootVer 'n' //Version 1.8
//#define BootVer 'o' //Version 1.9
//#define BootVer 'p' //Version 2.0 (should be the final version)
//**************************************************************

#define Atmega16 0x31

//********************************************************************************
//#define InteClk //Whether to use the internal clock
//#define OscAddress 0x1fff //Clock calibration value storage address
//#define OscAddress 0x3fff //Clock calibration value storage address
//********************************************************************************
//Baud rate setting under 8 clocks
//#define BAU 103 //4800
//#define BAU 51 //9600
//#define BAU 34 //14400
//#define BAU 25 //19200

//Baud rate setting under 16M clock
#define BAU 103 //9600

//EEPROM used
#define EEPROM_UPDATE_0X00_0X06 7
#define EEPROM_REPEAT_ENTER_BOOT_TIMES 0x07
#define EEPROM_DEBUG0 0x08
#define EEPROM_DEBUG1 0x09
#define ERASE_FLASH_PAGE_NUM 112 //Erase page number


const unsigned char ucEepromWriteSuccess[EEPROM_UPDATE_0X00_0X06]={"success"};
const unsigned char ucEepromWriteUpdates[EEPROM_UPDATE_0X00_0X06]={"updates"};


//*****************************************************************************

#if (ChipType == Atmega16)
  #include  "iom16v.h"
  #define   PageByte     128   
  #define   AddressShift   7
#endif

void FlashLoad(void);
unsigned char GetPageNumber(void);
void ExecCode(void);
char GetOnePageData(void);
unsigned char WriteFlash(void);
char CheckFlash(void);
void SendChar(unsigned char c);
void delay(void);                 //1ms延时函数
//unsigned char RecChar(void);
static unsigned int GetCRC16Code(unsigned char* pCalcBuf, unsigned char ucSize);


//unsigned char PageBuffer[PageByte+2];
unsigned int  PageAddress=0;

#define BUFLEN 200
char uRxData;
char ucRecvBuf[BUFLEN];
unsigned int uiBufLen=0;
unsigned int uiStartBufDateLen=0;


//Read EEPROM function
static void EEPROM_Write(unsigned int Add,unsigned char Data)
{
 if(Add<512) //If the address is greater than 512, invalid
 {
  while(EECR&BIT(EEWE)); //Check whether the last EEPROM write operation is completed
  EEAR=Add; //Write address
  EEDR=Data; //Write data
  EECR|=BIT(EEMWE); //EEPROM write host enable: prepare
  EECR|=BIT(EEWE); //EEPROM write enable: write
 }
}

//Read EEPROM function
static unsigned char EEPROM_Read(unsigned int Add)
{
 unsigned char Temp=0;
 if(Add<512) //If the address is greater than 512, read 0 value
 {
  while(EECR&BIT(EEWE)); //Check whether the last EEPROM write operation is completed
  EEAR=Add; //Write address
  EECR|=BIT(EERE); //EEPROM read enable: read out
  Temp=EEDR; //Read data
 } 
 return Temp; //Return data
}

#if 0
void PrintfStringToArm(char * str)
{
 int i=0;
 for(i=0;i {
  SendChar(*(str+i));
 }
}
#endif


/*****************************************************************************/
//Flash编程                            
/*****************************************************************************/
void FlashLoad(void)
{
 unsigned int i;

 unsigned char ucPageDateSuccessFlag=0;
 SendChar('!');
 while (1)
 {
  if(!GetPageNumber())//Get page address
  {
   return;
  }
  else
  {
   if (PageAddress == 0xff80)//Write completed
   {
    SendChar('$');
    CLI();
    
    for(i=0;i    {
     EEPROM_Write(i,ucEepromWriteSuccess[i]);
    }
    SEI();

    return;
   }
   
   ucPageDateSuccessFlag=GetOnePageData();

   if (ucPageDateSuccessFlag==1)//Get a page of correct data
   {
    if(WriteFlash())
    {
     if (CheckFlash())
      SendChar('!');
     else
      SendChar('@');
    }
    else
    {
     return;
    }
   }
   else if(ucPageDateSuccessFlag==2)//Get a page of incorrect data
   {   
    SendChar('@');
   }
   else//Timeout
   {
    return;
   }
  }
 }

 //SendChar('%');
}

/*****************************************************************************/
unsigned char GetPageNumber(void)
{
 unsigned int i;
 unsigned char j; 
 unsigned int uiAddress;

 for(j=0;j<100;j++)
 {
  for(i=0; (i+4)<=uiBufLen; i++)
  {
   if(memcmp(ucRecvBuf+i,"##",2)==0)//"##" is followed by the page address
   {
    memcpy(&uiAddress,ucRecvBuf+i+2,2);
    
    PageAddress=(uiAddress<    uiStartBufDateLen=i+4;//page data offset
   
    return 1;   
   }
  }
  delay();
 }
 return 0;
}

static unsigned int GetCRC16Code(unsigned char* pCalcBuf, unsigned char ucSize)

 unsigned char i = 0;
 unsigned char j = 0;
 unsigned int usReturnValue = 0xFFFF;
 unsigned int usNew = 0xA001;
 
 for (i=0; i {
  usReturnValue ^= pCalcBuf[i];
  for(j=0; j<8; ++j)
  {
   if(usReturnValue & 0x0001)
   {
    usReturnValue >>= 1;
    usReturnValue ^= usNew;
   }
   else
   {
    usReturnValue >>= 1;
   }
  }
 }
 return usReturnValue;
}


/*****************************************************************************/
char GetOnePageData(void)
{
 unsigned char i;
 unsigned int LocalCheckSum = 0;
 unsigned int CheckSum = 0;

 for(i=0;i<200;i++)
 {
  if(uiBufLen>=(uiStartBufDateLen+PageByte+2))
  {
   //for(i=0;i<(PageByte+2);i++)
   //{
   // PageBuffer[i]=ucRecvBuf[i+uiStartBufDateLen];
   //}

   //LocalCheckSum=GetCRC16Code(PageBuffer, PageByte);
   LocalCheckSum=GetCRC16Code(&ucRecvBuf[uiStartBufDateLen-2], PageByte+2);//Check the page address as well, a total of PageByte+2 bytes.//memcpy(&CheckSum,&PageBuffer[PageByte],2)
   
   ;
   memcpy(&CheckSum,&ucRecvBuf[uiStartBufDateLen+PageByte],2);
   
   if (LocalCheckSum == CheckSum)
   {
    return 1;
   }
   else
   {
    CLI();
    
    memset(ucRecvBuf,0,BUFLEN);
    
    uiBufLen=0;

    BE();

    return 2;
   }
  }
  delay();
 }

 return 0;
}

/*****************************************************************************/
unsigned char  WriteFlash(void)
{
 unsigned int i;
 unsigned int TempInt;
 
 for (i=0;i {

  //TempInt=PageBuffer[i]+(PageBuffer[i+1]<<8); //The program is written by 'word', one page is 128 bytes, 64 words
  TempInt=ucRecvBuf[uiStartBufDateLen+i]+(ucRecvBuf[uiStartBufDateLen+i+1]<<8);

  fill_temp_buffer(TempInt,i); //call asm routine. See assembly code, store a page of data
 }
 
 if(PageAddress==0x0000)
 {
  if(ucRecvBuf[uiStartBufDateLen]==0xFF)
  {
   //CLI();
    
   //EEPROM_Write(EEPROM_DEBUG1,0xD1);

   //BE();

   return 0;
   
  }
  else //Erase data, when it is the first page, consistently erase all data from pages 0-103
  {
   for(;PageAddress   {    
    write_page(PageAddress,0x03); //0x03,Bit1=1,page erase,Bit0=1,stored program memory enable (SPMEN)
   }
   PageAddress=0x0000;
  }
 }
 else if(PageAddress==0x3700) //When it is the first page address of page 110, consistently erase data from pages 110-111
 {
  for(;PageAddress<0x3800;PageAddress+=128)
  {   
   write_page(PageAddress,0x03); //0x03,Bit1=1,page erase,Bit0=1,stored program memory enable (SPMEN)
  }
  PageAddress=0x3700;
 }

[1] [2]
Keywords:avr  bootloader Reference address:avr bootloader source code

Previous article:ADC acquisition digital tube display simulation program based on AVR microcontroller Atmega16
Next article:AVR series keyboard scanning

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号