×
单片机 > 单片机程序设计 > 详情

Atmega32 Bootloader测试程序详解

发布时间:2024-05-16 发布时间:
|

Atmega32的Bootloader程序,下面是源码。


在使用时需要将熔丝位进行配置:

1.编程BOOTSZ0、BOOTSZ1和BOOTRST三处,然后通过下载器将BOOTLOADER的hex下载到单片机中,重启后就从BOOTLOADER处运行了。


2.注意本例子使用的是内部8MHz和9600的波特率。


3.启动后可以看到:

然后按下‘D’键进入Bootloader等待下载。

#include

#include

#include

#include

#include

//IO定義

#define PIN_RXD 0 //PD0

#define PIN_TXD 1 //PD1

//常數定義

#define SPM_PAGESIZE 128

#define DATA_BUFFER_SIZE SPM_PAGESIZE

#define BAUDRATE 9600

#undef F_CPU

#define F_CPU 8000000

//定義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_WAIT_CHAR 'C'

struct str_XMODEM

{

unsigned char SOH; //起始字节

unsigned char BlockNo; //数据块编号

unsigned char nBlockNo; //数据块编号反码

unsigned char Xdata[128]; //数据128字节

unsigned char CRC16hi; //CRC16校验数据高位

unsigned char CRC16lo; //CRC16校验数据低位

}

strXMODEM;

unsigned long FlashAddress; //FLASH地址

#define BootAdd 0x7000 //Boot区的首地址(应用区的最高地址)

unsigned char BlockCount; //数据块累计(仅8位,无须考虑溢出)

unsigned char STATUS; //运行状态

#define ST_WAIT_START 0x00 //等待启动

#define ST_BLOCK_OK 0x01 //接收一个数据块成功

#define ST_BLOCK_FAIL 0x02 //接收一个数据块失败

#define ST_OK 0x03 //完成

#define PROG_START 0x0000


//延時

void delay_ms(unsigned int t)

{

while(t--)

{

_delay_ms(1);

}

}

void write_one_page(void)

{

unsigned char i;

unsigned char *buf;

unsigned int w;

boot_page_erase(FlashAddress);

boot_spm_busy_wait();

buf=&strXMODEM.Xdata[0];

for(i=0;i

{

w=*buf++;

w+=(*buf++)<<8;

boot_page_fill(i,w);

}

boot_page_write(FlashAddress);

boot_spm_busy_wait();

}

void put_c(unsigned char c) //发送采用查询方式

{

loop_until_bit_is_set(UCSRA,UDRE);

UDR=c;

}

void put_s(unsigned char *ptr)

{

while (*ptr)

{

put_c(*ptr++);

}

put_c(0x0D);

put_c(0x0A); //结尾发送回车换行

}

unsigned char get_data(unsigned char *ptr,unsigned char len,unsigned int timeout)

{

unsigned count=0;

do

{

if (UCSRA & (1<

{

*ptr++ = UDR; //如果接收到数据,读出

count++;

if (count>=len)

{

break; //

}

}

if(TIFR & (1<

{

TIFR|=(1<

timeout--;

}

}while (timeout);

return count;

}

unsigned int calcrc(unsigned char *ptr, unsigned char count)

{

unsigned int crc = 0;

while (count--)

{

crc =_crc_xmodem_update(crc,*ptr++);

}

return crc;

}

int main(void)

{

unsigned char c = 0;

unsigned char i;

unsigned int crc;

WDTCR &= ~(1<

DDRD=(1<

GICR = (1<

GICR = (0<

cli();

UCSRC = (1<

UBRRL = (F_CPU/BAUDRATE/16-1)%256; //设定波特率

UBRRH = (F_CPU/BAUDRATE/16-1)/256;

UCSRA = 0x00;

UCSRB = (1<

OCR0 = 28;

TCCR0 = (1<

//CTC模式下,溢出标志是输出比较匹配OCF0,对应的中断是输出比较匹配中断;

put_c(0x0c);

put_c(0x0c);

put_c(0x0c); //超級終端清屏

put_s("User want updata the programme,please touch [d]rnOtherwise the MCU run the old programme.rn");

get_data(&c,1,3000); //限时3秒,接收一个数据

if ((c=='d')||(c=='D'))

{

STATUS=ST_WAIT_START; //并且数据='d'或'D',进入XMODEM

put_s("Please use xmodem transmit the *.bin file.");

}

else

{

STATUS=ST_OK; //退出Bootloader程序

}

FlashAddress=0x0000;

BlockCount=0x01;

while(STATUS!=ST_OK)

{

if (STATUS==ST_WAIT_START)

{//XMODEM未启动

put_c(XMODEM_WAIT_CHAR); //发送请求XMODEM_WAIT_CHAR

}

i=get_data(&strXMODEM.SOH,133,1000);

if(i)

{

//分析数据包的第一个数据 SOH/EOT/CAN

switch(strXMODEM.SOH)

{

case XMODEM_SOH: //收到开始符SOH

if (i>=133)

{

STATUS=ST_BLOCK_OK;

}

else

{

STATUS=ST_BLOCK_FAIL; //如果数据不足,要求重发当前数据块

put_c(XMODEM_NAK);

}

break;

case XMODEM_EOT: //收到结束符EOT

put_c(XMODEM_ACK); //通知PC机全部收到

STATUS=ST_OK;

put_s("Updata the programme success.");

break;

case XMODEM_CAN: //收到取消符CAN

put_c(XMODEM_ACK); //回应PC机

STATUS=ST_OK;

put_s("Warning! It canceled by user to updata the programme.");

break;

default: //起始字节错误

put_c(XMODEM_NAK); //要求重发当前数据块

STATUS=ST_BLOCK_FAIL;

break;

}

}

if (STATUS==ST_BLOCK_OK) //接收133字节OK,且起始字节正确

{

if (BlockCount != strXMODEM.BlockNo)//核对数据块编号正确

{

put_c(XMODEM_NAK); //数据块编号错误,要求重发当前数据块

continue;

}

if (BlockCount !=(unsigned char)(~strXMODEM.nBlockNo))

{

put_c(XMODEM_NAK);

continue;

}

crc=strXMODEM.CRC16hi<<8;

crc+=strXMODEM.CRC16lo;

if(calcrc(&strXMODEM.Xdata[0],128)!=crc)

{

put_c(XMODEM_NAK); //CRC错误,要求重发当前数据块

continue;

}

//正确接收128个字节数据,刚好是M16的一页

if (FlashAddress

{ //如果地址在应用区内

write_one_page(); //将收到128字节写入一页Flash中

FlashAddress+=SPM_PAGESIZE; //Flash页加1

}

else

{

put_c(XMODEM_CAN); //程序已满,取消传送

put_c(XMODEM_CAN);

put_c(XMODEM_CAN);

STATUS=ST_OK;

put_s("The programme is out of the flash,cancle transmitted. ");

break;

}

put_c(XMODEM_ACK); //回应已正确收到一个数据块

BlockCount++; //数据块累计加1

}

}

put_s("LET'S GO!");

loop_until_bit_is_set(UCSRA,UDRE); //等待结束提示信息回送完成

GICR = (1<

GICR = (0<

/* 无论BootLoader是否使用中断,将中断向量表迁移到应用程序区头部,会增强程序的健壮性*/

boot_rww_enable (); //RWW区读允许,否则无法马上执行用户的应用程序

asm volatile("jmp 0x0000"); //跳转到Flash的0x0000处,执行用户的应用程序

}



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
基于AT91M42800A的LED显示系统设计