搜索
bottom↓
回复: 2

关于PIC16 BootLoader 编译代码到末端FLASH地址问题?

[复制链接]

出0入0汤圆

发表于 2014-9-5 09:33:50 | 显示全部楼层 |阅读模式
附件是PICC软件的例子,有个疑问,

编译器没有任何设置,编译完代码自动偏移到末端FLASH地址,

明显是在代码实现的,那代码上是怎么实现编译偏移到FLASH 尾部?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2014-9-5 09:34:51 | 显示全部楼层
/*
*         BOOT LOADER v3.04 Copyright (C) 2008 HI-TECH Software
*        This software is freely distributable and may be used
*        for any purpose. No warranty of any kind is provided
*        and all use is entirely at your own risk.
*
*        The boot loader is suitable for use with the following
*        PICmicro controllers:
*
*        16F870, 16F871, 16F873, 16F873A, 16F874,
*        16F874A, 16F876, 16F876A, 16F877, 16F877A
*
*        Refer to the accompanying bootldr.txt file for details.
*       
*        BOOTLDR.C
*/


#include <htc.h>
#include "bootldr.h"

/* Unprotect memory and disable the watchdog timer */
#ifdef MPLAB_ICD
__CONFIG(UNPROTECT & WDTDIS & DEBUGEN & LVPDIS);
#else
__CONFIG(UNPROTECT & WDTDIS);
#endif


// cksum - a variable used for calculating checksums. By declaring the
// variable "persistent" it will tell the compiler not to bother initializing
// it on startup and therefore code size will be smaller.
persistent unsigned char cksum;       


// if "VERBOSE" is defined, additional feedback is given by the
// below routines.
#ifdef VERBOSE
const unsigned char START_MSG[]="HI-TECH Software (C)2008\n";
const unsigned char DOWNLOAD_MSG[]="\rDownload-";

/* PUTCH() - outputs a byte to the serial port */
void
putch(unsigned char byte)
{
        while(!TXIF);        /* set when register is empty */
                TXREG = byte;        /* output one byte */
}

/* Output a string via the serial port */
void
puts(const char *s)
{
        while(s && *s)               
                putch(*s++);       
}
#endif

/* Get a 4 bit HEX number from the serial port */
unsigned char
gx(void)
{
#if VERBOSE == 2
    char tmp;   

        while(!RCIF);
        tmp = RCREG;
        putch(XOFF);
        putch(tmp);        // echo input nibbles to output
        tmp -= '0';
        if (tmp>9)
                tmp -= ('A' - '0');
        putch(XON);
        return tmp;
#else
        while(!RCIF);
        if(RCREG>='A')        //translate the ASCII to hex
                return ((RCREG - (unsigned char)'A')+10);
        return (RCREG - '0');
#endif
}

/* Get an 8 bit HEX number from the serial port */
unsigned char
g2x(void)
{
        unsigned char input_byte;
        input_byte=(gx()<<4);                //get first nibble
        input_byte|=gx();                //get second nibble
        cksum+=input_byte;                //compute checksum
        return (input_byte);
}

/* check the checksum */
void
checksum(void)
{
        g2x();
        if(cksum!=0)        // if checksum does not add to zero, bad check, reset
                RESET();
#if VERBOSE == 2
        putch('\r');        // echo each hex record on a new line
        putch('\n');        // echo each hex record on a new line
#endif
}
       
/* Initiate a write to memory */
void
writemem(void)
{
        char tmpadrh;
#ifdef IRREG_START
        char tmpadr;

#endif
        while(!TXIF);
        TXREG = XOFF;
#ifdef IRREG_START
        tmpadr = EEADR;
        if (((tmpadrh=EEADRH)==0) && (tmpadr < 4))        // is the address < 4?
        {
                EEADRH = BOOT_START >> 8;        //yes - then move it
                EEADR += (BOOT_START & 0xFF);
        }
#else
        if (((tmpadrh = EEADRH)==0) && (EEADR < 4))
        {
                EEADRH = BOOT_START >> 8;        //yes - then move it
        }
#endif
        while(WR);                //configure for the write to memory
        WREN=1;
        EECON2=0x55;
        EECON2=0xAA;
        WR=1;                        //initiate the write
        NOP();
        NOP();
        WREN=0;
        EEADRH = tmpadrh;        //swap back the address in case it was one we moved
#ifdef IRREG_START
        EEADR = tmpadr;        //swap back the address in case it was one we moved
#endif
        while(!TXIF);
        TXREG = XON;
}

void
main(void)
{
        unsigned char LOW_ADDRESS,rectype,count;


        INIT_COMMS();        // sets up the serial port for communication

        LOW_ADDRESS = RCREG;  //flush receive register

/* Bootloader waits for a specified time. If the serial port gets no response in */
/* this time, execution of existing program begins. */
#ifdef VERBOSE
        puts(START_MSG);        // print a welcome message
#endif

        for(count=BOOT_TIMEOUT; count; --count)
        {
                if (RCIF)                //have we recieved anything?
                        break;
#ifdef VERBOSE        // display a countdown for user response
                puts(DOWNLOAD_MSG);
                putch('0'+count);
#else
                TXREG=('0'+count);        //display a countdown
                while(!TXIF);
                TXREG='\r';
#endif
                INTCON=0;        // disables interrupts.
                T1CON=0x35;        // pause during countdown
                while(!TMR1IF); //wait...
                TMR1IF=0;        //clear the flag
                T1CON=0x00;        // disable the timer again
        }

        if (!RCIF)        //did it timeout without recieving anything?
        {        // no hex file to download, resume normal program
                #asm       
                        ljmp BOOT_START
                #endasm       
        }
        TXREG=':';        // prompt to indicate bootloader is ready to recieve hex file

/* receive a hex file via the serial port and write it to program memory */
        for(;;)                // loop until end of file
        {
                while (RCREG!=':');                // wait for start of hex record
#if VERBOSE == 2
                putch(':');
#elif defined(VERBOSE)
                putch('.');
#endif       
                cksum = count = g2x();        // get the byte count and reset the checksum
                count>>=1;                // byte count >> word count
                EEDATA = g2x();                // get the high address byte

                LOW_ADDRESS = g2x();        // get the low byte of the address
                LOW_ADDRESS >>=1;        // convert the hex file's byte address to a PIC word address
                if((EEDATA&1)==1)        // does the high byte need to roll a bit into the low address?
                        LOW_ADDRESS |= 0x80;
                EEADRH = EEDATA >> 1;                // byte to word conversion on high address byte
                EEADR = LOW_ADDRESS & 0xFC;        // point to start of 4 word block
               
                EEPGD = 1;                // destination is flash memory
                if(EEDATA == 0x42)        // unless this case,
                        EEPGD = 0;        // when EEPROM should be selected
                else
                        if(EEDATA >= 0x40){        // ignore any other special types such as CONFIG/IDLOC
#if VERBOSE == 2
                                putch('\r');
#endif
                                continue;
                        }

                rectype = g2x();        // get the record type
                if(rectype==1){                // END OF FILE record: prepare to run new program
                        checksum();
#ifdef VERBOSE
                        puts("Ok");
#else
                        TXREG=')';
#endif
                        #asm
                                ljmp _redirect
                        #endasm
                }
                else{                // this record is a data record
                        while((count != 0)||(EEADR&2)||(EEADR&1)){        // keep writing until all bytes done and 4 word block complete...
                                RD=1;                // read data from destination address (may need to re-write this word)
                                NOP();
                                NOP();

                                if(EEADR == LOW_ADDRESS)        // has the address reached the valid range yet?
                                        rectype |= OK_BIT;        // if so set a bit to indicate we are Ok to source from USART

                        // Test to see whether this address is to be written with new data.
                                if(count!=0){                // if there is still incoming data for this hex record
                                        if((rectype & OK_BIT) == OK_BIT){        // has the address reached the valid range yet?
                                                if(LOADER_SAFE){
                                                        EEDATA = g2x();        // get the data low byte
                                                        EEDATH = g2x();        // get the data high byte
                                                }
                                                count--;        // decrement word count
                                        }
                                }
                                writemem();                // write this to memory
                                if(++EEADR == 0)        // select next address
                                        EEADRH++;
                        }        // end of this record and 4 word block
                        checksum();
                }
        }
}

