自己用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》

posted on 2015-10-04 13:26 GeekyGeek 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/geekygeek/p/hyperbootloader_pic18.html

本书所附光盘跟目录下包含以下子目录: ● C语言程序例程。该子目录包括以下子程序: ——AD程序实现模拟量到数字量的转换功能; ——CAN程序实现CAN总线通讯功能; ——keyboard_check程序实现键盘的扫描查询方式输入; ——keyboard_disturb程序实现PORTB的"电平变化中断"进行键盘的输入; ——led0-8程序实现在8个LED上依次显示1~8数字; ——PWM程序用于使CCP1模块产生分辨率为10位的PWM波形,占空比为50%; ——RS-232程序通过RS-232接口来完成PC计算机与单片机之间的通信; ——simple_POARD程序为外围功能模块简单应用实例,点亮与PORTD口相连的八个发光二极管; ——stopwatch程序实现计时秒表功能,时钟显示范围00.00~99.99秒,分辨度为0.01秒; ——switchinput程序用于开关量的输入(采用SPI总线),并显示在与D口相连的LED上; ——wakeup程序实现PIC18F458的休眠工作方式,并由实验板上的按键产生"电平变化中断"将其从休眠状态中激活; ——WDT程序实现"看门狗"WDT的功能; ——Yejing程序实现液晶显示器的接口和显示功能。 ● 汇编语言程序例程。该子目录包括以下子程序: ——AD程序实现模拟量到数字量的转换功能; ——CAN程序实现CAN总线通讯功能; ——CAN2程序是优化的程序,同样实现CAN总线通讯功能; ——keyboard_check程序实现键盘的扫描查询方式输入; ——keyboard_disturb程序实现PORTB的"电平变化中断"进行键盘的输入; ——led0-8程序实现在8个LED上依次显示1~8数字; ——PWM程序用于使CCP1模块产生分辨率为10位的PWM波形,占空比为50%; ——RS-232程序通过RS-232接口来完成PC计算机与单片机之间的通信; ——simple_POARD程序为外围功能模块简单应用实例,点亮与PORTD口相连的八个发光二极管; ——stopwatch程序实现计时秒表功能,时钟显示范围00.00~99.99秒,分辨度为0.01秒; ——switchinput程序用于开关量的输入(采用SPI总线),并显示在与D口相连的LED上; ——wakeup程序实现PIC18F458的休眠工作方式,并由实验板上的按键产生"电平变化中断"将其从休眠状态中激活; ——WDT程序实现"看门狗"WDT的功能; ——Yejing程序实现液晶显示器的接口和显示功能。 ● MPLAB及C18安装使用简介。 ● 建立工程项目实例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值