📄 prog.c
字号:
/**********************************************************************
* 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 + -