zoukankan      html  css  js  c++  java
  • 自己用C语言写单片机PIC18 serial bootloader

                         了解更多关于bootloader 的C语言实现,请加我QQ: 1273623966 (验证信息请填 bootloader),欢迎咨询或定制bootloader(在线升级程序)。

      HyperBootloader_PIC18_J 和 HyperBootloader_PIC18_None_J

      完成PIC16 bootloader (详细情况请阅读我的上一篇随笔《自己用C语言写单片机PIC16 serial bootloader》) 后,接着就开始写PIC18的UART bootloader。事实上我写了HyperBootloader_PIC18_J 和 HyperBootloader_PIC18_None_J 两种bootloader。 一种给PIC18F, 另一种给PIC18FJ。两种bootloader除了在实现上有一点不同,大小也不同外,其他都差不多。都是模仿HI-TECH PICC bootloader实现的, 都是放置在程序存储器的头部,电脑端的程序都是用超级终端传送应用程序的Hex文件。在继续之前,先讲讲PIC18F和PIC18FJ的区别。

      PIC18F和PIC18FJ的区别

      PIC18F和PIC18FJ一个不同点是CONFIG BITS的烧写位置。对于PIC18F, CONFIG BITS被映射到程序存储器300000h (虚拟地址)开始的单元中。对于PIC18FJ,CONFIG BITS被烧写到程序存储器的底部(真实地址),每次上电自动会被映射到程序存储器300000h (虚拟地址)开始的单元中,所以对于PIC18FJ, 更新了CONFIG BITS,reset后才生效。

      

      Interrupt Vector Remap

      由于bootloader 位于程序存储器的头部,需要对Interrupt Vector进行remap. 代码如下。

      #asm
        PSECT intcode
        goto APP_START + 0x8
        PSECT intcodelo
        goto APP_START + 0x18
      #endasm

      HyperBootloader_PIC18_None_J 主要代码段

      HyperBootloader_PIC18_None_J 每接收一行的超级终端发过来的Hex数据,一个一个程序字地烧录。具体实现的主要代码段如下。

        for(;;)        // loop until end of file
        {
            while (RCREG!=':');        // wait for start of hex file line
    
            while(!TXSTAbits.TRMT);
            TXREG=':';      // the prompt to download a new program
    
            cksum = bcount = g2x();        // get the byte count
    #if _EEPROMSIZE > 256
            EEADRH = TBLPTRH = g2x();        // get the address
    #else
            TBLPTRH = g2x();
    #endif
            TBLPTRL = EEADR = g2x();
    
            DO_NOT_INCREMENT = 1;
            rectype = g2x();    // get the record type
            switch(rectype)
            {
            case DATA:    // ldata record
                #if (PROG_START > 0x200) || defined(__PIC18FX520)    
    // to protect bootloader from being overwritten
                if( (FLASH) && (TBLPTRU==0) && (TBLPTRH < (unsigned char)(PROG_START>>8)) )    
    // to protect bootloader from being overwritten
                    break;        // if bootloader is threatened, skip this
                #endif
            clear_buffer();
                while(bcount--)
                {
                    TABLAT = EEDATA = buff[(EEADR&(_FLASH_WRITE_SIZE-1))] = g2x();     // get the data
    
                    if((CONFIG)||(EEPROM))
                    {
                        if(CONFIG) // EEPROM/config. write byte at a time
                        {
                            table_write();
                        }
                        //zap();
                    }
                    else
                    {
                        if((EEADR & (_FLASH_WRITE_SIZE-1)) == (_FLASH_WRITE_SIZE-1))  //program/IDLOCs flash bytes at a time
                        {
                            flash8();
                            clear_buffer();
                        }
                    }
                    EEADR++;
                }
                if(((EEADR&(_FLASH_WRITE_SIZE-1))!=0)&&(FLASH)&&(!CONFIG))
                    flash8();
                checksum();
                break;
            case END:    // end of hex file
                checksum();
                TXSTA = 0x02;     //reset USART before jump to application
                RCSTA = 0x00;
                (*((void(*)(void))PROG_START))(); // jump to new program
                break;
            case EXTEND_ADDRESS:    // extended address record
                while(bcount--)
                {
                    EEADR=g2x();    // determines whether EE, Config or ID 
                }
                EEPGD=1;
                if(EEADR==0xF0)
                    EEPGD=0;    // select for EEPROM
                CFGS=0;
                if((EEADR&0xF0)==0x30)
                    CFGS=1;        // select for config write
                TBLPTRU=EEADR;
                checksum();
                break;
            }
        }
    View Code

      HyperBootloader_PIC18_J 主要代码段

      HyperBootloader_PIC18_J 每接收一行的超级终端发过来的Hex数据,在存到block数组中,block满了,再整个block地烧录。具体实现的主要代码段如下。

    for (;;)
        {
            while (RCREG != ':');
            while(!TXSTAbits.TRMT);
            TXREG=':';    // the prompt to download a new program
    
            cksum = bcount = g2x();
            data_buffer[LEN_INDEX] = bcount;
            data_buffer[ADDRH_INDEX] = g2x();
            data_buffer[ADDRL_INDEX] = g2x();
            rectype = g2x();
            switch(rectype)
            {
                case DATA:
                    while (bcount--)
                    {
                        data_buffer[LEN_INDEX + data_index + 1] = g2x();
                        data_index++;
                    }
                    checksum();
                    EECON1 = PGM_WRITE;
                    WriteMem();
                    break;
                case END:
                    checksum();
                    if (block_start)
                    {
                        WriteStart();
                        resetBlockBuffer();
                        block_start = 0;
                    }
                    TXSTA = 0x02; //reset USART before jump to application
                    RCSTA = 0x00;
                    asm("goto "___mkstr(APP_START));
                    break;
                case EXTEND_ADDRESS:
                    g2x();
                    data_buffer[ADDRU_INDEX] = g2x();
                    checksum();
                    break;
            }
            data_index = 0;
        }
    View Code

      如何使用

      1. 使用XC8编译HyperBootloader_PIC18_J 或HyperBootloader_PIC18_None_J。

      2. 使用pickit3烧录HyperBootloader_PIC18_J 或HyperBootloader_PIC18_None_J的Hex文件到目标板中。

      3. 拔除pickit3烧录器,连接目标板与PC的串口,打开超级终端,设置如下:9600-8-None-1-None, Line Delay-20ms

      4. 重启目标板,超级终端会出现Booting... 字样。

      5. 6秒内,在超级终端窗口中按下键盘上任何按键,会出现">"(6秒内没按键,会自动跳转到用户的应用程序中去)。

      6. 打开Send Text File对话框,选择期望烧录的应用程序hex文件(由于bootloader在程序存储器的头部,所以应用程序需要在编译前设置XC8的Code offset, 如果是使用HyperBootloader_PIC18_J,设置为400, 如果是使用HyperBootloader_PIC18_None_J, 设置为300),点击确认, HyperBootloader会将接收到的数据传回到电脑超级终端上,并将数据烧录到目标板程序存储器的正确位置。

      7. 烧录完毕,再次重启目标板,超级终端显示完Booting ......,就自动跳到应用程序中,目标板开始正常运行应用程序。

      之后每次更新应用程序,只需重复步骤 4 ~ 7 就可以了。

      主要特性

      HyperBootloader_PIC18_J 和 HyperBootloader_PIC18_None_J 有以下主要特性

      1. C语言写的,XC8 编译。

      2. 非常容易移植。

      3. 支持FLASH烧写

      4. 可支持EEPROM烧写。

      5. 支持CONFIG BITS/IDLOC 烧写。

      如果你有什么疑问,或有兴趣了解更多关于bootloader 的C语言实现,请加我QQ: 1273623966验证信息请填 bootloader 或 cnblogs)。

      

      想了解dsPIC bootloader 请阅读我的随笔《自己用C语言写dsPIC / PIC24 serial bootloader》

      想了解PIC16 bootloader 请阅读我的随笔《自己用C语言写单片机PIC16 serial bootloader》

  • 相关阅读:
    permission 文档 翻译 运行时权限
    TabLayout ViewPager Fragment 简介 案例 MD
    Log 日志工具类 保存到文件 MD
    OkHttp 官方wiki 翻译 MD
    Okhttp 简介 示例 MD
    OkHttp 官方Wiki之【使用案例】
    DialogPlus
    倒计时 总结 Timer Handler CountDownTimer RxJava MD
    RecyclerView 判断滑到底部 顶部 预加载 更多 分页 MD
    CSS3的媒体查询(Media Queries)与移动设备显示尺寸大全
  • 原文地址:https://www.cnblogs.com/geekygeek/p/hyperbootloader_pic18.html
Copyright © 2011-2022 走看看