📄 dl_srec.c
字号:
/*
* File: dl_srec.c
* Purpose: Routines to download Motorola S-Records via serial port.
*
* Notes: Implements Xon/Xoff software handshaking
*
*/
#include "src/include/dbug.h"
#include "src/uif/uif.h"
/********************************************************************/
#define CHAR_WAIT_TIMEOUT 2000
uint8 overflow[60];
int ovchars;
int ovindex;
/********************************************************************/
static uint8
dl_getchar(void)
{
uint8 rval;
if (ovchars)
{
rval = overflow[ovindex++];
if (!--ovchars)
{
/* Send Xon character */
board_putchar(XON);
ovindex = 0;
}
return rval;
}
else
{
return board_getchar();
}
}
/********************************************************************/
static uint8
dl_gethexvalue (uint8 uint8)
{
switch (uint8)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return (uint8 - '0');
break;
case 'A':
case 'a':
return 10;
break;
case 'B':
case 'b':
return 11;
break;
case 'C':
case 'c':
return 12;
break;
case 'D':
case 'd':
return 13;
break;
case 'E':
case 'e':
return 14;
break;
case 'F':
case 'f':
return 15;
break;
default:
return 0;
}
}
/********************************************************************/
static uint8
dl_getS (void)
{
/*
* This routine skips all characters until an `S' is received.
* It then returns the next character.
* This routine is here in order to not echo characters back
* out as they are received during a download.
*
* This code ignores NL,CR-LF end of line issues by waiting
* for 'S'.
*/
uint8 c;
while (TRUE)
{
c = dl_getchar();
if (c == 'S')
break;
}
/* Get type of S-record */
return dl_getchar();
}
/********************************************************************/
static uint8
dl_getSpair (void)
{
uint8 ch;
uint8 upper;
ch = dl_getchar();
upper = (uint8)(dl_gethexvalue(ch) << 4);
ch = dl_getchar();
return (upper | dl_gethexvalue(ch));
}
/********************************************************************/
int
dl_download_srec (int offset_to_addr)
{
int checksum, i, index, done, timeout, type;
uint8 data, length, hash[5];
int hashi = 1, hashj = 0;
ADDRESS address = 0;
unsigned char buffer[150];
hash[0]=8; /* Backspace */
hash[1]=124;/* "|" */
hash[2]=47; /* "/" */
hash[3]=45; /* "-" */
hash[4]=92; /* "\" */
done = FALSE;
ovchars = 0;
/* Send Xon character */
board_putchar(XON);
while (!done)
{
/* Get start of S-record */
type = dl_getS();
/* Get record length */
length = dl_getSpair();
checksum = length;
/* Take appropriate action */
switch (type)
{
case '1':
case '2':
case '3':
timeout = 0;
address = NULL;
type -= '0';
for (i = 0; i <= type ; i++)
{
/* Formulate address */
data = dl_getSpair();
address = (address << 8) | data;
/* Maintain 8-bit checksum */
checksum = (data + checksum) & 0x00FF;
length--;
}
/* Adjust for user specified offset */
address = (ADDRESS)((int)address + offset_to_addr);
if ((index = flash_dlio_vda((ADDRESS)address)) != 0)
{
/* Get data and put into buffer */
for (i = 0; i < (length - 1); i++)
{
buffer[i] = dl_getSpair();
}
/* Get checksum byte */
data = dl_getSpair();
/* Send Xoff character */
board_putchar(XOFF);
/* Catch the overflow */
while (timeout++ < CHAR_WAIT_TIMEOUT)
{
if (board_getchar_present())
{
overflow[ovchars++] = board_getchar();
timeout = 0;
}
}
/* Write buffered data to Flash */
flash_program((ADDRESS)address,(ADDRESS)buffer,
i, index, FALSE, FALSE);
/* Calculate checksum */
for (i = 0; i < (length - 1); i++)
{
checksum = (*(uint8 *)address + checksum) & 0x00FF;
++address;
}
if (((data - ~checksum) & 0x00FF) != 0)
{
printf("\bError: S-record checksum error!\n");
printf("Expected: %2X, Received: %2X\n",
data,checksum);
printf("Address: %8X\n",address);
}
/* Send Xon if no overflow occured */
if (!ovchars)
board_putchar(XON);
}
else if (board_dlio_vda((ADDRESS)address))
{
/* Get data and put into memory */
for (i = 0; i < (length -1); i++)
{
data = dl_getSpair();
*(uint8 *)address = (uint8)data;
/* Checksum is computed from data written to RAM */
checksum = (*(uint8 *)address + checksum) & 0x00FF;
++address;
}
/* Get checksum byte */
data = dl_getSpair();
if (((data - ~checksum) & 0x00FF) != 0)
{
printf("\bError: S-record checksum error!\n");
printf("Expected: %2X, Received: %2X\n",
data,checksum);
return FALSE;
}
}
else
{
printf("\bInvalid download address: %#08X\n",address);
return FALSE;
}
/*
* Hash marks to indicate progress
*/
if (++hashj == 10)
{
board_putchar(hash[0]);
board_putchar(hash[hashi]);
if (++hashi == 5)
hashi=1;
hashj = 0;
}
break;
case '7':
case '8':
case '9':
type = type - '0';
type = 10 - type;
while (type-- >= 0)
{
data = dl_getSpair();
checksum = (data + checksum) & 0x00FF;
address = (address << 8) | data;
length--;
}
address = address + offset_to_addr;
while (length-- > 1)
{
data = dl_getSpair();
checksum = (data + checksum) & 0x00FF;
}
data = dl_getSpair();
if (((data - ~checksum) & 0x00FF) != 0)
{
printf("\bError: S-record checksum error!\n");
return FALSE;
}
else
{
printf("\bS-record download successful!\n");
cpu_pc_modify(address);
}
done = TRUE;
/* Clear out the \n in the receive buffer */
board_getchar();
break;
case '0':
case '4':
case '5':
case '6':
default:
break;
}
}
return TRUE;
}
/********************************************************************/
void
uif_cmd_dl (int argc, char **argv)
{
/*
* This routine downloads S-records from the host.
*/
int success;
int32 offset;
extern ADDRESS md_last_address;
extern ADDRESS disasm_last_address;
(void)argc;
if (argv[1] != NULL)
{
offset = (int32)get_value(argv[1],&success,BASE);
if (!success)
{
printf(INVALUE,argv[1]);
return;
}
printf("Offset: %#08X (%d)\n", offset);
}
else
offset = 0;
printf("Escape to local host and send S-records now...\n");
dl_download_srec(offset);
cpu_cache_flush();
disasm_last_address = cpu_pc_get();
md_last_address = cpu_pc_get();
}
/********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -