了解更多关于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; } }
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; }
如何使用
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》