📄 prog.c
字号:
} while(d);
return 0;
}
//////////////////////////////////////////////////////////////
// read memory block, return number of bytes read or -1
int read_blk(unsigned a, int len, BYTE *dest)
{
if(len < 0 || len >= MAX_LENGTH || a >= MAX_ADDRESS)
return -1;
// issue command
flush_uart(FDISCARD, FDISCARD);
W8(RD_DATA);
// and parameters
if ((bl_version == BL_HCS08_LARGE) || (bl_version == BL_HCS08_LONG)) W24(a) else W16(a);
W8(len);
// block read
if(rb(dest, len) != len)
return -1;
// return number of bytes read (==requested)
return len;
}
//////////////////////////////////////////////////////////////
// masquerade vector table (work on memory image)
// the trick is to move any vector values from S19 file to
// special jump table located at ident.app_vect_tbl
int setup_vect_tbl(void)
{
unsigned src, dest;
int any_hit = 0;
if((bl_version == BL_HC08) || (bl_version == BL_HC08_LARGE))
{
// start of jump table
dest = ident.bl_tbl;
// we store private data first
memcpy(&image.d[dest], ident.priv_data, sizeof(ident.priv_data));
dest += sizeof(ident.priv_data);
// and jump-table next
for(src = 0xfffe; src >= ident.int_vect_tbl; src -= 2)
{
image.d[dest++] = 0xcc; // jump instruction
image.d[dest++] = image.d[src];
image.d[dest++] = image.d[src+1];
// is the vector valid ?
if(image.f[src] && image.f[src+1])
any_hit = 1;
// original vector (from s19 image) is no longer valid
image.f[src] = 0;
image.f[src+1] = 0;
}
}
else if ((bl_version == BL_HCS08) || (bl_version == BL_HCS08_LONG))
{
// start of jump table
dest = ident.bl_tbl;
// private data not stored (YET)
// and jump-table next
for(src = ident.int_vect_tbl; src <= 0xfffe ; src += 2)
{
image.d[dest++] = image.d[src];
image.d[dest++] = image.d[src+1];
// is the vector valid ?
if(image.f[src] && image.f[src+1])
any_hit = 1;
// original vector (from s19 image) is no longer valid
image.f[src] = 0;
image.f[src+1] = 0;
}
}
else if (bl_version == BL_HCS08_LARGE) //at least QE family does not support the redirection, so use 'old' style
{
// start of jump table
dest = ident.bl_tbl;
// and jump-table next
for(src = 0xfffe; src >= ident.int_vect_tbl; src -= 2)
{
image.d[dest++] = 0xcc; // jump instruction
image.d[dest++] = image.d[src];
image.d[dest++] = image.d[src+1];
// is the vector valid ?
if(image.f[src] && image.f[src+1])
any_hit = 1;
// original vector (from s19 image) is no longer valid
image.f[src] = 0;
image.f[src+1] = 0;
}
}
// write the whole system area, but only if at least one vector was valid in the S19
if(any_hit)
memset(&image.f[ident.bl_tbl], 2, dest - ident.bl_tbl);
return 0;
}
//////////////////////////////////////////////////////////////
// erase single block around given address
int erase_blk(unsigned /*long */a)
{
int ret;
BYTE d;
DBG1("\nerase_blk: 0x%06x\n", a);
if(a >= MAX_ADDRESS)
return -1;
// issue command
flush_uart(FDISCARD, FDISCARD);
W8(ERASE);
// and parameter
if ((bl_version == BL_HCS08_LARGE) || (bl_version == BL_HCS08_LONG)) W24(a) else W16(a);
// wait for ack
while((ret = rb(&d, 1)) == 0)
; // do nothing
// it must be ACK character
if(ret > 0 && d != ACK)
ret = -1;
// either -1 or 1
return ret;
}
//////////////////////////////////////////////////////////////
// program single block
int prg_blk(unsigned long a, int len)
{
int ret;
BYTE d;
DBG2("\nprg_blk: 0x%06x-0x%06x\n", a, a+len-1);
if(len < 0 || len >= MAX_LENGTH || a >= MAX_ADDRESS)
return -1;
// issue command
flush_uart(FDISCARD, FDISCARD);
W8(WR_DATA);
// and parameters
if ((bl_version == BL_HCS08_LARGE) || (bl_version == BL_HCS08_LONG)) W24(a) else W16(a);
W8(len);
if(wb(&image.d[a], len) != len)
return -1;
// wait for ack
while((ret = rb(&d, 1)) == 0)
; // do nothing
// must be ACK character
if(ret > 0 && d != ACK)
ret = -1;
// either -1 or 1
return ret;
}
//////////////////////////////////////////////////////////////
// program one continuous area and give user a progess
static int prg_area(unsigned long start, unsigned long end)
{
unsigned long i, er, wr, er_next, wr_end, wr_next;
unsigned long wr_one, written=0, total=0;
DBG2("prg_area: 0x%06x-0x%06x\n", start, end);
if(start >= MAX_ADDRESS || end >= MAX_ADDRESS)
return -1;
// count valid bytes
for(i=start; i<end; i++)
if(image.f[i]) total++;
#define FLASHMODULO(x,y) ((unsigned long)(MAX_ADDRESS - (y) *(1 + ((MAX_ADDRESS-(unsigned long)((x)+(y))-1) / (y)))))
// take start address as it is, but do further steps to erblk boundaries
for(er=start; er<end; er=er_next)
{
// start of next erase block
er_next = FLASHMODULO(er,ident.erblk);
// anything to program in this erase block ?
wr = wr_end = er;
for(i=er; i<er_next; i++)
{
// valid byte
if(image.f[i])
{
if(!image.f[wr]) wr = i;
wr_end = i+1;
}
}
// never pass after end
if(wr_end > end)
wr_end = end;
// wr is now pointing to first valid byte (within current erase block)
// wr_end is now pointing after last valid byte (within current erase block)
if(wr < wr_end)
{
if ((bl_version == BL_HCS08_LARGE) || (bl_version == BL_HCS08_LONG))
printf("\rMemory programming: E 0x%06X %d%%", wr, 100*written/total);
else
printf("\rMemory programming: E 0x%04X %d%%", wr, 100*written/total);
fflush(stdout); DBG("\n");
// use the first valid-byte address
if(erase_blk(wr) < 0)
{
printf("\n");
if ((bl_version == BL_HCS08_LARGE) || (bl_version == BL_HCS08_LONG))
fprintf(stderr, "Can't erase block at address 0x%06X\n", wr);
else
fprintf(stderr, "Can't erase block at address 0x%04X\n", wr);
return -1;
}
for(/* original wr */; wr<wr_end; wr=wr_next)
{
// start of next write block
wr_next = FLASHMODULO(wr,ident.wrblk);
if ((bl_version == BL_HCS08_LARGE) || (bl_version == BL_HCS08_LONG))
printf("\rMemory programming: W 0x%06X %d%%", wr, 100*written/total);
else
printf("\rMemory programming: W 0x%04X %d%%", wr, 100*written/total);
fflush(stdout); DBG("\n");
wr_one = umin(wr_end, wr_next)-wr;
if(prg_blk(wr, wr_one) < 0)
{
printf("\n");
if ((bl_version == BL_HCS08_LARGE) || (bl_version == BL_HCS08_LONG))
fprintf(stderr, "Can't program block at address 0x%06X\n", wr);
else
fprintf(stderr, "Can't program block at address 0x%04X\n", wr);
return -1;
}
if((bl_rcs) && (verify)) // read command implemented!
{
unsigned char rbuff[256];
unsigned int adr;
if ((bl_version == BL_HCS08_LARGE) || (bl_version == BL_HCS08_LONG))
printf("\rMemory reading: R 0x%06X %d%%", wr, 100*written/total);
else
printf("\rMemory reading: R 0x%04X %d%%", wr, 100*written/total);
fflush(stdout); DBG("\n");
if (read_blk(wr, wr_one, rbuff) <0)
{
printf("\n");
if ((bl_version == BL_HCS08_LARGE) || (bl_version == BL_HCS08_LONG))
fprintf(stderr, "Can't read block at address 0x%06X\n", wr);
else
fprintf(stderr, "Can't read block at address 0x%04X\n", wr);
return -1;
}
for(adr = wr; adr < wr+wr_one; adr++)
{
if (image.d[adr] != rbuff[adr-wr])
{
if ((bl_version == BL_HCS08_LARGE) || (bl_version == BL_HCS08_LONG))
fprintf(stderr, "\nVerification failed at address 0x%06X, image: [0x%02X], MCU: [0x%02X]\n", adr, image.d[adr], rbuff[adr-wr]);
else
fprintf(stderr, "\nVerification failed at address 0x%04X, image: [0x%02X], MCU: [0x%02X]\n", adr, image.d[adr], rbuff[adr-wr]);
return -1;
}
}
}
// the percentage-counting algorithm is not perfect, in some cases there might
// be more than 100% achieved (if S19 file has holes within erblks = rare case)
if((written += wr_one) > total)
written = total;
}
}
}
return 0;
}
//////////////////////////////////////////////////////////////
// program all
int prg_mem(void)
{
unsigned s,e;
// find first and last valid byte
for(s=0; s<MAX_ADDRESS; s++)
if(image.f[s]) break;
for(e=MAX_ADDRESS; e>s; e--)
if(image.f[e-1]) break;
if(prg_area(s, e) < 0)
return -1;
if ((bl_version == BL_HCS08_LARGE) || (bl_version == BL_HCS08_LONG))
{
printf("\rMemory programmed: 100%%\n");
if((bl_rcs) && (verify))
printf("\rMemory verified: OK\n");
}
else
{
printf("\rMemory programmed: 100%%\n");
if((bl_rcs) && (verify))
printf("\rMemory verified: OK\n");
}
return 0;
}
//////////////////////////////////////////////////////////////
// print ID$, only printable char, max. 255 chars
void cleanprint(char * str)
{
int cnt = 255;
while(*str && cnt--)
{
if (isprint(*str))
putchar(*str);
else
putchar('.');
str++;
}
}
//////////////////////////////////////////////////////////////
// check if code goes to valid memory only
int check_image()
{
unsigned a, i, f;
unsigned s,e;
char* scannm;
char id;
// find first and last valid byte
for(s=0; s<MAX_ADDRESS; s++)
if(image.f[s]) break;
for(e=MAX_ADDRESS; e>s; e--)
if(image.f[e-1]) break;
// skip COM if specified and scan number and mode (optional)
id = strnicmp(image.d+s, "ID$:", 4);
if (id == 0)
{
scannm = image.d+s+4; /* string ptr. after ID$ */
printf("\r\nMCU software version: ");
cleanprint(scannm);
putchar('\n');
}
//sscanf(scannm, "%i%c%c", &portNum, &modemode, &serial_mode);
for(a=0; a<MAX_ADDRESS; a++)
{
if(image.f[a]==1)
{
f = 0;
for(i=0; i<ident.num_blocks; i++)
{
if ((a>=ident.mem_start[i]) && (a<ident.mem_end[i]))
{
f = 1;
break;
}
}
if(f == 0)
goto err_hit; //location at address a won't fit any memory block!
}
}
// no error
return 0;
err_hit:
if ((bl_version == BL_HCS08_LARGE) || (bl_version == BL_HCS08_LONG))
fprintf(stderr, "\nWARNING! S19 image will not fit into available memory (at address 0x%06X)!\n", a);
else
fprintf(stderr, "\nWARNING! S19 image will not fit into available memory (at address 0x%04X)!\n", a);
return -1;
}
//////////////////////////////////////////////////////////////
// exit program mode, start application
int unhook(void)
{
W8(QUIT);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -