历史上的今天
返回首页

历史上的今天

今天是:2025年03月30日(星期日)

正在发生

2020年03月30日 | 基于AVR-BootLoader,通过霜蝉远程串口可实现单片机的远程升级

2020-03-30 来源:eefocus

最近一直利用业余时间写自己的“基于AVR-BootLoader”,启发是由于一次在ourAVR论坛看到了绍子阳的bootloader,联想到公司在用AVR MCU,但每次升级程序都要花费很大的力气车马劳顿的跑到工程现场,而且很多机器还安装在国外,为了升级一次程序发费了很多的人力物力财力,加上公司的机器目前大部分都配有远程监控系统,所以本人决定写一个具有自有产权的“AVR-BootLoader”。


      

特别说明:本“AVR-BootLoad”软件代码属上海霜蝉版权所有,在此贡献发布,仅限于个人免费使用不得用于商业用途,本人也不保证代码的严谨性,如在升级中出现任何问题与本人无关,本人已测试过Atmega64A与Atmega128。话不多说了上源代码,网友们和AVR爱好者可以拷贝到CodeWizardAVR V2.03.9编译器下编译。

需要讨论或有遇到BUG的网友们可以联系我:QQ:285247488  mail:shw@scicala.com 


上位机截图:

远程升级DTU

远程升级连接云平台虚拟串口

// 关于上海霜蝉-AVR_BootLoade_V1.00

// 1、软件版本V1.00 编译环境CodeWizardAVR V2.03.9 Standard;

// 2、支持本公司常用的三种AVR芯片;

// 3、支持标准Xmodem和扩展Xmodem_1K协议;

// 4、联机握手密码为"00",握手成功手的等待文件超时为1分钟;

// 5、默认复位等待3S退出boot到用户程序或循环运行boot;

// 6、支持1分钟以内的断网续传;

// 7、支持连续10帧以内数据错误的重传;

// 8、支持下载过程中的取消超作;

// 9、支持当收到包时,接收过程中每个字符的超时间隔为 1 秒;

// 10、支持所有的超时及错误事件至少重试 10 次;

// 11、支持数等待超时6S的请求;

// 12、Boot Loader - Size:1024words;

// 13、支持传输速度:38.400KB/S~2.400KB/S;

// 14、支持公司常用最多的三个型号ATMEGA32,64,128。

// 15、支持开门狗自定义开关,自定义时钟频率


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

This program was produced by the

CodeWizardAVR V2.03.9 Standard

Automatic Program Generator

?Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.

http://www.hpinfotech.com

Project      : AVR_BootLoader

Version     : V1.00

Date         : 2014-7-19

Author      : Sui Hongwei

Company : SCICALA

Comments:

Chip type                   : ATmega64L

Program type             : Boot Loader - Size:1024words

AVR Core Clock frequency: 16.000000 MHz

Memory model            : Small

External RAM size       : 0

Data Stack size           : 1024

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

#include "AVR_boot.h"   // 头文件包含

//--------------------------------------------------//

//同步密码长度

#define CONNECTCNT         7

//同步密码

uchar KEY_Data[10] = {"SCICALA"};

// Declare your global variables here

//--------------------------------------------------//

// 全局变量定义

uchar     RX_buff[BUFSIZE];                          // 数据拉收缓存

uchar   Frame_State,SOH_Wait_cnt;            // 帧状态,帧头等待计数

uint    Time_cnt,Error_cnt;                             // 超时计数,连续帧错误计数

uint    buffptr,buffptr_old,buffptr_New;            // 数据缓存指针必须大于1024

ulong   FlashAddr;                                          // Flash地址

uchar   UpdatedSta;                                        // 升级标志

//-----------------------------------------------//

//擦除(code=0x03)和写入(code=0x05)一个Flash页

void boot_page_ew(ulong p_address,char code)

{

    #asm

     ldd  r26,y+1       ; R26 LSB

     ldd r27,y+2        ; R27 MSB

    #endasm

    SPM_REG = code;                 // 寄存器SPMCSR中为操作码

    #asm

     mov r30,r26

     mov r31,r27

    #endasm

    #ifdef  ATMEGA128

     RAMPZ=(p_address>>16);     // RAMPZ0 = 1: ELPM/SPM 可以访问程序存储器地址$8000 - $FFFF ( 高64K 字节)

    #endif

    #asm("spm");                // 对指定Flash页进行擦操作

}

//填充Flash缓冲页中的一个字

void boot_page_fill(uint A_address,uint data)

{

      #asm

        LDD R30,Y+2     ; R30 LSB

        LDD R31,Y+3     ; R31 MSB

        LD  R26,Y

        LDD R27,Y+1

        MOV R0,R26

        MOV R1,R27

        MOV R26,R30

        MOV R27,R31

      #endasm

        SPM_REG =0x01;           //寄存器SPMCSR中为操作码

      #asm

        mov r30,r26

        mov r31,r27

      #endasm

        #asm("spm");            //对指定Flash页进行擦操作

}

//等待一个Flash页的写完成

void wait_page_rw_ok(void)

{

      while(SPM_REG & 0x40)

     {

         while(SPM_REG & 0x01);

         SPM_REG = 0x11;

         #asm("spm");

         while(SPM_REG & 0x01);

     }

}

//-----------------------------------------------//

//更新一个Flash页的完整处理

void write_one_page(uchar data[])

{

    uint i;

    boot_page_ew(FlashAddr,0x03);         //擦除一个Flash页

    wait_page_rw_ok();                    //等待擦除完成

    for(i=0;i    {

        boot_page_fill(i,(uint)data[i]+(data[i+1]<<8));

        wait_page_rw_ok();

    }

    boot_page_ew(FlashAddr,0x05);         //将缓冲页数据写入一个Flash页

    wait_page_rw_ok();                    //等待写入完成

}

//--------------------------------------------------//

//等待串口数据1S超时自动转为应答

unsigned char Wait1S_UART()

{

uchar i=0;

  do

  {

    #if WDGEn

    Watchdog_Reset();                       // 喂狗

    #endif

    if(TIFR&0x10)                           // OCF1A: T/C1 输出比较 A 匹配标志位

    {

        TIFR|=0x10;                         // 清除Time1定时器比较匹配标志

        i++;

        if(i>=4)                            // 等待1S 250ms*4=1S

        {   Frame_State=0x06; break;    }   // 帧数据超时转为应答请求重发数据帧

    }

    if(UCSRAREG(COMPORTNo) & 0x80)

    {

        UCSRAREG(COMPORTNo)|=0x80;          // 清除接收完成状态

        #if Run_LEDEn

        Run_LED;                            // 运行LED闪烁

        #endif

        i=100;

        return UDRREG(COMPORTNo);           // 读取UDR0

    }

  }

  while(100!=i);                            // 等待数据||超时退出

}

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

//===================================================//

void main(void)

{

uchar   packNO,packNO_old;  // 包号、包号留存

uint    crc16;              // 接收CRC缓存

uint    li;                 // 帧计数

uchar   ch, cl;             // 包号

    PORT_Init();            // 端口初始化

    UART_Init();            // 串口初始化

    Time1_Init();           // 定时器初始化 250ms

    #if WDGEn

    WatchDog_Enable();      // 打开看门狗(2S)

    #else

    WatchDog_Disenable();   // 禁止看门狗

    #endif

    #if Wait_BootTime

    Time_cnt=EEPROM_Read(EE_TimeAddr);  // 读取boot运行时间

    #endif

    #if SafeUpdated_En

    UpdatedSta=EEPROM_Read(EE_SafeAddr);// 读取升级成功标志

    #endif

    #asm("cli")             // 关总中断

    #if Delay_En            // 是否延时

    for(li=0;li<5000;li++)

    {   #asm("nop") }

    #endif

//-----------------------------------------------//

//等待"握手",否则退出Bootloader程序,从0x0000处执行应用程序

    Time_cnt += WiteTimeCnt;

    cl = 0;

    while(1)

    {

        if(TIFR&0x10)                   // OCF1A: T/C1 输出比较 A 匹配标志位

        {

            TIFR|=0x10;                 // 清除Time1定时器比较匹配标志

            #if Run_LEDEn

            Run_LED;                    // 运行LED闪烁

            #endif

            Time_cnt--;

            if(Time_cnt==0)             // 等待握手超时

            {

                #if SafeUpdated_En

                if(UpdatedSta)              // 上次升级失败

                {   while(1);           }   // 复位boot

推荐阅读

史海拾趣

博众电气(BZCN)公司的发展小趣事

博众电气深知人才是企业发展的核心力量。因此,公司高度重视人才培养和团队建设。通过引进优秀人才、建立完善的培训体系、营造良好的企业文化等措施,博众电气成功打造了一支高素质、专业化的团队。这支团队不仅为公司的发展提供了有力的人才保障,还为公司不断创新和进步注入了源源不断的动力。

这五个故事只是博众电气发展起来的冰山一角。在电子行业的激烈竞争中,博众电气凭借技术突破、质量管理体系建设、环保理念、国际化战略以及人才培养与团队建设等举措,不断壮大自身实力,逐步成为行业内的佼佼者。未来,博众电气将继续秉持创新、质量、环保、国际化和人才的理念,不断追求卓越,为实现更加辉煌的成就而努力拼搏。

BITECH公司的发展小趣事

随着国内市场的日益饱和,博众电气开始将目光投向国际市场。公司制定了国际化发展战略,积极参与国际竞争与合作。通过在国外设立分支机构、参加国际展会等方式,博众电气成功打开了国际市场的大门。如今,公司的产品已经远销海外多个国家和地区,国际市场份额逐年攀升。

Data Delay Devices公司的发展小趣事

在竞争激烈的电子行业中,质量管理是企业生存和发展的关键。DDD公司高度重视产品质量管理,建立了完善的质量管理体系和检测机制。公司从原材料采购、生产过程到成品检验都实行严格的质量控制,确保每一件产品都符合客户的要求和行业标准。这种对质量的执着追求使得DDD公司的产品在市场上赢得了良好的口碑和信誉。

Fremont_Micro_Devices_USA公司的发展小趣事

企业文化是企业的灵魂和核心竞争力之一。DDD公司一直注重企业文化的建设和发展。公司倡导“创新、协作、务实、进取”的企业精神,鼓励员工勇于创新、敢于担当、追求卓越。同时,DDD公司还注重员工培训和福利待遇的改善,为员工提供了广阔的发展空间和良好的工作环境。这种积极向上的企业文化氛围使得DDD公司成为了一个充满活力和凝聚力的团队。

CUI公司的发展小趣事

随着电子行业的发展,CUI技术逐渐融入到整个电子产业链的各个环节中。一些企业通过整合上下游资源,形成了从CUI材料研发、生产到电子产品制造的完整产业链。这种产业链整合不仅提高了企业的运营效率,还降低了生产成本,为企业赢得了更多的市场份额。

Bkc Semiconductors Inc公司的发展小趣事

随着技术的成熟和产品的不断完善,Bkc开始积极拓展市场。公司不仅加强了与国内外知名电子厂商的合作,还积极参与国际半导体展会和技术交流,不断提升品牌知名度。同时,Bkc还通过战略投资和并购等方式,进一步扩大了自身的业务规模和市场份额。

问答坊 | AI 解惑

做好职业规划的四个要点

职业生涯规划是针对决定个人职业选择的主观和客观因素进行分析和测定,确定个人的奋斗目标并选择符合这一目标的职业。职业生涯规划要求你根据自身的兴趣、特点,将自己定位在一个最能发挥自己长处的位置,选择最适合自己能力的事业,下面从四个方面 ...…

查看全部问答>

国内最大太阳能电池封装玻璃生产线建成投产

10月10日,国内最大的太阳能电池封装玻璃生产线在博爱县建成投产。   据介绍,河南裕华高白玻璃有限公司年产10万吨太阳能光伏玻璃项目三期工程是国家工业国债项目、河南省50家高成长型企业之一。到今年年底,这家位于焦作市博爱县的国内最大的 ...…

查看全部问答>

不错的系统资料,WCDMA系统设计PPT

1.W-CDMA协议概观(25.201) 2.传输信道和物理信道映射(25.211) 3.信道复用与信道编码(25.212) 4.扩频与调制模式(25.213)    5.物理层处理机制(25.214) 6.物理层测试规范(25.215) …

查看全部问答>

求购C8051下的汇编T9输入法源代码

求购C8051下的汇编T9输入法源代码…

查看全部问答>

NXP LPC2468 USB Host 主机控制器程序

本人第一次写USB 程序,网上很多都是USB设备(模拟一个USB设备),但任务是USB主机驱动,即驱动开发板驱动一个USB设备,先期是HID类 有哪位高手给一个资源,给点指导郁闷很长时间了。(1.JUNGO的USBWare要钱,很贵,有免费的吗) nxp LPC 24xx 以 ...…

查看全部问答>

关于年龄问题

我今年27了,搞嵌入式是不是有点晚了,请问这个行业能干到多少岁? 我是指目前国内的现状,一般搞嵌入式软件开发的都是多大的人? 总觉得自己有点大了,人家都是小伙子,有点不好意思,哈哈。…

查看全部问答>

关于PWM,S3C2440,timer

要使得TOUT1的输出频率是25MHZ,作了如下配置: //step1 s2440IOP->rGPBCON &=~(3rTCMPB1 =   ?? ; //step5         s2440PWM->rTCON &= (~(0xf…

查看全部问答>

EnumPrinterDrivers的奇怪现象

        BOOL ret;         ret = EnumPrinterDrivers(NULL, NULL, 1, NULL, 0, &dwNeeded, &dwReturned);         返回值是1,但是dwNeeded却为0,dwReturned也为0 & ...…

查看全部问答>

关于CPropSheet的问题

VS2005的MFC智能设备程序 我继承了 CPropertySheet类CMyPropSheet,然后在它的OnInitialDialog()中使用SetActivePage()就会出错,请问这是什么原因啊??…

查看全部问答>

无法读取处理器ID寄存器,请检查电缆和电源

终于把Jennic的产品先拿回来试试了,按照步骤运行Flash Programmer,选中目标bin文件,选择串口,连接好串口电缆,打开目标板电源,点击program按钮(这一步是要把程序写入板子),可是到这一步就跳出个对话框:无法读取处理器ID寄存器,请检查电缆 ...…

查看全部问答>