⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bootldr.c

📁 picc_18v 8.35pl35 PIC18系列单片机开发C编译器
💻 C
字号:
/*
 * 18Fxxx BOOT LOADER Copyright (C) 2002 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.
 *	
 */
#pragma psect text=bootldr 
#include <pic18.h>
#include "bootldr.h"

#if defined(MPLAB_ICD)
__CONFIG(4,DEBUGEN & LVPDIS);	// required ICD2 settings
__CONFIG(6,UNPROTECT);		// enable writing to flash
#else
__CONFIG(6,WPB & UNPROTECT);	// bootloader self protection
#endif

#if defined(ERRATA_4000_BOUNDARY)
#error Command line option -NOERRATA must be specified when compiling this code for this device.
#endif

/* Function prototypes */
void checksum(void);
void putch(unsigned char);
void puts(const char *s);
unsigned char gx(void);
unsigned char g2x(void);
void zap(void);
void table_write(void);
void flash8(void);
void clear_buffer(void);

persistent near unsigned char buff[8];	/* 8 byte buffer used for writing to program memory */
persistent near unsigned char DO_NOT_INCREMENT;
persistent near unsigned char cksum,rectype,bcount;
persistent near unsigned char delay_time;
persistent near unsigned char index;
persistent near unsigned short erase;

#ifdef VERBOSE
persistent near unsigned char START_MSG[] = "HI-TECH Software (C)2002\n";
persistent near unsigned char DOWNLOAD_MSG[] = "\rDownload-";
#endif

#asm

psect intcode	// redirect interrupts to new routine addresses
	goto	PROG_START+8
	
#ifndef VERBOSE
/* Sqeeze the checksum function in between the ISR redirection
 * instructions for even tighter code!
 * Will not fit if VERBOSE mode is enabled, in which case
 * the C version will be used. */
global _checksum
_checksum:
	call	_g2x		// read the checksum byte
	movf	_cksum,w,c
	btfss	status,2,c	// if it doesn't add up...
	reset			// reset
	return
#endif
	
psect intcodelo	// redirect low priority interrupts to new routine addresses
	goto	PROG_START+0x18

#endasm

/* putch() - outputs 1 byte to the serial port */
#ifdef VERBOSE
void
putch(unsigned char byte){
	while(!TRMT);	/* 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++);	
}

/* check the checksum 
 * NOTE: if not in verbose mode, the code will use the even more compact
 * assembler version of the checksum() function defined above.
 */

void
checksum(void){
	g2x();
	if(cksum)	// if checksum does not add to zero, bad check, reset
		RESET();
	putch('\r');	// echo each hex record on a new line
}
	
#endif

/* Get a 4 bit HEX number from the serial port */
unsigned char
gx(void){
	while(!RCIF);
	EEDATA=RCREG;
#ifdef VERBOSE
	if(!TRMT)		// Echo RX nibbles to output. If high speed RX, some 
		TXREG=EEDATA;	// nibbles mightn't be TXed but will still be programmed.
#endif
	if(EEDATA>='A')
		return ((EEDATA - (unsigned char)'A')+10);
	return (EEDATA - '0');
}

/* recieve a hexadecimal byte, add it to the checksum */
unsigned char g2x(void)
{
	unsigned char temp = (gx()<<4);
	temp += gx();
	cksum+=temp;
	return temp;
}

/* Initiate a write to memory */
void
zap(void){
	WREN=1;
	EECON2=0x55;
	EECON2=0xAA;
	WR=1;
	NOP();
	while(WR);
	WREN=0;
}

/* transfer a byte from RAM to internal flash register(s) */
void
table_write(void){
	if(DO_NOT_INCREMENT)	// address is already loaded in TBLPTR, no pre-increment needed
		asm("tblwt*");
	else
		asm("tblwt+*");	// otherwise TBLPTR must be pre-incremented
	DO_NOT_INCREMENT=0;
}

/* write the 8 byte buffer to flash */
void
flash8(void){
	if(DO_NOT_INCREMENT)
		TBLPTRL&=0xF8;	// point to start of 8 byte panel
	for(index=0;index<8;)
	{	
		TABLAT = buff[index++];
		table_write();
	}
	zap();
}

void
clear_buffer(void){
	buff[0] = buff[1] = buff[2] = FILL_BYTE;	// 8 byte buffer initialised with	
	buff[3] = buff[4] = buff[5] = FILL_BYTE;	// known data
	buff[6] = buff[7] = FILL_BYTE;
}


void
main(void){
#if defined(_18F242) || defined(_18F252) || defined(_18F442) || defined(_18F452)
	PIE1=0;	// as per the errata document for these parts
#endif

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

/* 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);
#else
	TXREG='\n';
#endif

	// Some devices' errata require these registers to be cleared
	INTCON3=0;	// Also serves to disable interrupts
	PIE2=0;
	INTCON=0;

	T0CON = 0x94;	// use timer to give ~1 second delays
	for(delay_time=BOOT_TIMEOUT; delay_time ; --delay_time)
	{
		if (RCIF)
			break;
#ifdef VERBOSE	/* display a countdown for user response */
		puts(DOWNLOAD_MSG);
		putch('0'+delay_time);
#else
		TXREG=('0'+delay_time);
		while(!TRMT);
		TXREG='\r';
#endif
		while(!TMR0IF);	// pause for timer 0 timeout
		TMR0IF=0;
	}
	T0CON=0xFF;	// disable timer again

	if (!RCIF)	/* if no hex file to download, resume normal program */
	{
		(*((void(*)(void))PROG_START))();
	}

	TXREG=':';	// the prompt to invite you to download a new program

	TBLPTRU=0;
	erase=PROG_START;
	/* Clear program memory prior to program download */
	while(1)
	{
		TBLPTRL=(unsigned char)erase;
		TBLPTRH=(unsigned char)(erase>>8);
		EECON1=0x90;	// set up for flash erasure
		zap();
		erase+=64;
#ifdef UPPER_ADDRESS_BYTE
		if(CARRY)
			TBLPTRU++;
		if(TBLPTRU==UPPER_ADDRESS_BYTE)
#endif
		if(erase==MEM_TOP)
			break;
	}

#ifdef UPPER_ADDRESS_BYTE
	TBLPTRU=0;
#endif
/* 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 file line 
#ifdef VERBOSE
		putch(':');
#endif		
		cksum = bcount = g2x();		// get the byte count 
#if EEPROM_SIZE > 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:	// data 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 address range is threatened, skip this record
#endif
			clear_buffer();
				while(bcount--)
				{	
					TABLAT = EEDATA = buff[(EEADR&7)] = g2x();	// get the data

					if((CONFIG)||(EEPROM))
					{
						if(CONFIG)	// EEPROM/config. bytes are written one byte at a time
							table_write();
						zap();
					}
					else
						if((EEADR&7)==7)	// program/IDLOCs are flashed 8 bytes at a time
						{
							flash8();
							clear_buffer();
						}
					EEADR++;
				}	
				if(((EEADR&7)!=0)&&(FLASH))
                                        flash8();

				checksum();
				break;

			case END:	// end of hex file
				checksum();
				TXREG=')';
				(*((void(*)(void))PROG_START))(); // jump to new program 
				break;

			case EXTEND_ADDRESS:	// extended address record
				while(bcount--)
				{
					EEADR=g2x();	// this byte determines whether EE, Config or ID data
				}
				
				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;
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -