历史上的今天
返回首页

历史上的今天

今天是:2024年10月19日(星期六)

正在发生

2019年10月19日 | AVR单片机BootLoader功能应用源码与详细介绍

2019-10-19 来源:eefocus

一、题目:

AVR单片机BootLoader功能应用

二、特色芯片技术介绍、使用说明:

AVR单片机中多数Mega系列单片机具有片内引导程序自编程功能即BootLoader功能。MCU 通过运行一个常驻FLASH的BootLoader 程序,利用任何可用的数据接口读取代码后写入自身的FLASH存储器中,实现自编程目的。


BootLoader功能将FLASH程序存储器其分为应用程序区和引导加载区,通过设置熔丝位BOOTSZ0和BOOTSZ1可以配置不同大小的引导加载区空间;通过设置熔丝位BOOTRST用于设置复位向量,当BOOTRST未被编程时器件复位后从应用程序区首地址开始执行,当BOOTRST被编程时器件复位后从引导区首地址开始执行。在设置好BOOTSZ0、BOOTSZ1和BOOTRST熔丝位后,需要把BootLoader程序定位并写入到引导区中,其首地址由熔丝位ROOTSZ0和BOOTSZ1的编程状态决定。在单片机上电复位后BootLoader程序开始执行,BootLoader程序可以通过USART、TWI或其它方式从计算机或其它数据源读取应用程序代码并写入到应用区中。


avr-libc提供一组C程序接口API来支持BootLoader功能,包含在中,主要几个宏有:
boot_page_erase ( address ):擦除FLASH指定页,address是以字节为单位的FLASH地址。


boot_page_fill ( address, data ):填充BootLoader 缓冲页,address为以字节为单位的缓冲页地址(对mega8:0~64),而data是长度为两个字节的字数据,因此调用前address 的增量应为2。此时data的高字节写入到高地址,低字节写入到低地址。


boot_page_write ( address ):boot_page_write执行一次的SPM指令,将缓冲页数据写入到FLASH指定页。


boot_rww_enable ( ):RWW区读使能,根据自编程的同时是否允许读FLASH存储器。RWW(Read-While-Write)可同时读写区,在对RWW 区自编程即页写入或页擦除时,由硬件锁定RWW区,RWW区的读操作被禁止,在对RWW区的编程结束后应当调用boot_rww_enable()使RWW区开放。

三、驱动程序的流程图

本应用以实际使用的Mega系列单片机Mega168为例,说明AVR单片机BootLoader的功能应用。BootLoader程序通过串口与计算机进行通信,执行读、写以及跳转到FLASH应用区的操作。单片机与计算机通信使用Xmodem通信协议,Xmodem通信协议见相关文档。其程序流程如下图。(可见附件中“流程图.vsd”文件)


四、驱动程序的源程序

对应Mega168的BootLoader程序包括bootloader.c和bootloader.h。
源程序清单如下:(可见附件中“bootloader.c”和“bootloader.h”文件)

五、设计及调试技巧

BootLoader程序不使用中断,以查询的方式读写UART数据。退出BootLoader程序后程序指针跳转到应用程序区首地址,如果要重新执行BootLoader程序以加载应用区程序,必须使用硬件复位。

六、典型问题及解决办法

在程序升级过程中遇到多个模块通过485总线连接在一起时,引起多个模块响应,造成误擦除,升级不能成功,在硬件及Bootloader程序中设置升级条件,条件满足时升级模块程序,否则跳转到应用程序区。

单片机源程序如下:

#include "bootloader.h"


//串口初始化

void ComInit(void)                                                                

{                                                                                        

        UBRR0H = BAUDREG/256;                                        

        UBRR0L = BAUDREG%256;                                        

        UCSR0A = 0;                                                                

        UCSR0B = (1 << RXEN0)|(1 << TXEN0);                

        UCSR0C = (1 << UCSZ00)|(1 << UCSZ01);        

}


//使用定时器1:产生以毫秒为单位的时间

void TimerInit()                                                      

{                                                                 

        OCR1A  = (unsigned int)(timeclk * (F_CPU  / (1024 * 1000.0f)));

        TCCR1A = 0;                                    

        TCCR1B = (1 << WGM12)|(1 << CS12)|(1 << CS10); 

}


