自己用C语言写单片机PIC18 serial bootloader

摘要:
事实上我写了HyperBootloader_PIC18_J和HyperBootloader_PIC18_None_J两种bootloader。两种bootloader除了在实现上有一点不同,大小也不同外,其他都差不多。都是模仿HI-TECHPICCbootloader实现的,都是放置在程序存储器的头部,电脑端的程序都是用超级终端传送应用程序的Hex文件。InterruptVectorRemap由于bootloader位于程序存储器的头部,需要对InterruptVector进行remap.代码如下。#asm    PSECTintcode    gotoAPP_START+0x8    PSECTintcodelo    gotoAPP_START+0x18  #endasmHyperBootloader_PIC18_None_J主要代码段HyperBootloader_PIC18_None_J每接收一行的超级终端发过来的Hex数据,一个一个程序字地烧录。

了解更多关于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后才生效。

自己用C语言写单片机PIC18 serial bootloader第1张

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数据,一个一个程序字地烧录。具体实现的主要代码段如下。

自己用C语言写单片机PIC18 serial bootloader第2张自己用C语言写单片机PIC18 serial bootloader第3张
    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地烧录。具体实现的主要代码段如下。

自己用C语言写单片机PIC18 serial bootloader第2张自己用C语言写单片机PIC18 serial bootloader第5张
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)
        {
            caseDATA:
                while (bcount--)
                {
                    data_buffer[LEN_INDEX + data_index + 1] =g2x();
                    data_index++;
                }
                checksum();
                EECON1 =PGM_WRITE;
                WriteMem();
                break;
            caseEND:
                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;
            caseEXTEND_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》

免责声明:文章转载自《自己用C语言写单片机PIC18 serial bootloader》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇基于总变差模型的纹理图像中图像主结构的提取方法。C#原生加密方法: System.Security.Cryptography.CryptoStream DataSet加密解密下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

C语言中宏的作用

在C语言#define机制中包括了一个规定,与允许把参数替换到文本中,这种实现通常称为宏或宏定义。下面是宏的声明方式: #define name(parameter-list) stuff 其中 parameter-list的左括号必须与name紧邻,如果中间有空白,parameter-list就会被解释为stuff的一部分。 宏的作用 1.替换作用:在程...

c语言-----劫持系统03

1. 回顾   在前2节我们已经实现了劫持原理、函数指针等一些概念,下面进行系统劫持 2. 工具   vs2017   Detours 3. windows如何创建一个进程?   (1)创建进程函数 CreateProcessW( LPCWSTR lpApplicationName, //执行程序名称 LPWSTR lpCom...

C语言实现单链表面试题(进阶篇)

首先给出单链表的结构,下面实现具体代码 typedef int DataType; typedef struct Node { DataType data; struct Node*next; }Node,*pNode,*pList;//结点 typedef struct ComplexNode { DataType D;...

xilinx FPGA课程学习总结

    一时冲动,跑步进入了FPGA的大门,尤老师是教练,我之前一直做嵌入式软件,数字电路也是十年前大学课堂学过,早已经还给老师了。FPGA对于我来说完全是小白,所以。老师的课程,对于我来说至关重要!因为见过太多从入门到放弃的案例了! 什么样的教程和视频,可以不至于让小白从入门到放弃呢?我总结了几点:1.由浅入深,循序渐进,不急躁,不跃进,符合人的认知规律...

关于跨平台的一些认识

前段时间看了 周志明的那本 《深入理解java虚拟机》。对于平台无关性问题,有了一些新的认识。所以特写一篇博客来进行总结。 这是我的第一篇不针对具体技术,而只针对计算机系统和原理的博客文章,而这种话题,总是比较宽泛,而我本人的水平有限,所以我也只能泛泛的写写,思考的不对的地方,还望读者不吝批评。 C为什么不能跨平台 咱们先来讨论一下,C语言的执行过程,从而...

C语言中的正负数及其输出

在数学中,数字有正负之分。在C语言中也是一样,short、int、long 都可以带上正负号,例如: //负数 short a1 = -10; short a2 = -0x2dc9; //十六进制 //正数 int b1 = +10; int b2 = +0174; //八进制 int b3 = 22910; //负数和正数相加 lon...