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

📄 prog.c

📁 M68HC08及HCS08系列单片机bootloader引导程序源码/示例
💻 C
📖 第 1 页 / 共 2 页
字号:
/**********************************************************************
* HEADER_START                                                        *
*                                                                     *
*      Name:           PROG.C                                         *
*      Project:        Developper's HC08 Bootloader Master            *
*      Description:    Main programming routines file                 *
*      Platform:       Linux/Win32                                    *
*      Revision:       1.0                                            *
*      Date:           Apr 8 2002                                     *
*      Author:         Michal Hanak                                   *
*      Company:        Freescale                                      *
*      Security:       General Business                               *
*                                                                     *
* =================================================================== *
* Copyright (c):       FREESCALE Inc., 2004, All rights reserved.     *
*                                                                     *
* =================================================================== *
* THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY              *
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE *
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR  *
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL FREESCALE OR             *
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,    *
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT        *
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;        *
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)            *
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, *
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)       *
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED *
* OF THE POSSIBILITY OF SUCH DAMAGE.                                  *
* =================================================================== *
*
* HEADER_END
*/

#include "sysdep.h"
#include "hc08sprg.h"
#include "serial.h"

/////////////////////////////////////////////////
// bootloader commands

#define WR_DATA		'W'
#define RD_DATA		'R'
#define IDENT		'I'
#define QUIT		'Q'
#define ERASE		'E'
#define ACK			0xFC

char *SDID[MAX_SDID]=
{
	"MC9S08CT16",						//0  (never released, experimental only)
	"unknown",							//1
	"MC9S08(GB/GT)(32-60),MC1321x",		//2
	"MC9S08(RC/RD/RE)(8/16)",			//3
	"MC9S08(RC/RD/RE/RG)(32-60)",		//4
	"unknown",							//5
	"MC3S08RX32",						//6
	"MC3S08RE16",						//7
	"MC9S08AW(16-60)",					//8
	"MC9S08QG(4/8)",					//9
	"MC9S08JR12",						//10 (0x0A)
	"unknown",							//11 (0x0B)
	"MC9S08LC(36-60)",					//12 (0x0C)
	"unknown",							//13 (0x0D)
	"MC9S08(DE/DN/DZ/DV/EN)(16-60)",	//14 (0x0E)
	"unknown",							//15 (0x0F)
	"MC9S08RA16",						//16 (0x10)
	"MC9S08QD(4/8)",					//17 (0x11)
	"unknown",							//18 (0x12)
	"MC9S08(EL/SL)(8/16/32)",			//19 (0x13)
	"MC9S08(SG/SH)(4/8)",				//20 (0x14)
	"MC9S08QE(64/96/128)",				//21 (0x15)
	"MC9S08JM(16-60)",					//22 (0x16)
	"unknown",							//23 (0x17)
	"unknown",							//24 (0x18)
	"MC9S08(DZ/DV)(96/128)",			//25 (0x19)
	"MC9S08(SG/SH)(16/32)",				//26 (0x1A)
	"unknown",							//27 (0x1B)
	"unknown",							//28 (0x1C)
	"unknown",							//29 (0x1D)
	"unknown",							//30 (0x1E)
	"unknown",							//31 (0x1F)
};

char SDID2blver[MAX_SDID]=
{
	BL_HCS08,			//0  	"MC9S08CT16",						//0  (never released, experimental only))
	BL_UNKNOWN,			//1		"unknown",							//1
	BL_HCS08,			//2		"MC9S08(GB/GT)(32-60),MC1321x",		//2
	BL_HCS08,			//3		"MC9S08(RC/RD/RE)(8/16)",			//3
	BL_HCS08,			//4		"MC9S08(RC/RD/RE/RG)(32-60)",		//4
	BL_UNKNOWN,			//5		"unknown",							//5
	BL_HCS08,			//6		"MC3S08RX32",						//6
	BL_HCS08,			//7		"MC3S08RE16",						//7
	BL_HCS08,			//8		"MC9S08AW(16-60)",					//8
	BL_HCS08,			//9		"MC9S08QG(4/8)",					//9
	BL_HCS08,			//10 	"MC9S08JR12",						//10 (0x0A)
	BL_UNKNOWN,			//11 	"unknown",							//11 (0x0B)
	BL_HCS08,			//12 	"MC9S08LC(36-60)",					//12 (0x0C)
	BL_UNKNOWN,			//13 	"unknown",							//13 (0x0D)
	BL_HCS08_LONG,		//14 	"MC9S08(DE/DN/DZ/DV/EN)(16-60)",	//14 (0x0E)
	BL_UNKNOWN,			//15 	"unknown",							//15 (0x0F)
	BL_HCS08,			//16 	"MC9S08RA16",						//16 (0x10)
	BL_HCS08,			//17 	"MC9S08QD(4/8)",					//17 (0x11)
	BL_UNKNOWN,			//18 	"unknown",							//18 (0x12)
	BL_HCS08_LONG,		//19 	"MC9S08(EL/SL)(8/16/32)",			//19 (0x13)
	BL_HCS08,			//20 	"MC9S08(SG/SH)(4/8)",				//20 (0x14)
	BL_HCS08_LARGE,		//21 	"MC9S08QE(64/96/128)",				//21 (0x15)
	BL_HCS08,			//22 	"MC9S08JM(16-60)",					//22 (0x16)
	BL_UNKNOWN,			//23 	"unknown",							//23 (0x17)
	BL_UNKNOWN,			//24 	"unknown",							//24 (0x18)
	BL_HCS08_LONG,		//25 	"MC9S08(DZ/DV)(96/128)",			//25 (0x19)
	BL_HCS08,			//26 	"MC9S08(SG/SH)(16/32)",				//26 (0x1A)
	BL_UNKNOWN,			//27 	"unknown",							//27 (0x1B)
	BL_UNKNOWN,			//28 	"unknown",							//28 (0x1C)
	BL_UNKNOWN,			//29 	"unknown",							//29 (0x1D)
	BL_UNKNOWN,			//30 	"unknown",							//30 (0x1E)
	BL_UNKNOWN			//31 	"unknown",							//31 (0x1F)
};

/////////////////////////////////////////////////////////////////
// helper compare of unsigned 

static unsigned umin(unsigned a, unsigned b)
{
	return a < b ? a : b;
}

//////////////////////////////////////////////////////////////////
// helper read 16 bit number
// return -1=error; 0=rd timeout; 2=success (2 bytes read)

static int r16(unsigned* n)
{
	int ret;
	BYTE b[2];

	// we need 2 bytes (otherwise return -1 or 0)
	if((ret=rb(b, 2)) != 2)	
		return ret < 0 ? ret : 0;

	// first was HI, then LO
	*n = b[0] << 8;
	*n += b[1];
	return 2;
}

/////////////////////////////////////////////////////////////////////
// helper write 16 bit number
// return -1=error; 0=wr timeout; 2=success (2 bytes written)

static int w16(unsigned n)
{
	int ret;
	BYTE b[2];

	b[0] = (BYTE) ((n & 0xff00) >> 8);
	b[1] = (BYTE) (n & 0xff);
	if((ret=wb(b, 2)) != 2) 
		return ret < 0 ? -1 : 0;

	return 2;
}


//////////////////////////////////////////////////////////////////
// helper read 24 bit number
// return -1=error; 0=rd timeout; 3=success (3 bytes read)

static int r24(unsigned long* n)
{
	int ret;
	BYTE b[3];

	// we need 3 bytes (otherwise return -1 or 0)
	if((ret=rb(b, 3)) != 3)	
		return ret < 0 ? ret : 0;

	// first was HI, then LO
	*n =  b[0] << 16;
	*n += b[1] << 8;
	*n += b[2];
	return 3;
}

/////////////////////////////////////////////////////////////////////
// helper write 24 bit number
// return -1=error; 0=wr timeout; 3=success (3 bytes written)

static int w24(unsigned long n)
{
	int ret;
	BYTE b[3];

	b[0] = (BYTE) ((n & 0xff0000) >> 16);
	b[1] = (BYTE) ((n & 0xff00) >> 8);
	b[2] = (BYTE) (n & 0xff);
	if((ret=wb(b, 3)) != 3) 
		return ret < 0 ? -1 : 0;

	return 3;
}

//////////////////////////////////////////////////////////////
// wait for hc08 reset

// target send us ACK (0xfc) but in this time, it might be off-key up to factor 3
// so we might receive FF, FE, FC, F8, ..., 80, 0

static int could_be_ack(unsigned b)
{
	b |= 0xff00;
	while(!(b&1))
		b = b >> 1;

	return (b & 0xff) == 0xff ? 1 : 0;
}

int hook_reset(void)
{
	int ret;
	BYTE d;

	printf("Waiting for HC(S)08 reset ACK...");
	fflush(stdout);

	// ignore timeouts
	while((ret=rb(&d, 1)) >= 0)
	{
		if(ret > 0)
		{
			printf("received 0x%02x ", d);
			if(could_be_ack(d))
			{
				if(d == ACK) printf("(good).\n");
				else printf("(off-key).\n");
				break;
			}
			else
			{
				printf("(ignoring).\n");
			}
		}
	}

	if(ret < 0)
	{
		printf("\n");
		fprintf(stderr, "Error receiving reset ACK.\n");
		return -1;		 
	}

	// enter interactive mode
	if(wb(&d, 1) <= 0)
	{
		fprintf(stderr, "Error sending locking ACK.\n");
		return -1;		 
	}

	// wait for finish
	flush_uart(FDRAIN, 0);

	// success
	return 1;
}

///////////////////////////////////////////////////////////////
// send breaks to calibrate target's oscillator

