历史上的今天

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

正在发生

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

发布者:koimqerolulk 来源: eefocus关键字:AVR单片机  BootLoader 手机看文章 扫描二维码
随时随地手机看文章

一、题目:

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)

                        {

[1] [2]
关键字:AVR单片机  BootLoader 引用地址:AVR单片机BootLoader功能应用源码与详细介绍

上一篇:Atmega64 LCD1602+proteus仿真程序
下一篇:Key.h头文件下载-AVR系列单片机的4*4小键盘驱动头文件

推荐阅读

不久前,上汽安吉物流旗下创新型智能物流一体化解决方案系统集成商安吉智能物联技术有限公司与全球著名的机器人专业生产企业发那科(FANUC)联合研发具有区域移动能力的协作机器人亮相。该机器人项目将智能AGV技术与协作机器人相结合,通过在区域内的自主移动,实现货物的智能抓取、搬运和操作。 安吉智能与发那科携手,将各自在智能AGV技术与协作机器人...
AMD已经完成了7nm Zen 2在桌面、发烧平台、服务器端甚至半定制领域(PS5、Xbox Scarlett)的布局,却还未惠及APU和笔记本处理器。据外媒报道,可靠消息称,AMD将在CES 2020(1月7日~10日,美国拉斯维加斯)期间发布,当季上市。当然,AMD并非单纯发布CPU,届时会有OEM厂商顺势推出7nm 3A平台的游戏本,处理器为6核Zen 2的Ryzen 5,RX 5300M或...
据最新消息,小米已经在为其下一代旗舰手机小米 11 做准备,这款机器将会搭载骁龙 875 处理器,而且还将获得限时的独占期。该信息来自爆料者@数码闲聊站,近日他在微博帖子中透露了该信息。小米 11 将是国内首款采用骁龙 875 处理器的手机,而三星的 Galaxy S21 系列将是全球首款采用该芯片的产品。这并不令人意外,但目前没有有关独占期将持续...
库函数学习笔记之相关函数:void CLK_DeInit(void);void CLK_HSECmd(FunctionalState NewState);void CLK_HSICmd(FunctionalState NewState);void CLK_LSICmd(FunctionalState NewState);void CLK_CCOCmd(FunctionalState NewState);void CLK_ClockSwitchCmd(FunctionalState NewState);void CLK_FastHaltWakeUpCmd(FunctionalState NewState)...

史海拾趣

问答坊 | AI 解惑

用VC++6.0实现PC机与单片机之间的串口数据交换

工业控制领域(如DCS系统),经常涉及到串行通信问题。为了实现微机和单片机之间的数据交换,人们用各种不同方法实现串行通信,如DOS下采用汇编语言或C语言,但在Windows 环境下却存在一些困难和不足。在Windows操作系统已经占据统治地位的情况下( ...…

查看全部问答∨

关于步进 伺服 脉冲量的计算

脉冲量的控制多用于步进电机、伺服电机的角度控制、距离控制、位置控制等。以下是以步进电机为例来说明各控制方式。 1、 步进电机的角度控制。首先要明确步进电机的细分数,然后确定步进电机转一圈所需要的总脉冲数。计算“角度百分比=设定角度/36 ...…

查看全部问答∨

仿反激式DCM的振铃现象

仿反激式DCM时发现VD有振铃现象,产生原因?比较以下两图,看能否看懂; 第一个图是取自别人的测量仿图;下图是FSZE1317的机理简易框图; 第二图的VD图我觉得不对 ,好像应该取反;该高电平的时候改成低电平 …

查看全部问答∨

关于Altera 调用modelsim仿真的问题

M序列产生 module Mxulie(clk,rst,mout); input clk; input rst; output mout; reg mout;  reg[3:0] temp;  always @(posedge clk or negedge rst)  begin  if(!rst)   b ...…

查看全部问答∨

如何使用Wince下WZC Tool配置无线网络

        在对wifi无线网络进行配置的时候,找到了wince提供的无线网络配置的工具WZC TOOL,但是我把WZC TOOL编译生成.exe文件,然后在shell.reg中进行加载,但是运行的时候,无线网络并没有配置好,不知道在wzctool.cpp中mai ...…

查看全部问答∨

纯C语言的Win32的程序(源文件的扩展名都是.c的)能用COM么?

纯C语言的Win32的程序(源文件的扩展名都是.c的)能用COM么?比如能用 IImagingFactory 和 IImage  COM接口么?…

查看全部问答∨

vxworks启动不了,各位大侠帮帮忙

编译已经通过并生成vxworks文件,通过网口加载vxworks,通过串口调试助手观察到,跑到starting就没下文了,大侠们赐教是什么原因。(我想在各个启动过程中所调用的函数中使用printf(“标记”);来观察到底执行到哪一个函数死掉了,结果不能将prin ...…

查看全部问答∨

分享一个lm3s811的入门资料

在网上找到一个lm3s811开发板的入门资料,觉得不错,大家分享下。为抢购的开发板做准备…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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