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


免責聲明!

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



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