int calibrate_speed(void)
{
	BYTE b;
	int ret, cnt=0;

	for(;;)
	{
		// wait for ACK or timeout
		ret = rb(&b, 1);
		// read error
		if(ret < 0)
		{
			if(cnt) printf("\n");
			fprintf(stderr, "Error receiving calibrate ACK.\n");
			return -1;
		}
		// got something
		else if(ret > 0)
		{
			// it is wrong to receive anything other than ACK
			if(b != ACK)
			{
				if(cnt) printf("\n");
				fprintf(stderr, "Wrong calibrate response (0x%02x, must be 0x%02x). Target is not calibrated.\n", b, ACK);
				return -1;
			}
			// OK, exit calibration loop
			break;
		}
		
		// rx timeout ! send 1.04ms break pulse (again)
		if(send_break10() < 0) 
		{
			if(cnt) printf("\n");
			fprintf(stderr, "Can't send break pulse.\n");
			return -1;
		}

		// another break sent
		printf("\rCalibration break pulse sent. Count: %d ", ++cnt);
		fflush(stdout);
	};

	if(cnt) printf("\n");
	// success (got ACK)
	return 1;
}


///////////////////////////////////////////////////////////////
// simple return-on-error macros

#define R8(var)		{if(rb(var, 1) != 1) return -1;}
#define R16(var)	{if(r16(var) <= 0) return -1;}
#define R24(var)	{if(r24(var) <= 0) return -1;}
#define W8(n)		{ BYTE _x=n; if(wb(&_x, 1) != 1) return -1; }
#define W16(n)		{if(w16(n) <= 0) return -1;}
#define W24(n)		{if(w24(n) <= 0) return -1;}
//////////////////////////////////////////////////////////////
// get basic info about target board

int read_mcu_info(void)
{
	BYTE d;
	unsigned i;

	// initialize memory space
	memset(&ident, 0, sizeof(ident));

	// issue command
	flush_uart(FDISCARD, FDISCARD);
	W8(IDENT);

	// first byte is protocol version
	R8(&d); 
	bl_version = (int) (d & 0x0F);
	bl_rcs = (((int)d & 0x80) != 0);

	if(bl_version == BL_HC08)
	{
		// read identification structure for version 1 (HC08)
		ident.num_blocks = 1;
		R16(&ident.mem_start[0]);
		R16(&ident.mem_end[0]);
		R16(&ident.bl_tbl);
		R16(&ident.int_vect_tbl);
		R16(&ident.erblk);
		R16(&ident.wrblk);
		// read private data
		if(rb(&ident.priv_data, sizeof(ident.priv_data)) != sizeof(ident.priv_data))
			return -1;
	} 
	else if((bl_version == BL_HCS08) 
		 || (bl_version == BL_HC08_LARGE) 
		 || (bl_version == BL_HCS08_LONG) 
		 || (bl_version == BL_HCS08_LARGE))
	{
		unsigned i, sdidh, sdidl;
		// read identification structure for version 2 (HCS08), 3 (large HC08), 6 (HCS08 with "non-binary" Erase/Write size)
		// 10 (HCS08 with >64kB memory), 12 (long HCS08)
		R8(&sdidh);
		R8(&sdidl);
		ident.sdid = ((sdidh & 0x0F) << 8) | (sdidl & 0xFF);
		ident.sdidrev = ((sdidh & 0xF0) >> 4);
		R8(&ident.num_blocks);
		if ((ident.num_blocks > MAX_NUM_BLOCKS) || (ident.num_blocks == 0))
			return -1;
		for(i=0; i<ident.num_blocks; i++)
		{
			if((bl_version == BL_HCS08_LARGE) || (bl_version == BL_HCS08_LONG))	// versions 10 + 12 (HCS08 with >64kB memory) is 24-bit address here
			{
				R24(&ident.mem_start[i]);
				R24(&ident.mem_end[i]);
			}
			else
			{
				R16(&ident.mem_start[i]);
				R16(&ident.mem_end[i]);
			}
		}
		R16(&ident.bl_tbl);
		R16(&ident.int_vect_tbl);
		R16(&ident.erblk);
		R16(&ident.wrblk);

		if (bl_version != BL_HC08_LARGE)	// check only S08 families, not HC08
		{
			if(ident.sdid >= MAX_SDID)
			{	
				fprintf(stderr, "\nERROR! The SDID of the device [0x%03X] is too high and not (yet) supported! Check AN2295SW for update!\n", ident.sdid);
				return -1;
			}
			else
			{
				chipid = SDID[ident.sdid];
				if (SDID2blver[ident.sdid] == BL_UNKNOWN)
				{
					fprintf(stderr, "\nWARNING! The SDID of the device [0x%03X] is not (yet) supported! Check AN2295SW for update!\n", ident.sdid);
				}
				else
				{
					if (SDID2blver[ident.sdid] != bl_version)
						fprintf(stderr, "\nWARNING! The protocol version [0x%02X] does not match the one associated\n"
										  "with the device with following SDID [0x%03X].\n"
										  "Continuing with reported protocol version anyway.\n\n"
										  "Something is screwed up, please report!\n", bl_version, ident.sdid);
				}
			}
		}
	}
	else
		return -1;


	// read string
	i = 0;
	// read all name characters
	do
	{
		R8(&d);

		// but store up to our buffer len chars only
		if(i < sizeof(ident.targ_name)-1)
			ident.targ_name[i++] = d;

	// zero terminated

⌨️ 快捷键说明

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