//更新一个Flash页

void write_one_page(unsigned char *buf)

{

        boot_page_erase(FlashAddr);                  

        boot_spm_busy_wait();

        for(pagptr = 0; pagptr < SPM_PAGESIZE; pagptr += 2) 

        {

                boot_page_fill(pagptr, buf[pagptr] + (buf[pagptr + 1] << 8));

        }

        boot_page_write(FlashAddr);                 

        boot_spm_busy_wait();            

}


//跳转到用户程序

void quit()

{

        boot_rww_enable();

        (*((void(*)(void))PROG_START))();

}


//写入数据到串口

void WriteCom(unsigned char dat)

{

#if RS485

        RS485Enable();

#endif


        UDR0 = dat;

        while(!(UCSR0A & (1<        UCSR0A |= (1<

#if RS485

        RS485Disable();

#endif

}


//等待串口数据

unsigned char WaitCom()

{

        while(!(UCSR0A & (1<        return UDR0;

}


//向串口输出字符串

void putstr(const char *str)

{

        while(*str)

                WriteCom(*str++);

        WriteCom(0x0D);

        WriteCom(0x0A);

}


//CRC校验

void crc16(unsigned char *buf, unsigned char n)

{

        unsigned char j;

        unsigned char i;

        unsigned int crc, t;


        crc = 0;

        for(j = n; j > 0; j--)

        {

            crc = (crc ^ (((unsigned int) *buf) << 8));

                for(i = 8; i > 0; i--)

                {

                        t = crc << 1;

                        if(crc & 0x8000)

                                t = t ^ 0x1021;

                        crc = t;

                }

                buf++;

        }

        ch = crc / 256;

        cl = crc % 256;

}


int main(void)

{

        unsigned char cnt;

        unsigned char packNO;

        unsigned char crch, crcl;

        unsigned char li;


        asm volatile("cli": : );


        wdt_enable(WDTO_1S);

        TimerInit();


#if RS485

        DDRREG(RS485PORT) |= (1 << RS485TXEn);

        RS485Disable();

#endif


        ComInit();


        putstr(msg1);


        cnt = TimeOutCnt;

        cl = 0;

        while(1)

        {

                if(TIFR1 & (1<                {

                        TIFR1 |= (1 << OCF1A);


                        if(cl == CONNECTCNT)

                                break;


                        wdt_reset();


                        cnt--;

                        if(cnt == 0)

                        {

                        putstr(msg2);


                                quit();

                        }

                }


            if(DataInCom())

            {

                        if(ReadCom() == KEY[cl])

                                cl++;

                        else

                                cl = 0;

            }

        }


        putstr(msg3);


        cnt = TimeOutCntC;

        while(1)        

        {

                if(TIFR1 & (1<                {

                        TIFR1 |= (1 << OCF1A);

                        WriteCom(XMODEM_RWC) ; 


                        wdt_reset();


                        cnt--;

                        if(cnt == 0)

                        {

推荐阅读

史海拾趣

DETCO公司的发展小趣事

在电子产品行业日益关注环保和可持续发展的背景下,ElectronicsCorp采取了一系列积极措施。公司开始使用环保材料制造产品,并优化生产流程以减少能源消耗和废物排放。此外,ElectronicsCorp还推出了一系列回收计划,鼓励消费者将旧电子产品回收再利用。这些措施不仅提高了公司的环保形象,还增强了消费者对公司品牌的忠诚度。

DENWIRE公司的发展小趣事

ElectronicsCorp最初是一个在亚洲某城市的小型电子产品制造商。它以其高质量和合理的价格迅速获得了市场份额。公司创始人李先生坚持将研发作为核心驱动力,不断投入资金研发新技术。随着时间的推移,ElectronicsCorp的产品线不断扩大,包括智能手机、平板电脑和智能家居设备。凭借持续的创新和卓越的质量,ElectronicsCorp逐渐成长为全球电子行业的领导者。

Atmel (Microchip)公司的发展小趣事

Atmel公司自1984年成立以来,便专注于微控制器及相关技术的研发。在创业初期,公司凭借其深厚的技术积累,成功开发出了基于8051内核的8位元Flash微控制器,这在当时是一个重大的技术突破。这一产品的推出,不仅奠定了Atmel在微控制器领域的地位,也为公司的后续发展奠定了坚实的基础。

CHINFA公司的发展小趣事

CHINFA公司的创立并非一帆风顺。在创业初期,公司面临着资金短缺、技术落后和市场竞争激烈等多重困难。然而,公司的创始人凭借对电子行业的深厚热爱和坚定信念,带领团队克服了一个又一个难关。他们通过自主研发、技术创新和市场拓展,逐渐在行业中崭露头角。

AUSTIN公司的发展小趣事

在合并与合作的背景下,奥斯汀汽车开始注重产品创新和多样化。公司不断推出新的车型,以满足不同消费者的需求。例如,奥斯汀A40和A50等车型在市场上取得了不错的销量。同时,奥斯汀汽车还注重技术研发和创新,不断提升产品的性能和品质。

Green Power Solutions公司的发展小趣事
可能是由于取样电路、放大电路或磁放大器故障导致。

问答坊 | AI 解惑

联想LJ2500打印机打印原理图出现错误的解决方法

联想LJ2500打印机由于驱动程序的问题,在WINXP系统下打印Protel原理图时,图中的字符都是反向的,即镜像打印,真是一大缺陷,不知道联想是怎么搞的。就是将原理图复制到WORD文档中打印也是一样的。      我找到了一个解决方法 ...…

查看全部问答>

刚入门-请教

看了几天的Vxworks的书,基本看明白了任务调度,信号量,中断I/O等知识。 今年毕业,出来工作是做Vxworks应用开发的。 想多学点东西,应该再往哪方面走呢?…

查看全部问答>

请大家指点一下以后的学习方向

    我是西南大学的学生,本科,现在刚刚大三,9月2号刚刚参加完全国大学生电子大赛,最后却是意想不到的那种失败。     我本身是学计算机的,计算机科学与技术专业,这个专业软、硬全学,但偏向软件,而我偏偏对硬件感兴趣, ...…

查看全部问答>

PPC2003

请问一下我在XP上显示一张位图(×.BMP)SetDIBitsToDevice调用显示了图片··· 同一样代码我在VC2008上 ·PPC2003项目 但是SetDIBitsToDevice收到同样参数·但是还是不显示 SetDIBitsToDevice( hdc, 0, 0, cxDib, cyDib, 0, 0,  0, cyD ...…

查看全部问答>

求教关于蓝牙驱动SLEEP后的问题!

我在控制面板扫描蓝牙设备能扫描到,可以当WINCESLEEP起来后,再在控制面板扫描时,就扫描不到了,并弹出对话框“BLUETOOTH HARDWARE ERROR 10050。。。。。。”有哪位兄弟遇到过这样的情况呀,是哪一块把连接断开了吗?请多多赐教呀!…

查看全部问答>

Mk7A11p,兼容em78p153,sn2501,性价比优

研发兼销售工程师:李泳生   13760155692   075581580452  QQ:252859106(技术交流) Mk7A11p,兼容em78p153,sn2501,性价比优,同比优惠15%, 广泛应用于电动车防盗器,闪灯控制,闪字棒,闪字风扇,i温度显示等。月 ...…

查看全部问答>

实在被MSP430FG439集成的OA运放搞晕了.

MSP430FG439集成的的三个运放,datasheet上引脚的标注不怎么看得明白,有相关的中文资料吗,实在是被弄晕了!这些运放能设置各自的放大倍数吗,有没有例子啊!救命!!…

查看全部问答>

【征询贴】关于先前论坛团购的Real6410

团购的事情忙完了,参加团购的网友不能让板子闲着,要玩起来,所以想征询下大家的意见,想从何玩起?想怎么玩?玩成什么样?有具体计划的网友请跟帖回复,过几天我把我的计划给大家分享一下!~前一段时间不用多说,肯定要按照计划来熟悉学习板子, ...…

查看全部问答>

zedboard学习

有学习zedboard的同学吗,一起来交流学习http://write.blog.csdn.net/postlist…

查看全部问答>