📄 mbxtcl.c
字号:
"Reads data from the upper half of the flash memory. It is 1 MB in size.\n\
Syntax:\n\
flread pos ?length?\n\
Reads 32-bits data from byte position pos (0-1048575)\n\
Number of data read is length (1-32) and is default to 1.";
static int MbxTclFlashRead(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]) {
int data[32];
char str[50];
Cyg_ErrNo err;
cyg_io_handle_t flash;
int length, len, pos, i;
if (argc < 2 || argc > 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" pos ?length?\"", (char *)NULL);
return TCL_ERROR;
}
if (Tcl_GetUInt(interp, argv[1], &pos) != TCL_OK) {
return TCL_ERROR;
}
if (pos < 0 || pos > 1048575) {
Tcl_AppendResult(interp, "wrong value for pos: should be 0-1048575", (char *)NULL);
return TCL_ERROR;
}
if (argc == 3) {
if (Tcl_GetUInt(interp, argv[2], &length) != TCL_OK) {
return TCL_ERROR;
}
if (length < 1 || length > 32) {
Tcl_AppendResult(interp, "wrong value for length: should be 1-32", (char *)NULL);
return TCL_ERROR;
}
} else {
length = 1;
}
err = cyg_io_lookup("/dev/flash1", &flash);
if (err) {
sprintf(str, "Error opening /dev/flash1: %d", err);
Tcl_SetResult(interp, str, TCL_VOLATILE);
return TCL_ERROR;
}
len = length*sizeof(int);
err = cyg_io_bread(flash, data, &len, pos);
if (err) {
sprintf(str, "Error reading /dev/flash1: %d", err);
Tcl_SetResult(interp, str, TCL_VOLATILE);
return TCL_ERROR;
}
for (i=0; i<length; i++) {
sprintf(str, "%d", data[i]);
Tcl_AppendResult(interp, str, (i == length-1 ? "" : " "), (char*)NULL);
}
return TCL_OK;
}
/****f* MBXTCL/MbxTclFlashWrite
* DESCRIPTION
* Writes data to the flash.
***/
static const char MbxTclFlashWriteHelp[] =
"Writes data to the upper half of the flash memory. It is 1 MB in size.\n\
Syntax:\n\
flwrite pos data\n\
Writes 32-bits data to byte position pos (0-1048575)\n\
Data is a list of words to write. Maximum of 32 words.";
static int MbxTclFlashWrite(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]) {
int data[32];
char str[50];
Cyg_ErrNo err;
cyg_io_handle_t flash;
int len, i;
int pos;
char *first, *next;
char temp;
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" pos data\"", (char *)NULL);
return TCL_ERROR;
}
if (Tcl_GetUInt(interp, argv[1], &pos) != TCL_OK) {
return TCL_ERROR;
}
if (pos < 0 || pos > 1048575) {
Tcl_AppendResult(interp, "wrong value for pos: should be 0-1048575", (char *)NULL);
return TCL_ERROR;
}
i = 0;
first = argv[2];
while ((i < 32) && (first[0] != '\0')) {
if (TclFindElement(interp, first, &first, &next, &len, NULL) != TCL_OK) {
Tcl_AppendResult(interp, "data is not a list", (char *)NULL);
return TCL_ERROR;
}
if (len == 0) {
Tcl_AppendResult(interp, "empty list?", (char *)NULL);
return TCL_ERROR;
}
temp = first[len];
first[len] = '\0';
if (Tcl_GetInt(interp, first, &(data[i])) != TCL_OK) {
return TCL_ERROR;
}
first[len] = temp;
i++;
first = next;
}
err = cyg_io_lookup("/dev/flash1", &flash);
if (err) {
sprintf(str, "Error opening /dev/flash1: %d", err);
Tcl_SetResult(interp, str, TCL_VOLATILE);
return TCL_ERROR;
}
len = i*sizeof(int);
err = cyg_io_bwrite(flash, data, &len, pos);
if (err) {
sprintf(str, "Error writing /dev/flash1: %d", err);
Tcl_SetResult(interp, str, TCL_VOLATILE);
return TCL_ERROR;
}
return TCL_OK;
}
/****f* MBXTCL/MbxTclShowThreads
* DESCRIPTION
* Show all threads in the system.
***/
static const char MbxTclShowThreadsHelp[] = "Show all threads in the system.";
static int MbxTclShowThreads(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]) {
cyg_handle_t thread = 0;
cyg_uint16 id = 0;
char str[80];
if (argc != 1) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
"\"", (char *)NULL);
return TCL_ERROR;
}
Tcl_AppendResult(interp, " Stack Stack Stack\n", (char *)NULL);
Tcl_AppendResult(interp, "ID: Name: Prio: State: size: used: base:\n", (char *)NULL);
while(cyg_thread_get_next(&thread, &id)) {
cyg_thread_info info;
if(!cyg_thread_get_info(thread, id, &info))
break;
sprintf(str, "%3d %12s %5d %6d %5d %5d 0x%08x\n",
info.id, info.name?info.name:"----", info.set_pri, info.state,
info.stack_size, info.stack_used, info.stack_base);
Tcl_AppendResult(interp, str, (char *)NULL);
}
return TCL_OK;
}
/*************************************************************************************/
/* A data structure that pair a Tcl command with the implementation in a C function */
/* and a help string for the command. */
typedef struct {
char *name; /* Name of command. */
Tcl_CmdProc *proc; /* Procedure that executes command. */
const char *help; /* Help text that describes the command. */
} cmdInfo_t;
/* A list of all Mobitex TCL commands implemented. */
static const cmdInfo_t mbxCmds[] = {
{"rev", MbxTclRev, MbxTclRevHelp},
{"hw", MbxTclHw, MbxTclHwHelp},
{"time", MbxTclTime, MbxTclTimeHelp},
{"print", MbxTclPrint, MbxTclPrintHelp},
{"cpuload", MbxTclCpuLoad, MbxTclCpuLoadHelp},
{"exit", MbxTclExit, MbxTclExitHelp},
{"pio", MbxTclPio, MbxTclPioHelp},
{"adc", MbxTclAdc, MbxTclAdcHelp},
{"dac", MbxTclDac, MbxTclDacHelp},
{"pll", MbxTclPll, MbxTclPllHelp},
{"cmx", MbxTclCmx, MbxTclCmxHelp},
{"prbs", MbxTclPrbs, MbxTclPrbsHelp},
{"rx", MbxTclRx, MbxTclRxHelp},
{"tx", MbxTclTx, MbxTclTxHelp},
{"band", MbxTclBand, MbxTclBandHelp},
{"freqpar", MbxTclFreqPar, MbxTclFreqParHelp},
{"peek8", MbxTclPeek8, MbxTclPeek8Help},
{"peek", MbxTclPeek32, MbxTclPeek32Help},
{"poke8", MbxTclPoke8, MbxTclPoke8Help},
{"poke", MbxTclPoke32, MbxTclPoke32Help},
{"wd", MbxTclWd, MbxTclWdHelp},
{"flashload", MbxTclFlashLoad, MbxTclFlashLoadHelp},
{"flread", MbxTclFlashRead, MbxTclFlashReadHelp},
{"flwrite", MbxTclFlashWrite, MbxTclFlashWriteHelp},
{"ps", MbxTclShowThreads, MbxTclShowThreadsHelp},
/* End list with NULL pointers */
{NULL, (Tcl_CmdProc *) NULL, NULL}
};
/****f* MBXTCL/MbxTclHelp
* DESCRIPTION
* Prints the help string for a command.
***/
static int MbxTclHelp(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]) {
cmdInfo_t *cmdInfoPtr;
if (argc > 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" [command]\"", (char *)NULL);
return TCL_ERROR;
}
if (argc == 1) {
/* Return a list of all commands. */
Tcl_AppendResult(interp, "Type \"help <command>\" for specific help on a command.\n",
"See a Tcl user guide for general tcl commands.\n", "This is a list of DE9901 specific commands:\n", (char *)NULL);
for (cmdInfoPtr = (cmdInfo_t *)mbxCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) {
Tcl_AppendResult(interp, cmdInfoPtr->name, " ", (char *)NULL);
}
return TCL_OK;
}
/* Search for the command. */
for (cmdInfoPtr = (cmdInfo_t *)mbxCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) {
if (strcmp(cmdInfoPtr->name, argv[1]) == 0) {
if (cmdInfoPtr->help == NULL) {
Tcl_SetResult(interp, "No help available", TCL_STATIC);
return TCL_ERROR;
}
Tcl_SetResult(interp, (char*)cmdInfoPtr->help, TCL_STATIC);
return TCL_OK;
}
}
Tcl_SetResult(interp, "Command not found", TCL_STATIC);
return TCL_ERROR;
}
/****f* MBXTCL/InitCommands
* DESCRIPTION
* This function installs all new TCL commands in a Tcl interpreter.
***/
static void InitCommands(Tcl_Interp *iPtr) {
cmdInfo_t *cmdInfoPtr;
for (cmdInfoPtr = (cmdInfo_t *)mbxCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) {
Tcl_CreateCommand(iPtr, cmdInfoPtr->name, cmdInfoPtr->proc, (ClientData) 0,
(Tcl_CmdDeleteProc *) NULL);
}
Tcl_CreateCommand(iPtr, "help", MbxTclHelp, (ClientData) 0,
(Tcl_CmdDeleteProc *) NULL);
}
/* A pointer to the default TCL interpreter. */
extern Tcl_Interp *interp;
/* TCL function to run as a thread. */
void TclMain(cyg_addrword_t lData);
/****f* MBXTCL/MbxTclInit
* DESCRIPTION
* This function shall be called when the system is started. The console port is opened
* and setup for used by Tcl.
* The Tcl thread is started and the Tcl system is initialized.
* The Tcl thread stops automatically after the initialization is ready.
* The user application can start the Tcl thread later. See MbxTclStartCheck.
***/
void MbxTclInit(void) {
int err;
cyg_tty_info_t ttyInfo;
cyg_serial_info_t serInfo;
cyg_uint32 block;
cyg_uint32 len;
// Open console serial port.
err = cyg_io_lookup("/dev/con", &portHandl[0]);
if (err) {
diag_printf("ERROR opening /dev/con\n");
}
// Open console TTY.
err = cyg_io_lookup("/dev/tty1", &portHandl[1]);
if (err) {
diag_printf("ERROR opening device tty1\n");
}
// Setup serial port config.
len = sizeof(serInfo);
cyg_io_get_config(portHandl[0], CYG_IO_GET_CONFIG_SERIAL_INFO, &serInfo, &len);
// Change speed to 9600 since 38400 seems to be too much for the system,
// characters are lost.
serInfo.baud = CYGNUM_SERIAL_BAUD_9600;
len = sizeof(serInfo);
cyg_io_set_config(portHandl[0], CYG_IO_SET_CONFIG_SERIAL_INFO, &serInfo, &len);
// Setup tty console port for use by tcl.
ttyInfo.tty_in_flags = CYG_TTY_IN_FLAGS_ECHO | CYG_TTY_IN_FLAGS_CRLF;
ttyInfo.tty_out_flags = CYG_TTY_OUT_FLAGS_CRLF;
len = sizeof(ttyInfo);
cyg_io_set_config(portHandl[1], CYG_IO_SET_CONFIG_TTY_INFO, &ttyInfo, &len);
// Setup console port to be non-blocking until tcl is started.
block = 0;
len = sizeof(block);
cyg_io_set_config(portHandl[0], CYG_IO_SET_CONFIG_SERIAL_READ_BLOCKING, &block, &len);
// Create the TCL thread.
// It will run immediately and initialize itself and then suspend.
cyg_thread_create(1, TclMain, (cyg_addrword_t) 0,
"Tcl", (void *)&tclStack, TCL_STACK_SIZE,
&tclThread, &tclThreadPCB);
cyg_thread_resume(tclThread);
// When resume is executed this thread will stop and this function
// will execute again after tcl has been initialized.
// Now it is time to install Mobitex specific commands.
InitCommands(interp);
// Set the priority for TCL thread to the lowest.
// It will not run again until the user starts it.
cyg_thread_set_priority(tclThread, TCL_THREAD_PRIO);
printf("TCL thread initialized.\n");
printf("Enter password to start TCL.\n");
}
/****f* MBXTCL/MbxTclStartCheck
* DESCRIPTION
* This function checks for a password to be entered on the console port.
* When the right word is read the Tcl thread is started and the user has
* a command interface to DE9901.
***/
void MbxTclStartCheck(void) {
static char buffer[20]; /* The length must be at least 10 + sizeof(password). */
static const char password[] = "tcl";
static cyg_uint32 pi = 0;
char str[10];
char *p;
cyg_uint32 len, block, i;
len = 10;
cyg_io_read(portHandl[0], str, &len);
if (len > 0) {
/* Copy characters to password buffer and check if the right word is entered. */
for (i=0; i<len; i++) {
buffer[pi] = str[i];
pi++;
}
buffer[pi] = 0;
p = strstr(buffer, password);
if (p != NULL) {
/* The right password was found. */
pi = 0;
buffer[0] = 0;
/* Setup console port to have read blocking when tcl is started. */
block = 1;
len = sizeof(block);
cyg_io_set_config(portHandl[0], CYG_IO_SET_CONFIG_SERIAL_READ_BLOCKING, &block, &len);
mbxTclRun = TRUE;
fputs("\n", stdout);
fputs("Welcome to Mobitex embedded TCL (R1A) for eCos\n", stdout);
fputs("running on a DE9901 demonstration board!\n", stdout);
fputs("(Type \"help\" for a list of DE9901 specific commands.)\n", stdout);
cyg_thread_resume(tclThread);
} else {
if (pi > sizeof(password)) {
/* Shift the last password characters down for the next check. */
for (i=0; i<sizeof(password); i++) {
buffer[i] = buffer[pi-sizeof(password)+i];
}
pi = i;
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -