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

📄 monitor_cmd.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 4 页
字号:
    }

  if (argvect[1] != NULL)
    {
      if (argvect[2] != NULL)
	return tcpport_cmd (USAGE);

      p = argvect[1];
      n = 0;
      while (isdigit(*p))
	{
	  n = n*10 + (*p++ - '0');
	  if (n > 65535)
	    return tcpport_cmd (USAGE);
	}
      if (*p != '\0')
	return tcpport_cmd (USAGE);

      NVRAM_TCP_PORT(0) = (n >> 8) & 0xff;
      NVRAM_TCP_PORT(1) = n & 0xff;
    }
  else
    xprintf("%d\n", (NVRAM_TCP_PORT(0) << 8) + NVRAM_TCP_PORT(1));

  return 0;
}
#endif /* NVRAM_TCP_PORT */


#ifdef __ECOS__
#  if (CYG_BYTEORDER == CYG_LSBFIRST)
#    define LITTLE_ENDIAN_TARGET
#  else
#    define BIG_ENDIAN_TARGET
#  endif
#endif

#ifdef LITTLE_ENDIAN_TARGET
static int swap_bytes = 1;
#else
static int swap_bytes = 0;
#endif

int
get_memory_display_mode (void)
{
  return swap_bytes;
}

void
set_memory_display_mode (int mode)
{
  swap_bytes = mode;
}


/* Just to make DEFAULT_SIZE something usable, this may go elsewhere later.*/
#ifndef DEFAULT_SIZE
#define DEFAULT_SIZE 1
#endif

static int
get_cmd_size (void)
{
  int size = 0;
  char *sizestr;

  sizestr = strchr (argvect[0], '.');

  if (sizestr == NULL || sizestr[0] == '\0' || sizestr[1] == '\0')
    {
      size = DEFAULT_SIZE;
    }
  else
    {
      size = str2int (sizestr + 1, 10) / 8;
    }
  if (size != 1 && size != 2 && size != 4 && size != 8)
    {
      xprintf ("Invalid size.\n");
      return -1;
    }
  return size;
}


void
display_memory (char *value, int size, int littleEndian)
{
  int x;
  int start = littleEndian ? size - 1 : 0 ;
  int end = littleEndian ? -1 : size;
  int incr = littleEndian ? -1 : 1;

  if (value)
    {
      for (x = start; x != end; x += incr)
        xprintf ("%02x", value[x] & 0xff);
    }
  else
    {
      for (x = start; x != end; x += incr)
        xprintf ("..");
    }
}


static int
peek (void)
{
  mem_addr_t addr;
  int size = get_cmd_size ();

  if (size > 0)
    {
      /* We already checked to see if the command was legal when we called the
	 function, so there's no need to worry about that here. */

      if (argvect[1] != 0)
	{
	  char value[8];

	  str2addr (argvect[1], &addr);
	  if (read_memory (&addr, size, 1, value))
	    {
	      xprintf ("Memory read failed\n");
	    }
	  else
	    {
	      display_memory (value, size, get_memory_display_mode ());
	      xprintf ("\n");
	    }
	}
      else
	{
	  xprintf ("Not enough arguments\n");
	  return mem_cmd (USAGE);
	}
    }
  return 0;
}

/* Poke a single byte in memory. */

static int 
poke (void)
{
  int size = 0;

  size = get_cmd_size ();
  if (size > 0)
    {
      /* We already checked to see if the command was legal when we called the
	 function, so there's no need to worry about that here. */

      if ((argvect[1] != 0) && (argvect[2] != 0))
	{
	  char value[8];
	  mem_addr_t addr;

	  str2addr (argvect[1], &addr);
	  hex2bytes (argvect[2], value, size);

	  if (get_memory_display_mode ())
	    {
	      /* Gotta swap this puppy. */
	      int x;

	      for (x = 0; x < (size / 2); x++)
		{
		  char tmp = value[x];
		  value [x] = value [size - 1 - x];
		  value [size - 1 - x] = tmp;
		}
	    }
	  if (write_memory (&addr, size, 1, value))
	    {
	      xprintf ("Memory write failed\n");
	    }
#ifdef HAVE_BSP
	  bsp_flush_dcache((void *)addr.addr, size);
	  bsp_flush_icache((void *)addr.addr, size);
#endif
	}
      else
	{
	  xprintf ("Not enough arguments\n");
	  return mem_cmd (USAGE);
	}
    }
  return 0;
}


/* I am cheap and easy. */
int
mem_cmd (cmdmode_t mode)
{
  if (mode == USAGE)
    {
      usage ("memory[.size] address [value]");
      return 0;
    }
  if (mode == SHORT_HELP)
    {
      short_help ("read/write memory");
      return 0;
    }
  if (mode == LONG_HELP)
    {
      mem_cmd (USAGE);
      long_help ("\
The memory command is used to view and modify single locations in memory.\n\
It can take a size extension, which follows the command name or partial\n\
command name without a space, and is a period followed by the number of\n\
bits to be viewed or modified.  Options are 8, 16, 32, and 64.  Without\n\
a size extension, the memory command defaults to displaying or changing 8\n\
bits at a time.\n\
The memory command can take one or two arguments, independent of\n\
whether a size extension is specified.  With one argument, it displays the\n\
contents of the specified location.  With two arguments, it replaces the\n\
contents of the specified location with the specified value.\n");
      example ("\
memory.8 45f6b2 57\n\
Places the 8 bit value 57 at the location 45f6b2.");
      return 0;
    }

  if (argvect[1] == NULL || (argvect[2] != NULL && argvect[3] != NULL))
    {
      return mem_cmd (USAGE);
    }
  if (argvect[1] != NULL && argvect[2] != NULL)
    return poke ();
  else
    return peek ();
}

/* Memory dump function. */

int 
dump_cmd (cmdmode_t mode)
{
  mem_addr_t addr;
  char value[8];

  if (mode == USAGE)
    {
      usage ("dump[.size] location [count]");
      return 0;
    }
  if (mode == SHORT_HELP)
    {
      short_help ("Memory dump command");
      return 0;
    }
  if (mode == LONG_HELP)
    {
      dump_cmd (USAGE);
      long_help ("\
The dump command displays a region of memory. If no count value is\n\
supplied, the command displays 16 bytes.  It can take a size\n\
extension, which follows the command name or partial command name\n\
without a space, and is a period followed by the number of bits to be\n\
viewed or modified.  Options are 8, 16, 32, and 64.  Without a size\n\
extension, the dump command defaults to displaying 8 bits at a time.\n\
Addresses are aligned to a 16-byte boundary.  Thus, dump 65 would show\n\
all bytes from 60 through 6f.\n");
      example ("\
dump 44f5\n\
Displays 16 bytes starting with 44f0 and ending with 44ff.");
      return 0;
    }

  if (argvect[1] != 0 && (argvect[2] == NULL || argvect[3] == NULL))
    {
      mem_addr_t start_addr;
      char chardumps[32];
      int offset;
      int count;
      int line;
      int size = get_cmd_size ();
      int i;

      if (size == -1)
          /*
           * Invalid size specified.
           */
          return 0;

      str2addr (argvect[1], &addr);
      if (argvect[2] != NULL)
	{
	  count = str2int (argvect[2], 10);
	  count = (count + 15) / 16;
	}
      else
	{
	  count = 1;
	}
      ADD_ALIGN(&addr, &start_addr, 16);
      for (line = 0; line < count; line ++)
	{
	  for (offset = 0; offset < 16; offset += size)
	    {
	      ADD_OFFSET(&start_addr, &addr, offset + line * 16);

	      if (offset == 0)
		{
		  char buf[32];
	      
		  addr2str (&addr, buf);
                  xprintf("%s: ", buf);
		}
              if (read_memory (&addr, size, 1, value))
                {
                  display_memory (0, size, get_memory_display_mode ());
                  for (i = 0; i < size; i++)
                    {
                      value[i] = 0;
                    }
                } else {
                  display_memory (value, size, get_memory_display_mode ());
                }
              xprintf (" ");
              for (i = 0; i < size; i++)
                {
                  chardumps[offset + i] = value[i] & 0x7f;
                  if (chardumps[offset + i] < 32)
                    chardumps[offset + i] = '.';
                }
	    }
	  xprintf (" ");
	  for(i = 0; i < offset; i++)
	    {
	      xprintf ("%c", chardumps[i]);
	    }
          xprintf ("\n");
	}
    }
  else
    {
      dump_cmd (USAGE);
    }
  return 0;
}

static int scnt;
static int (*srec_input_char) (void);

static inline int
gethexnibble(void)
{
  int ch;

  inbuf[scnt++] = ch = srec_input_char();
  if (ch >= '0' && ch <= '9')
    return (ch - '0');
  if (ch >= 'a' && ch <= 'f')
    return (ch - 'a' + 10);
  if (ch >= 'A' && ch <= 'F')
    return (ch - 'A' + 10);

  inbuf[scnt] = '\0';
  xprintf("Bad hex char: %s\n", inbuf);
  return -1;
}


static inline int
gethexbyte(void)
{
  int nib;
  unsigned char n;

  if ((nib = gethexnibble()) < 0)
    return -1;
  n = nib << 4;
  if ((nib = gethexnibble()) < 0)
    return -1;
  n |= nib;
  return n;
}

static inline int
chk_cksum(unsigned int cksum, int rval)
{
  int n;

  if ((n = gethexbyte()) < 0)
    return -1;

  cksum = ~cksum & 0xff;

  if (cksum != n)
    {
      inbuf[scnt] = '\0';
      xprintf("Bad cksum[%02x]: %s\n", cksum, inbuf);
      return -1;
    }
  return rval;
}

int
load_srec(srec_input_func_t inp_func)
{
  int count, dcount, data, n, addr_bytes = 0, is_term, is_comment;
  unsigned int address, cksum;
  unsigned char data_buf[256];
  mem_addr_t memaddr;

  srec_input_char = inp_func;

  is_comment = is_term = 0;

  while (srec_input_char() != 'S')
    ;

  scnt = 0;
  inbuf[scnt++] = 'S';

  if ((n = gethexnibble()) < 0)
    return -1;

  switch (n)
    {
      case 0:
      case 5:
	is_comment = 1;
	break;

      case 1:
      case 2:
      case 3:
	addr_bytes = n + 1;
	break;

      case 7:
      case 8:
      case 9:
	is_term = 1;
	addr_bytes = 11 - n;
	break;

      default:
	inbuf[scnt] = '\0';
	xprintf("Bad record type: %s\n", inbuf);
	return -1;
    }

  if ((count = gethexbyte()) < 0)
    return -1;
  cksum = count;

  --count; /* don't count chksum */

  if (is_comment)
    {
      while (count > 0)
	{
	  if ((n = gethexbyte()) < 0)
	    return -1;
	  cksum += n;
	  --count;
	}
      return chk_cksum(cksum, 0);
    }

  address = 0;
  while (count > 0 && addr_bytes)
    {
      if ((n = gethexbyte()) < 0)
	return -1;
      cksum += n;
      address = (address << 8) | n;
      --addr_bytes;
      --count;
    }

  if (is_term)
    {
      if (count || addr_bytes)
	{
	  inbuf[scnt] = '\0';
	  xprintf("Malformed record cnt[%d] abytes[%d]: %s\n",
		 count, addr_bytes, inbuf);
	  return -1;
	}
      if (chk_cksum(cksum, 1) == 1)
	{
	  set_pc (address);
	  xprintf("Setting start address: 0x%08x\n", address);
	  return 1;
	}
      return -1;
    }

  dcount = 0;

  while (count > 0)
    {
      if ((data = gethexbyte()) < 0)
	return -1;
      cksum += data;
      data_buf[dcount++] = data;
      --count;
    }
    
  if (chk_cksum(cksum, 0))
    return -1;

  MAKE_STD_ADDR (address, &memaddr);
  write_memory (&memaddr, 1, dcount, data_buf);
#ifdef HAVE_BSP
  bsp_flush_dcache((void *)memaddr.addr, dcount);
  bsp_flush_icache((void *)memaddr.addr, dcount);
#endif

  return 0;
}


int 
load_cmd (cmdmode_t mode)
{
  if (mode == USAGE)
    {
      usage ("load");
      return 0;
    }
  if (mode == SHORT_HELP)
    {
      short_help ("Load srecords into memory");
      return 0;
    }
  if (mode == LONG_HELP)
    {
      load_cmd (USAGE);
      long_help ("\
The load command switches the monitor into a state where it takes all input 
as s-records and stores them in memory.  The monitor exits this mode when a
termination record is hit, or certain errors (such as an invalid s-record)
cause the load to fail.");
      return 0;
    }
  
  if (argvect[1] != NULL)
    {
      return load_cmd (USAGE);
    }

  while (!load_srec(xgetchar))
      ;

  return 0;
}

#ifndef REGNAME_EXAMPLE
# define REGNAME_EXAMPLE "a0"
#endif

#if !defined(__ECOS__) || defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
int
transfer_cmd (cmdmode_t mode)
{
  if (mode == USAGE)
    {
      usage ("$");
      return 0;
    }
  if (mode == SHORT_HELP)
    {
      short_help ("Transfer to gdb stub");
      return 0;
    }
  if (mode == LONG_HELP)
    {
      transfer_cmd (USAGE);
      long_help ("\
The transfer or $ command transfers control to the gdb stub.  This function\n\
does not actually need to be called by the user, as connecting to the board\n\
with gdb will call it automatically.  The transfer command takes no\n\
arguments.  The $ command does not wait for a return, but executes\n\
immediately.  A telnet setup in line mode will require a return when $ is\n\
executed by the user, as the host computer does not pass any characters to\n\
the monitor until a return is pressed.  Disconnecting from the board in gdb\n\
automatically returns control to the monitor.");
      return 0;
    }
  if (argvect[1] == NULL)
    {
      return transfer_to_stub ();
    }
  else
    {
      transfer_cmd (USAGE);
    }
  return 0;
}
#endif

static void
display_group (int which_group)
{
  int len = 0;
  int skipping_group = 0;
  char buf[80];
  int start_entry = 0;
  int i;

  if (which_group >= 0)
    {
      start_entry = which_group;
    }

  for (i = start_entry; regtab[i].registername != NULL; i++)
    {
      int buflen;

      if (regtab[i].registernumber < 0)
	{
	  if (which_group >= 0 && i != which_group)
	    {
	      break;
	    }

	  if (len > 0)
	    {
	      xprintf ("\n");
	      len = 0;
	    }
	  if (which_group < 0)
	    {
	      if (regtab[i].registernumber == -2)
		{
		  skipping_group = 1;
		  xprintf ("[skipping %s]\n", regtab[i].registername);
		}

⌨️ 快捷键说明

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