Write your own PIC16 serial bootloader in C

Publisher:TechWhizKidLatest update time:2017-01-20 Source: eefocus Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

  Why write your own bootloader?

  My first serial bootloader was a UART bootloader for Microchip PIC16 microcontrollers. I named it HyperBootloader_PIC16. I will explain why I chose this name below. Many friends may ask why you should write your own bootloader. If you search on Baidu, you will find many bootloaders that can be used directly after downloading. For example, ds30_Loader is very good, free, and supports many series of Microchip microcontrollers. That's right, but the bootloaders found online are written in C language, which are either unusable or not compiled with XC8 (Microchip's C compiler). Most of them are written in assembly language, including ds30_Loader. For me who don't use assembly language very much, I feel very headache. These bootloaders are also not easy to modify. For example, it is difficult to add a function that I need. So I decided to write a PIC16 serial bootloader in C language. I did it right away. I thought it would be a piece of cake. I didn't expect that writing a stable, easy-to-use and space-saving bootloader is not easy. This is a later story. Before I talk about how to implement your own PIC16 serial bootloader, I will first talk about the basics of serial bootloader. If you don't need to know, please skip this part.

  The ABCs of Serial Bootloader

  Serial bootloader is a very convenient and low-cost method for burning programs. Generally, every time we burn Microchip microcontrollers, we need to connect the burner PICKit3 or ICD3 to the target board, and then use Microchip IPE or MPLAB X on the computer to directly burn the Hex file to the target board. Using serial bootloader does not require plugging and unplugging the burner, which is very convenient for development engineers. Serial bootloader requires the serial port of the microcontroller, so the microcontroller side needs the following hardware circuit, in which the DB9 serial port is connected to the serial port of the computer.

  

  The serial bootloader is burned into the program memory just like the application program. The serial bootloader and the application program need to be placed separately in the program memory. Therefore, there are generally two ways to place the serial bootloader, one is to place it at the head of the program memory, and the other is to place it at the bottom of the program memory, as shown in the figure below.

  

  Serial bootloader can be burned to the target board using the burner PICkit3 or ICD3, and then the burner is not needed to update the application. The target board and the computer are connected through the serial port. A serial communication program is run on the computer to pass the Hex file of the application to the serial bootloader through the serial port. The serial bootloader then burns the received Hex data to the correct location of the program memory. Next, let's talk about today's protagonist HyperBootloader_PIC16 - the first PIC16 microcontroller C language serial bootloader I wrote by myself.

  HyperBootloader_PIC16

  HyperBootloader_PIC16 is an imitation of HI-TECH's PICC bootloader. Since I use the XC8 compiler, there are many changes. It is mentioned above that the bootloader is either at the head or at the bottom of the program memory, and HyperBootloader_PIC16 is at the bottom of the program memory. The serial communication program on the computer side that communicates with it is HyperTerminal. This is also the origin of its name.

  Main code snippet

  HyerBootloader_PIC16 is a serial bootloader written in C language that takes up very little space. Less than 0x200 program word space. The implementation logic is also very simple, the main code segment is as follows.

/* receive a hex file via the serial port and write it to program memory */
    for(;;)        // loop until end of file    {
        typedef union {
            unsigned int word;
            unsigned char byte[2];
        } wordbyte;        static persistent unsigned char inx;        static persistent BANKX wordbyte addr;        while (comms_getch()!=':');    // wait for start of hex file line
        words2write = cksum = bytecount = getXbyte();    
        words2write >>= 1;           // convert byte count to word count
        addr.byte[1] = getXbyte();    // get the high byte of address
        addr.byte[0] = getXbyte();   // get the low byte of the address
        addr.word >>= 1;   // convert byte address to word address
        EEADR = addr.byte[0];
        EEADRH = addr.byte[1];        if(addr.byte[1] == 0x21)    // unless this case,
            EEPGD = 0;              // when EEPROM should be selected
        else
        {
            EEPGD = 1;        // else destination is flash memory    // ignore code that overlaps loader or data such as CONF/IDLOC            #ifdef _BANK_ALIGNED            if( addr.byte[1] >= (BOOT_START>>8) )
            {            #else
            if( addr.word >= (BOOT_START) ){            #endif
                while (!TRMT);
                TXREG='\r';                while (!TRMT);
                TXREG='\n';                continue;
            }
        }
        rectype = getXbyte();    // get the record type
        inx=0;        while(bytecount--)
        {
            databuff[inx++]=getXbyte();    // read all bytes in this record        }
        checksum();    // test the checksum of this record

        if(rectype==1)
        { // if this was an END record: prepare to run new program
            comms_puts("\r\nDone\r\n");
        #asm
            GOTO run_program
        #endasm
        }        // else ... INHX8M data record
        ix=0;
        isStartup=0;       // Initiate a write to memory - EEADR has already been loaded
        if (((tmpadrh=addr.byte[1])|(addr.byte[0] & 0xFC)) == 0)
        {    // is this address < 0004h?
            EEADRH = BOOT_START >> 8;    
        #ifndef _BANK_ALIGNED
            tmpadr=EEADR;
            EEADR = ((BOOT_START & 0xFF));        #endif
            isStartup=1;    // Yes - this is the reset vector code of new app        }
        #ifdef _WRITE_4_WORDS
        prewrite = EEADR & _FWMASK;
        EEADR &= ~_FWMASK;  // to start of flash-write boundary
        do
        {        if(prewrite){
                prewrite--;
                RD=1;
                NOP();
                NOP();
        }else{
                EEDATA=databuff[ix++];
                EEDATH=databuff[ix++];                if ( words2write == 0 ) {
                        prewrite=((~EEADR)&_FWMASK);
                }
        }        #else
        do
        {
            EEDATA=databuff[ix++];
            EEDATH=databuff[ix++];        #endif
            while(WR);
            WREN=1;    // commit this word to flash
            EECON2=0x55;
            EECON2=0xAA;
            WR=1;            //initiate the write            NOP();
            NOP();            while (WR);
            WREN=0;
        #ifdef _BANK_ALIGNED            if(isStartup && (EEADR==3)){        #else
            if(isStartup && ((EEADR&3)==3)){        #endif
            isStartup = 0;
            EEADRH = tmpadrh;    //swap back the address        #ifndef _BANK_ALIGNED
            EEADR = (tmpadr|3);        #endif
            }            if(++EEADR == 0)
                EEADRH++;
        #ifdef _WRITE_4_WORDS
        }while((prewrite)||words2write--);        #else
        }while(words2write--);        #endif
    }


  how to use

  1. Use XC8 to compile HyperBootloader_PIC16. Since HyperBootloader_PIC16 will be placed at the bottom of the program memory, occupying 0x200 program words, before compiling, you need to set the Code Offset compilation parameter to the correct value. For example, the program memory space of a PIC16 microcontroller is 0x2000 program words, Code Offset = 0x2000 - 0x200 = 0x1E00, so you only need to set the Code offset to 1E00 and then compile.

  2. Use pickit3 to burn the Hex file of HyperBootloader_PIC16 to the target board.

  3. Unplug the pickit3 programmer, connect the target board to the PC’s serial port, open the HyperTerminal, and set it as follows: 9600-8-None-1-None, Line Delay-20ms.

  4. Restart the target board and the word Booting... will appear in the HyperTerminal.

  5. Within 6 seconds, if you press any key on the keyboard in the HyperTerminal window, ">" will appear (if no key is pressed within 6 seconds, it will automatically jump to the user's application).

  6. Open the Send Text File dialog box, select the application hex file you want to burn, click OK, and HyperBootloader will transmit the received data back to the computer's hyperterminal and burn the data to the correct location of the target board's program memory.

  7. After burning is completed, restart the target board again. After the hyperterminal displays Booting..., it will automatically jump to the application program, and the target board will start to run the application program normally.

  Each time you update the app, just repeat steps 4 to 7.

  Show results

  The following is the result of me using HyperBootloader_PIC16 to burn the application program to PIC16F877A. HyperBootloader_PIC16 will send the received data back to the computer first, and then complete the burning. If there is a problem, this is very helpful for debugging.

  Booting.... >
  :100000000A128A1104283FFF0A128A11522EFF1B7E
  :10001000112883137F1883170008840A0319FF0A25
  :1000200008007F087F398A000408840A0319FF0A40
  :1000300082003FFF3FFF3FFF3FFF3FFF3FFF3FFF8C
  :10020000533465347434743469346E346734203450
  :1002100054344D3452343034203474346F342034F8
  :10022000753473346534203469346E347434653411
  :1002300072346E3461346C34203469346E34733407
  :100240007434723475346334743469346F346E3496
  :1002500020346334793463346C346534203463344B
  :100260006C346F3463346B342E342E342E342E348D
  :100270002E342E34203400347534743469346C34A4
  :1002800069347A346134743469346F346E342034B0
  :100290006F346E3420344D346934633472346F34C7
  :1002A0006334683469347034203438342D34623423
  :1002B0006934743420346D34693464342D347234C8
  :1002C00061346E346734653420344D3443345534EE
  :1002D000203450344934433431343634463438349D
  :1002E0003734373441340D340A3400341B345B3432
  :1002F00031343B34343430343B34333431346D3482
  :1003000020344E344F34543445341B345B34313450
  :100310003B34343430343B34333434346D3420346F
  :1003200043344F344C344F3452341B345B34313407
  :100330003B34343430343B34333432346D34203451
  :100340004334483441344E34473445341B345B34F1
  :1003500030346D3420340D340A3400342D342D34CF
  :100360002D342D342D342D342D342D342D342D3485
  :100370002D342D342D342D342D342D342D342D3475
  :100380002D342D342D342D342D342D342D342D3465
  :100390002D342D342D342D342D342D342D342D3455
  :1003A0002D342D342D342D342D342D342D342D3445
  :1003B0002D342D342D342D342D342D342D342D3435
  :1003C0002D342D340D340A340034543468346934F7
  :1003D00073342034703472346F346734723461345F
  :1003E0006D342034693473342034613420347334F0
  :1003F00069346D3470346C34653420346534783449
  :1004000061346D3470346C34653420346F34663448
  :100410002034733465347234693461346C3420347C
      .

      .

      .
  :100CA000FE0A452E8313E830FD000530FE00F930C2
  :100CB000FF00A03084000A128A11452683010A121F
  :100CC0008A115C2D20308316980090308312980092
  :100CD000673083169900181508008C1E00341A0816
  :100CE000F0008C1208003FFF3FFF3FFF3FFF3FFF38
  :02400E
  :00000001FF

  Done

  Key Features

  HyperBootloader_PIC16 has the following main features

  1. Written in C, compiled by XC8 (only a little bit of assembly in it).

  2. Very easy to transplant.

  3. Support FLASH burning

  4. Support EEPROM burning.

  5. CONFIG BITS/IDLOC programming is not supported. Keep the Configuration Bits of the application consistent with the Bootloader.


Reference address:Write your own PIC16 serial bootloader in C

Previous article:PIC microcontroller learning SPI operation digital tube
Next article:Write your own PIC18 serial bootloader in C

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号