void redirect(void) @ BOOT_START{
#asm
        PCLATH equ 0Ah
        PCL equ 02h
       
        ; this must be 4 word in length (including return)
        movlw 0
        movwf PCLATH
        movwf PCL
#endasm
}


出0入0汤圆

 楼主| 发表于 2014-9-5 09:35:09 | 显示全部楼层
#ifndef _BOOTLDR_H_
#define _BOOTLDR_H_

/*
*         BOOT LOADER v3.01A Copyright (C) 2008 HI-TECH Software
*        This software is freely distributable and may be used
*        for any purpose. No warranty of any kind is provided
*        and all use is entirely at your own risk.
*
*        The boot loader is suitable for use with the following
*        PICmicro controllers:
*
*        16F870, 16F871, 16F873, 16F873A, 16F874,
*        16F874A, 16F876, 16F876A, 16F877, 16F877A
*       
*        BOOTLDR.H
*/


/* Time (seconds) to wait for user input. Must be <= 9 */
#define BOOT_TIMEOUT        9

/* Baud rate to use for data transfer/communication */
#ifndef BAUD
#define BAUD 2400
#endif

// System frequency
#ifndef FOSC
#define FOSC 4000000L
#endif

// Find out the program memry size of this chip
#ifndef _ROMSIZE
#error Bootloader does not support the selected processor
#else
#define FLASH_SIZE        _ROMSIZE        // _ROMSIZE is defined by the compiler
#endif

// Address where boot loader will start
#if VERBOSE == 2
#define BOOTLOADER_SIZE 0x180
#elif defined(VERBOSE)
#define BOOTLOADER_SIZE 0x180
#else
#define BOOTLOADER_SIZE 0x100
#endif

// If this bootloader is being compiled to run on a system that may one day
// be debugged with the ICD2, we need to allow space for that.
#if defined(MPLAB_ICD)
#define BOOT_START (FLASH_SIZE - BOOTLOADER_SIZE - 0x100)
#else
#define BOOT_START (FLASH_SIZE - BOOTLOADER_SIZE)
#endif

// Check whether the bootloader supports this processor
#if defined(_16F877) || defined(_16F877A) || defined(_16F876) || defined(_16F876A) || \
        defined(_16F874) || defined(_16F874A) || defined(_16F873) || defined(_16F873A) || \
        defined(_16F871) || defined(_16F870)
// processor is supported
#else
#error This bootloader does not support the selected processor
#endif

#if ((BOOT_START & 0xFF) != 0)
#define IRREG_START
#endif

#if (BAUD > 2400)
#warning File transfer not recommended to exceed 2400 baud
#endif

#define NINE 0     /* Use 9bit communication? FALSE=8bit */

#define DIVIDER ((int)(FOSC/(16UL * BAUD) -1))
#define HIGH_SPEED 1

#if NINE == 1
#define NINE_BITS 0x40
#else
#define NINE_BITS 0
#endif

#if HIGH_SPEED == 1
#define SPEED 0x4
#else
#define SPEED 0
#endif

#define RX_PIN TRISC7
#define TX_PIN TRISC6
       
/* Serial initialization */
#define INIT_COMMS()\
        RX_PIN = 1;        \
        TX_PIN = 1;                  \
        SPBRG = DIVIDER;             \
        RCSTA = (NINE_BITS|0x90);        \
        TXSTA = (SPEED|NINE_BITS|0x20)

#ifndef NOP()
#define NOP()        asm("nop")
#endif

#ifndef RESET()
#define RESET()        asm("ljmp 0")
#endif

/* expressions used in the code */
#define FLASH EEPGD==1
#define EEPROM EEPGD==0
#ifdef IRREG_START
#define LOADER_SAFE ((EEPROM) || (EEADRH < (BOOT_START >> 8)) || ((EEADRH == (BOOT_START >> 8)) && (EEADR < (BOOT_START & 0xFF))) )
#else
#define LOADER_SAFE ((EEPROM)||(EEADRH < (BOOT_START >> 8)))
#endif

#define OK_BIT 0x80

/* stop & start controls for HyperTerminal */
#define XON        17
#define XOFF        19

#endif
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-5 17:35

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表