📄 eval_cmnd.c
字号:
/*
**********************************************************************************
*
* Project Name: AT89C5131 MCU and Hi-Tech 8051 compiler evaluation
*
* File Name: eval_cmnd.c
*
* Copyright 2004++ by Michael J Bauer [www.hotkey.net.au/~mjbauer/free_IP.htm]
*
* Date Created: 2004.08.26
*
* This source module implements a simple "command line interface" (CLI) and a
* set of generic command functions, including resident "debug" facilities.
*
* A command string is composed of a 2-letter command "name" and a number of
* user-supplied "arguments" (parameters). Some commands have no arguments.
* A single space must be inserted between command line arguments, where there is
* more than one (including the 2-letter command name).
* Refer to "help" strings for command syntax details.
*
*
**********************************************************************************
*/
#include "a89c5131.h" /* MCU-specific definitions */
#include "intrpt.h" /* Compiler-specific interrupt support defs (Hi-Tech C 8051) */
#include "eval_defs.h" /* Eval common definitions */
#include "usb_vuart_lib.h"
#include "usb_drv.h"
#include "usb_cdc_enum.h"
/* Command table entry looks like this */
struct CmndTableEntry_t
{
char cName1; /* command name, 1st char */
char cName2; /* command name, 2nd char */
pfnvoid Function; /* pointer to CLI function */
};
/*** globals ***/
idata char gacCmdLine[CMD_LINE_SIZE]; /* Command Line buffer for USB input */
idata char * pacCmdLinePtr; /* Pointer into gacCmdLine[] */
idata char gacPrompt[6]; /* Variable prompt string */
idata uint8 gubRespCksm; /* Response checksum (1 byte) */
/*****
* Text strings for "help" command.
*/
const char kszHelpPage1[] = "User command set...\n" ;
const char kszHelpHE[] = "HE [+] | Help (+ debug cmnds)\n" ;
const char kszHelpST[] = "ST <arg> | Set Time & date (arg='yymmdd-hhmmss')\n" ;
const char kszHelpDP[] = "DP | Default Param's\n" ;
const char kszHelpWA[] = "WA | Watch Variables\n" ;
const char kszHelpWT[] = "WT | Watch Timers\n" ;
const char kszHelpSE[] = "SE | System Errors\n" ;
const char kszHelpVN[] = "VN | Firmware Version\n" ;
const char kszHelpRS[] = "RS | Reset \n" ;
const char kszHelpPage2[] = "Debug command set...\n" ;
#if DISASM_INCLUDED
const char kszHelp202[] = "DA aaaa x | Disassemble @ aaaa [x= no pause]\n" ;
#endif
const char kszHelp203[] = "DC [aaaa] | Dump Code memory (0000..FFFF)\n" ;
const char kszHelp204[] = "DD [aaaa] | Dump Data memory (0000..FFFF)\n" ;
const char kszHelp205[] = "DE p | Dump EEPROM page (0..7)\n" ;
const char kszHelp206[] = "RM aa | Read MCU memory (00..FF)\n" ;
const char kszHelp207[] = "WM aa dd | Write MCU memory (00..FF)\n" ;
const char kszHelp208[] = "RP p.b | Read Port pin (p=0..3, b=0..7)\n" ;
const char kszHelp209[] = "WP p.b d | Write Port latch (p=0..3, d=0,1)\n" ;
const char kszHelp210[] = "RE aaaa | Read Ext memory or I/O\n" ;
const char kszHelp211[] = "WE aaaa dd | Write Ext memory or I/O\n" ;
const char kszHelp212[] = "XE aaaa | Execute function\n" ;
/*****
* String constants...
* (See comments with function putconstr() elsewhere in this module.)
*/
const char kszGreeting[] = "AT89C5131 Evaluation Firmware: ";
const char kszCopyright[] = "M.J. Bauer 2004";
const char kszHead16bits[] = "15-------10 9 8 7 6 5 4 3 2 1 0 \n";
const char kszCommandError[] = "Command error!\n";
const char kszWatchAppHeader[]
= "Hit <Enter> to quit...\n";
const char kszWatchTimHeader[]
= "_____Date_____ __Time__ _______________\n";
const char kszSUN[] = "SUN";
const char kszMON[] = "MON";
const char kszTUE[] = "TUE";
const char kszWED[] = "WED";
const char kszTHU[] = "THU";
const char kszFRI[] = "FRI";
const char kszSAT[] = "SAT";
const char * pkzDayName[] = { kszSUN, kszMON, kszTUE, kszWED, kszTHU, kszFRI, kszSAT };
const char kszTimeInvalid[] = "--:--:--";
/*****
* Command table -- maximum number of commands is 250.
* (Application-specific command functions should go at the top)
*/
const struct CmndTableEntry_t asCommand[] =
{
'H','E', help_cmd, /* "User" commands */
'S','T', show_set_time_cmd,
'W','T', watch_timers_cmd,
'W','A', watch_app_cmd,
'D','P', default_params_cmd,
'S','E', show_errors_cmd,
'V','N', version_cmd,
'R','S', reset_MCU_cmd,
#if DISASM_INCLUDED
'D','A', disassemble_cmd, /* "Debug" commands */
#endif
'D','C', dump_memory_cmd,
'D','D', dump_memory_cmd,
'D','E', dump_memory_cmd,
'R','M', read_MCU_mem_cmd,
'W','M', write_MCU_mem_cmd,
'R','P', read_port_cmd,
'W','P', write_port_cmd,
'R','E', read_extd_cmd,
'W','E', write_extd_cmd,
'X','E', execute_cmd,
'$','$', DummyCmd /* Last entry in cmd table */
} ;
/********************************** CLI FUNCTIONS **************************************/
/*****
* Initialise the Command Line Interface
* Called from main before CLI is used.
* CLI functions may change gacPrompt[0] or gacPrompt[1] to indicate various conditions,
* e.g. errors, warnings, other command status.
*/
void
initialise_cli()
{
gbHCI_Stream = UART_HOST_LINK; // default HCI input/output stream
gacPrompt[0] = '-'; /* Create prompt string */
gacPrompt[1] = '-';
gacPrompt[2] = '>';
gacPrompt[3] = SPACE;
gacPrompt[4] = NUL;
flush_command_line();
}
/*****
* Function: check_HCI_input
* Purpose: Host command interface (HCI) data input routine for UART.
*
* This background function is called *frequently* from the main loop. It is not a
* "scheduled" task, and therefore it is permitted to call the function 'putch()'.
* The function checks for data input from the host PC via the UART; it returns
* immediately if there's no new input data available from the active input stream.
*
* If there is data available, it is processed. Printable chars are appended to the
* command line buffer. The same buffer is common to UART and USB input streams.
* Only data from the active input stream is written into the command line buffer.
*
* When a command terminator (CR) is received, the command line is interpreted and if
* the cmnd name is defined, the respective command function is executed.
* Most command functions generate response data to be output to the host PC.
* Output data is directed to the port associated with the active input/output stream.
* A global variable determines the active input/output stream (UART or USB).
*
* If 3 successive 'SYN' codes (Ctrl-V = ASCII 22) are received from the same input
* stream, then that stream will become the active one.
*/
void
check_uart_HCI_input( void )
{
static uint8 bUART_SYNcount; // Number of 'SYN' codes rx'd from UART input stream
char c;
if ( uart_rx_data_avail() )
{
c = uart_getch(); // no echo yet (in case c==SYN)
if ( gbHCI_Stream == UART_HOST_LINK )
{
putch( c ); // echo char to HCI stream
process_HCI_input_char( c );
}
else if ( c == SYN )
{
if ( ++bUART_SYNcount >= 3 )
{
gbHCI_Stream = UART_HOST_LINK; // make UART the active I/O stream
bUART_SYNcount = 0;
flush_command_line();
put_prompt();
}
}
else bUART_SYNcount = 0;
}
}
/*****
* Function: check_usb_HCI_input
* Purpose: Host command interface (HCI) data input routine for USB port.
*
* Performs the same routine as check_uart_HCI_input(), above, but with USB input.
* See header on check_uart_HCI_input().
*/
void
check_usb_HCI_input( void )
{
static uint8 bUSB_SYNcount; // Number of 'SYN' codes rx'd from USB input stream
char c;
if ( usb_vuart_rx_data_avail() )
{
c = usb_vuart_getchar(); // no echo yet
if ( gbHCI_Stream == USB_HOST_LINK )
{
putch( c ); // echo char to HCI stream...
usb_vuart_flush(); // ... immediately (if diagnostic mode)
process_HCI_input_char( c );
}
else if ( c == SYN )
{
if ( ++bUSB_SYNcount >= 3 ) // make USB the active I/O stream
{
gbHCI_Stream = USB_HOST_LINK;
bUSB_SYNcount = 0;
flush_command_line();
put_prompt();
}
}
else bUSB_SYNcount = 0;
}
}
/*****
* Function common to both check_uart_HCI_input() and check_usb_HCI_input().
* Examines a character received via the active input stream and decides what
* to do with it. If printable, it goes into the command line buffer, gacCmdLine[].
*/
void
process_HCI_input_char( char c )
{
if ( c == CR ) // CR is the command line terminator
{
if ( pacCmdLinePtr != gacCmdLine ) /* Cmd line length > 0 */
do_command();
else { putNewLine(); put_prompt(); }
}
else if ( isprint(c) ) // if printable, append c to command line
{
if ( pacCmdLinePtr <= (gacCmdLine + CMD_LINE_SIZE - 2) )
{ *pacCmdLinePtr++ = c; *pacCmdLinePtr = NUL; }
}
else if ( c == ESC || c == BACKSP ) /* Trash cmd line */
{
flush_command_line();
gacPrompt[1] = '?';
putch( NUL );
putNewLine();
put_prompt();
}
}
/*
* Function: do_command
*
* Purpose:
* Looks for command name (mnemonic, 2 chars) in command table;
* if found, executes respective command function.
* Output is directed to the active HCI stream (USB or UART).
*/
void
do_command( void )
{
char c1, c2;
uint8 n;
bool yFoundCndName = FALSE;
c1 = toupper( gacCmdLine[0] );
c2 = toupper( gacCmdLine[1] );
gubRespCksm = 0;
for ( n = 0; n < 250; n++ )
{
if ( asCommand[n].cName1 == '$' ) /* end of table */
break;
if ( asCommand[n].cName1 == c1 )
{
if ( asCommand[n].cName2 == c2 ) /* found match */
{
yFoundCndName = TRUE;
break;
}
}
}
putNewLine();
if ( yFoundCndName )
(*asCommand[n].Function)(); /* Call CLI command function */
else
{
putconstr( kszCommandError );
gacPrompt[1] = '?'; /* NACK... unrecognised command */
}
put_prompt();
flush_command_line();
}
/*****
* Function: flush_command_line();
* Clear command line buffer and reset pointer.
*
* Param's: --
* Returns: --
* Globals: pacCmdLinePtr, gacCmdLine
*/
void
flush_command_line( void )
{
uint8 ubx;
for ( ubx = 0; ubx < CMD_LINE_SIZE; ubx++ )
{
gacCmdLine[ubx] = NUL;
}
pacCmdLinePtr = gacCmdLine;
}
/*
* Output the prompt string to active HCI stream.
* If the HCI stream is USB, then the USB TX buffer is flushed (transmitted to the host)
* so that the prompt is seen at the host immediately.
*/
void
put_prompt( void )
{
putstr( gacPrompt );
if ( gbHCI_Stream == USB_HOST_LINK ) usb_vuart_flush();
gacPrompt[0] = '-'; // restore prompt
gacPrompt[1] = '-';
}
/* Dummy command function -- does nothing! */
void
DummyCmd( void )
{
return;
}
/****************************** "USER" COMMAND FUNCTIONS ********************************
*
*
* Command function 'HE' : Outputs a list of available commands & their param's.
*
* Command line format: "HE [+]"
* Optional parameter [+] selects "debug" commands page.
* User commands are selected by default.
*/
void
help_cmd( void )
{
if ( gacCmdLine[2] == SPACE ) /* Cmnd line arg. supplied... */
{
putconstr( kszHelpPage2 ); /* List debug command set */
#if DISASM_INCLUDED
putconstr( kszHelp202 );
#endif
putconstr( kszHelp203 );
putconstr( kszHelp204 );
putconstr( kszHelp205 );
putconstr( kszHelp206 );
putconstr( kszHelp207 );
putconstr( kszHelp208 );
putconstr( kszHelp209 );
putconstr( kszHelp210 );
putconstr( kszHelp211 );
putconstr( kszHelp212 );
}
else /* No cmd line arg. */
{
putconstr( kszHelpPage1 ); /* List end-user command set */
putconstr( kszHelpHE );
putconstr( kszHelpST );
putconstr( kszHelpWT );
putconstr( kszHelpWA );
putconstr( kszHelpDP );
putconstr( kszHelpSE );
putconstr( kszHelpVN );
putconstr( kszHelpRS );
}
}
/*
* Command function 'ST': Show or Set RTC Time and date.
* Cmd format: "ST yymmdd.hhmmss" (Time is in 24 hour format)
* If the argument [yymmdd.hhmmss] is omitted, the function outputs the date & time.
* (See also: watch_timers_cmd() function.)
*/
void
show_set_time_cmd( void )
{
if ( !isdigit( gacCmdLine[3] ) /* No arg, or format error... */
|| !isdigit( gacCmdLine[10] )
|| gacCmdLine[2] != SPACE )
{ /* Show current RTC date:time */
read_RTC_date_time();
putch( ' ' );
putconstr( pkzDayName[gsRTCbuf.dow] );
putch( SPACE );
putch( '2' ); putch( '0' );
putDecimal( gsRTCbuf.year, 2 );
putch( '.' );
putDecimal( gsRTCbuf.month, 2 );
putch( '.' );
putDecimal( gsRTCbuf.day, 2 );
putch( SPACE );
putch( SPACE );
putDecimal( gsRTCbuf.hour, 2 );
putch( ':' );
putDecimal( gsRTCbuf.min, 2 );
putch( ':' );
putDecimal( gsRTCbuf.sec, 2 );
putNewLine();
}
else
{
gsRTCbuf.year = decatoi( &gacCmdLine[3], 2 );
gsRTCbuf.month = decatoi( &gacCmdLine[5], 2 );
gsRTCbuf.day = decatoi( &gacCmdLine[7], 2 );
gsRTCbuf.hour = decatoi( &gacCmdLine[10], 2 );
gsRTCbuf.min = decatoi( &gacCmdLine[12], 2 );
gsRTCbuf.sec = decatoi( &gacCmdLine[14], 2 );
set_RTC_date_time(); /* This also determines the "day of the week" value */
if ( read_RTC_date_time() ) /* success! */
Clear_Bit( gwSystemError, RTC_INVALID );
}
}
/*
* Command function 'WT': Watch Timers (in real time).
* Outputs RTC day-date-time and various system timers in ASCII format.
* The output line is continuously refreshed until a char is received from
* the host PC (i.e. any key hit).
*/
void
watch_timers_cmd( void )
{
uint16 wStartTime;
putconstr( kszWatchTimHeader );
while ( 1 ) /* Loop until any key hit */
{
read_RTC_date_time();
putconstr( pkzDayName[gsRTCbuf.dow] );
putch( SPACE );
putch( '2' ); putch( '0' );
putDecimal( gsRTCbuf.year, 2 );
putch( '.' );
putDecimal( gsRTCbuf.month, 2 );
putch( '.' );
putDecimal( gsRTCbuf.day, 2 );
putch( SPACE );
putch( SPACE );
putDecimal( gsRTCbuf.hour, 2 );
putch( ':' );
putDecimal( gsRTCbuf.min, 2 );
putch( ':' );
putDecimal( gsRTCbuf.sec, 2 );
putch( SPACE );
putch( SPACE );
if ( gbHCI_Stream == USB_HOST_LINK ) usb_vuart_flush();
wStartTime = get_ticks();
while ( get_ticks() - wStartTime < 10 ) // wait 50mS (10 ticks)
{
background_process();
}
putch( CR );
if ( hci_data_avail() ) { getch(); break; } // quit
}
putNewLine();
}
/*
* Command function 'WA': Watch Application variables in real-time.
* (See 'WT' cmd fn for a complete example of implementation.)
*/
void
watch_app_cmd( void )
{
uint16 wStartTime;
putconstr( kszWatchAppHeader ); // Output a header line (optional)
while ( 1 ) /* Loop until any key hit */
{
/**** Output app. variables here on a single line *****/
if ( gbHCI_Stream == USB_HOST_LINK ) usb_vuart_flush();
wStartTime = get_ticks();
while ( get_ticks() - wStartTime < 10 ) // wait 50mS (10 ticks)
{
background_process();
}
putch( CR );
if ( hci_data_avail() ) { getch(); break; } // quit
}
putNewLine();
}
/*
* Command function 'DP': Default configuration parameters.
*
* Configuration parameters are application-specific persistent data maintained in EEPROM.
* The command copies "factory default" parameter values from program code ('const' data)
* to ERAM working variables, then stores these in a pre-defined EEPROM page.
*
* The example given here simply copies some strings from program code to ERAM and EEPROM,
* in order to demonstrate the EEPROM handling functions built into the operating system.
* The command 'DE 0' may be used to verify the operation.
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -