自己用C語言寫單片機PIC16 serial bootloader


                     了解更多關於bootloader 的C語言實現,請加我QQ: 1273623966 (驗證信息請填 bootloader),歡迎咨詢或定制bootloader(在線升級程序)。

  為什么自己寫bootloader

  我的第一款自己的serial bootloader是為Microchip PIC16單片機寫的UART bootloader,我命其名為HyperBootloader_PIC16. 為什么取這個名字,下面會講。很多朋友可能會問為什么要自己寫bootloader, 百度上一搜,有不少下載下來直接就可以用。比如ds30_Loader 就很不錯,免費,還支持Microchip很多系列的單片機。是沒錯,但是網上搜到的bootloader用C語言寫的少得可憐,或者不能用,或者不是用XC8編譯的(Microchip 的C編譯器)。它們絕大多數都是用匯編寫的,包括ds30_Loader。對於不怎么用匯編的我感覺很頭疼,這些bootloader也不太好修改,比如增加個自己需要的功能都比較困難。所以我決定自己用C語言寫PIC16 serial bootloader。說干就干,本來以為是小菜一碟,沒想到寫一個穩定好用又節省空間的bootloader也不簡單,這是后話。在講如何實現自己的PIC16 serial bootloader之前,我先講下serial bootloader的基礎知識。如果不需要了解的,請跳過這部分。

  Serial bootloader之ABC

  Serial bootloader是一種非常方便使用並且低成本的程序燒寫的方法。一般情況,每次燒寫Microchip單片機我們都需要將燒錄器PICKit3或ICD3接上目標板,然后在電腦上使用Microchip IPE或MPLAB X就可以直接燒寫Hex文件到目標板中。使用serial bootloader 就可以不需要插拔燒錄器,對開發工程師來講非常的方便。Serial bootloader需要用到單片機的串口,所以單片機端需要如下硬件電路,其中DB9串口是和電腦的串口相連。

  

  Serial bootloader 和應用程序一樣也是燒錄到程序存儲器中,serial bootloader 和應用程序在程序存儲器中需要分開放置。所以serial bootloader一般有兩種放置方式,一種是放置在程序存儲器頭部,另一種是放置在程序存儲器底部,如下圖所示。

 

  Serial bootloader 可以使用燒錄器PICkit3或ICD3燒到目標板上,之后更新應用程序就不需要燒錄器了。目標板和電腦通過串口相連,電腦上運行一個串口通信程序,將應用程序的Hex文件通過串口傳給serial bootloader, serial bootloader 再將接收到的Hex數據燒錄到程序存儲器的正確的位置上。接下來就是講今天的主角HyperBootloader_PIC16——我自己寫的第一款PIC16單片機C語言 serial bootloader。

  HyperBootloader_PIC16

  HyperBootloader_PIC16我是模仿HI-TECH的PICC bootloader,由於我是用XC8的編譯器的,所以有很多改動。上面有提到bootloader在程序存儲器中要么是在頭部要么是在底部,而HyperBootloader_PIC16 是在程序存儲器的底部。與它通信的電腦端的串口通信程序是超級終端——HyperTerminal. 這也是它命名的由來。

  主要代碼段

  HyerBootloader_PIC16是一款用C語言寫的只占很少空間的serial bootloader。不到0x200程序字空間. 實現邏輯也很簡單,主要代碼段如下。

/* 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
    }
View Code

  如何使用

  1. 使用XC8編譯HyperBootloader_PIC16, 由於HyperBootloader_PIC16將放在程序存儲器底部,占0x200程序字,編譯前,需先將Code Offset編譯參數設到正確值。例如,某PIC16 單片機的程序存儲器空間為0x2000程序字,Code Offset = 0x2000 - 0x200 = 0x1E00, 所以只需設置Code offset為1E00, 然后編譯。

  2. 使用pickit3燒錄HyperBootloader_PIC16的Hex文件到目標板中。

  3. 拔除pickit3燒錄器,連接目標板與PC的串口,打開超級終端,設置如下:9600-8-None-1-None, Line Delay-20ms

  4. 重啟目標板,超級終端會出現Booting... 字樣。

  5. 6秒內,在超級終端窗口中按下鍵盤上任何按鍵,會出現">"(6秒內沒按鍵,會自動跳轉到用戶的應用程序中去)。

  6. 打開Send Text File對話框,選擇期望燒錄的應用程序hex文件,點擊確認, HyperBootloader會將接收到的數據傳回到電腦超級終端上,並將數據燒錄到目標板程序存儲器的正確位置。

  7. 燒錄完畢,再次重啟目標板,超級終端顯示完Booting ......,就自動跳到應用程序中,目標板開始正常運行應用程序。

  之后每次更新應用程序,只需重復步驟 4 ~ 7 就可以了。

  效果展示

  下面是我使用HyperBootloader_PIC16給PIC16F877A燒錄應用程序的效果, HyperBootloader_PIC16會將接收到的數據先發送回電腦,同時再完成燒錄。如果有問題,這樣非常利於debug.

  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

  主要特性

  HyperBootloader_PIC16有以下主要特性

  1. C語言寫的,XC8 編譯(只有一點匯編在里面)。

  2. 非常容易移植。

  3. 支持FLASH燒寫

  4. 可支持EEPROM燒寫。

  5. 不支持CONFIG BITS/IDLOC 燒寫, 保持應用程序的Configuration Bits和Bootloader的一致。

 

  如果你有什么疑問,或有興趣了解更多關於bootloader 的C語言實現,請加我QQ: 1273623966驗證信息請填 bootloader 或 cnblogs)

 

  想了解dsPIC bootloader 請閱讀我的隨筆《自己用C語言寫dsPIC / PIC24 serial bootloader》

  想了解PIC18 bootloader 請閱讀我的隨筆《自己用C語言寫單片機PIC18 serial bootloader》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM