// // ww.c - program & UI for talking to the wand using the serial port // // Copyright (C) 2006 Nathan (Acorn) Pooley // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // version 2 as published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License (gpl.txt) for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // You can contact the author, Nathan (Acorn) Pooley, by writing // to Nathan (Acorn) Pooley, 949 Buckeye Drive, Sunnyvale, CA 94086, USA // or through the form at http://www.rawbw.com/~acorn/wand/feedback.html // //#@DOC@ program & UI for talking to the wand using the serial port //########################################################################### //############################### INCLUDES ################################## //########################################################################### #include <stdio.h> #include <stdarg.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <ctype.h> #include <sys/time.h> #include <time.h> #include "ac_serialio.h" #include "ac_fdio.h" #include "wandio.h" #include "ac_hexfile.h" #include "ac_log.h" #include "kernel.h" //########################################################################### //############################### DEFINES ################################### //########################################################################### #define PROG_MAX 65536 #define DEFAULT_HEX_FILE "../sw/wand.hex" #define TMP_FILENAME ".ww_tmp_data_file.txt" // // Each bit represents 64 bytes (0x20 bytes) // #define UI_PROG_IS_DIRTY_100(ui,addr) \ ((ui)->wandProgDirty[addr>>(6+5)] & (7<<((addr>>6)&0x1c))) #define UI_PROG_IS_DIRTY(ui,addr) \ ((ui)->wandProgDirty[addr>>(6+5)] & (1<<((addr>>6)&0x1f))) #define UI_PROG_SET_DIRTY(ui,addr) \ ((ui)->wandProgDirty[addr>>(6+5)] |= (1<<((addr>>6)&0x1f))) #define UI_PROG_CLR_DIRTY(ui,addr) \ ((ui)->wandProgDirty[addr>>(6+5)] &= ~(1<<((addr>>6)&0x1f))) //########################################################################### //############################### TYPEDEFS ################################## //########################################################################### struct WandUiRec; typedef int (*UiCmdFunc)(struct WandUiRec *ui, char *arg); typedef enum UiCmdFlagsEnum { UI_CFLG_NOARGS = 0x00000001, UI_CFLG_NEEDARGS = 0x00000002, UI_CFLG_EXACTMATCH = 0x00000004, UI_CFLG_END = 0x7fffffff } UiCmdFlagsEnum; typedef struct UiCmdRec { UiCmdFunc func; const char *name; int flags; // from UiCmdFlagsEnum const char *helpArgs; const char *help1; const char *help2; int namelen; } UiCmd; typedef struct WandUiRec { WandInfo *wand; AcHexByte *wandProg; unsigned int *wandProgDirty; // 1 bit for each 64 byte block int wandProgAllClean; const UiCmd *cmdList; AcHexFile *hexFile; char *saveName; // name to insert in save filenames char *lastOut; // last wand output char *lastSaveName; // // header from file & wand // kernelHeader headerFile; kernelHeader headerWand; // // addrMax is the max prog addr we care about // AcHexAddress addrMax; AcHexAddress addrMaxUser; AcHexAddress addrMaxFile; AcHexAddress addrMaxWand; // // addrMin is the min prog addr we care about // AcHexAddress addrMin; AcHexAddress addrMinUser; AcFdGroup *selectGroup; AcLog *log; int logToWand; int logFromWand; int logCmd; int logMsg; int debugLevel; int quit; } WandUi; //########################################################################### //############################### GLOBALS ################################### //########################################################################### AcHexByte gbuf[0x1000]; //########################################################################### //############################### PROTOTYPES ################################ //########################################################################### static int UiCmdGraph(WandUi *ui, char *args); //########################################################################### //############################### CODE ###################################### //########################################################################### //=========================================================================== // GetReply() - ask for an answer //=========================================================================== static const char *GetReply(void) { static char buf[100]; char *s = buf; while(1) { int c = getc(stdin); if (c == '\n') { *(s++) = 0; return buf; } *(s++) = c; if (s-buf >= sizeof(buf)-3) s--; } } //=========================================================================== // UiGetArgs() - get numeric args. //=========================================================================== // // argsp - pointer to args - pointer is updated to point to next arg // values - array of longs where results will go // max - number of longs lin values array // // RETURN: number of args found // static int UiGetArgs( WandUi *ui, char **argsp, unsigned long *values, int max) { int i; char *s = *argsp; while(isspace(*s)) s++; *argsp = s; for (i=0; i<max; i++) { unsigned long val; char *e = 0; //printf("a1='%s'\n",s); if (!*s) { return i; } val = strtoul(s,&e,0); if (!e || e == s) { break; } s = e; //printf("a2='%s'\n",s); values[i] = val; while(isspace(*s)) s++; //printf("a3='%s'\n",s); *argsp = s; } //printf("a4='%s'\n",*argsp); return i; } //=========================================================================== // UiHeaderValid() - true if header is valid //=========================================================================== static int UiHeaderValid(WandUi *ui, kernelHeader *hdr) { if ( !hdr || hdr->xa5 != 0xa5 || hdr->x5a != 0x5a || hdr->pad0 != 0x00 || hdr->pad1 != 0x00 || hdr->pad2 != 0x00 || hdr->version < 10 || hdr->kk_app_main_high < 0x01 || hdr->kk_app_main_low != 0x00) { return 0; } return 1; } //=========================================================================== // UiHeaderCompare() - 0 if headers are the same, nonzero otherwise //=========================================================================== static int UiHeaderCompare( WandUi *ui, kernelHeader *hdr1, kernelHeader *hdr2) { if (!UiHeaderValid(ui,hdr1) || !UiHeaderValid(ui,hdr2) || hdr1->version != hdr2->version || hdr1->kk_app_main_high != hdr2->kk_app_main_high || hdr1->kk_app_main_low != hdr2->kk_app_main_low) { return 1; } return 0; } //=========================================================================== // UiCheckAddrMaxMin() - calc max/min address //=========================================================================== static void UiCheckAddrMaxMin(WandUi *ui) { ui->addrMin = 0; if (!UiHeaderCompare(ui, &ui->headerWand, &ui->headerFile)) { ui->addrMin = (ui->headerWand.kk_app_main_high << 8) + (ui->headerWand.kk_app_main_low); } if (ui->addrMinUser != AC_HEX_INVALID_ADDRESS) { ui->addrMin = ui->addrMinUser; } ui->addrMax = 0; if (ui->addrMaxFile != AC_HEX_INVALID_ADDRESS && ui->addrMax < ui->addrMaxFile) { ui->addrMax = ui->addrMaxFile; } if (ui->addrMaxWand != AC_HEX_INVALID_ADDRESS && ui->addrMax < ui->addrMaxWand) { ui->addrMax = ui->addrMaxWand; } if (ui->addrMaxUser != AC_HEX_INVALID_ADDRESS) { ui->addrMax = ui->addrMaxUser; } if (ui->addrMax <= ui->addrMin) { ui->addrMax = ui->addrMin + 64; } ui->addrMin &= ~63UL; ui->addrMax = (ui->addrMax + 63) & ~63UL; } //=========================================================================== // UiSetProgDirty() - mark range that is unknown (dirty) //=========================================================================== static void UiSetProgDirty(WandUi *ui, unsigned long start, unsigned long end) { start &= ~63UL; end = (end + 63)&~63; if (start == 0 && end == 0) { end = PROG_MAX; } if (end > PROG_MAX) { end = PROG_MAX; } for (; start<=end; start+=64) { UI_PROG_SET_DIRTY(ui,start); } ui->wandProgAllClean = 0; } //=========================================================================== // UiSetProgClean() - mark range that was read from wand (clean) //=========================================================================== static void UiSetProgClean(WandUi *ui, AcHexAddress start, AcHexAddress end) { AcHexAddress addr; if (ui->wandProgAllClean) return; start = (start + 63)&~63UL; end &= ~63UL; for (addr=start; addr<=end; addr+=64) { UI_PROG_CLR_DIRTY(ui,addr); } // // Check if whole program is clean // start = ui->addrMin & ~63UL; end = (ui->addrMax + 63) & ~63UL; for (addr=start; ; addr+=64) { if (addr > end) { ui->wandProgAllClean = 1; break; } if (UI_PROG_IS_DIRTY(ui,addr)) { break; } } } //=========================================================================== // UiReadProgOld() - get program from wand //=========================================================================== static int UiReadProgOld( WandUi *ui, AcHexAddress start, AcHexOffset size, int force) { AcHexByte *buf; AcHexAddress addr = start; AcHexAddress end = start + size; int errCnt = 0; int lastGood=0; start = start & ~63UL; end = (end + 63) & ~63UL; if (end > PROG_MAX) { end = PROG_MAX; } buf = ui->wandProg; addr = start; while(addr < end) { int err = 0; AcHexAddress addr2; char *wand_output; if (!force && !UI_PROG_IS_DIRTY(ui,addr)) { addr = (addr + 64) & ~63UL; continue; } if (!lastGood) { wand_output = WandCmdfStr(ui->wand,"P%04x", (addr-1)&0xffff); if (wand_output) { free(wand_output); } else { err=1; } } if (!err) { wand_output = WandCmdfStr(ui->wand,""); if (!wand_output) { err = 1; } } if (!err) do { char *s = wand_output; char *e; err = 1; if (strncmp(s,"flash 0x",7)) break; s += 8; addr2 = strtol(s,&e,16); if (e!=s+4 || *e!=':' || addr2 != addr) break; s = e+1; while(1) { unsigned int val; while(isspace(*s)) s++; if (addr2 >= end) { err = 0; break; } if (!*s && addr != addr2) { err = 0; break; } if (!isxdigit(s[0]) || !isxdigit(s[1])) break; if (isdigit(s[0])) { val = 16 * (s[0] - '0'); } else { val = 16 * (toupper(s[0]) - 'A' + 10); } if (isdigit(s[1])) { val += (s[1] - '0'); } else { val += (toupper(s[1]) - 'A' + 10); } buf[addr2] = val; addr2 += 1; s += 2; } } while(0); lastGood = !err; if (err) { errCnt++; AcLogPrintf(0,4,"6:Error (%d) in wand output (b):\n",err); AcLogPrintf(0,4,"6:Got from wand: '%s'\n",wand_output); if (errCnt > 5) { AcLogPrintf(0,4,"3:Too many errors - aborting\n"); if (wand_output) free(wand_output); if (addr >= start + 64 + 64) { UiSetProgClean(ui, start, addr-64-64); } return -1; } WandRecoverWait(ui->wand); } else { AcBytePrint(&buf[addr],addr2-addr,addr,0); if (errCnt) errCnt--; addr = addr2; } if (wand_output) free(wand_output); } UiSetProgClean(ui, start, end-1); return 0; } //=========================================================================== // UiReadProg() - get program from wand //=========================================================================== static int UiReadProg( WandUi *ui, AcHexAddress start0, AcHexOffset size0, int force) { AcHexByte *buf; AcHexAddress start = start0; AcHexAddress addr = start; AcHexAddress end = start + size0; int errCnt = 0; start = start & ~0xffUL; end = (end + 0xff) & ~0xffUL; if (end > PROG_MAX) { end = PROG_MAX; } buf = ui->wandProg; addr = start; while(addr < end) { char *s; int err = 0; AcHexAddress end2 = end; AcHexAddress addr2; char *wand_output; addr = addr & ~0xffUL; if (!force) { if (!UI_PROG_IS_DIRTY_100(ui,addr)) { addr = (addr + 0x100) & ~0xffUL; continue; } end2 = addr + 0x100; while(1) { if (end2 >= addr + 0x2000) break; if (end2 >= end) break; if (!UI_PROG_IS_DIRTY_100(ui,end2)) break; end2 += 0x100; } } if (end2 - addr > 0x0800) { end2 = addr + 0x0800; } wand_output = WandCmdfStr(ui->wand,"F%02x%02x", (int)(addr>>8), (int)(end2>>8)); if (!wand_output || !wand_output[0]) err = 2; s = wand_output; if (!err) while(1) { int state; while(isspace(*s)) s++; if (*s == 0) break; addr2 = 0; for (state=0; state<4; state++, s++) { if (!isxdigit(*s)) { err = 3+state; break; } addr2 *= 16; if (isdigit(*s)) { addr2 += *s - '0'; } else { addr2 += tolower(*s) - 'a' + 10; } } if (err) break; if (*s != ':') { err = 8; break; } if (addr != addr2) { err=9; break; } s++; while(1) { int val = 0; if (*s == 0x0a || *s == 0x0d || *s == 0x00) break; if (isdigit(*s)) { val = *s - '0'; } else if (isxdigit(*s)) { val = tolower(*s) - 'a' + 10; } else { err = 10; break; } s++; val *= 16; if (isdigit(*s)) { val += *s - '0'; } else if (isxdigit(*s)) { val += tolower(*s) - 'a' + 10; } else { err = 11; break; } s++; buf[addr2] = val; addr2 += 1; } if ((addr2 & 0xff) == 0) { AcLogPrintf(0,4,"0:read 0x%04x - 0x%04x\n", (int)addr, (int)addr2); addr = addr2; } } if (err) { errCnt++; AcLogPrintf(0,4,"6:Error (%d) in wand output (a):\n",err); AcLogPrintf(0,4,"6:Got from wand: '%s'\n",wand_output); if (errCnt > 5) { AcLogPrintf(0,4,"3:Too many errors - use old method\n"); if (wand_output) free(wand_output); WandRecoverWait(ui->wand); return UiReadProgOld(ui,start0,size0,force); } WandRecoverWait(ui->wand); } else { //printf("Read 0x%04x\n",(int)addr); //AcBytePrint(&buf[addr],addr2-addr,addr,0); if (errCnt) errCnt--; addr = addr2; } if (wand_output) free(wand_output); } UiSetProgClean(ui, start, end-1); return 0; } //=========================================================================== // UiReadMinProgAddr() - calculate addrMin from wand and file //=========================================================================== static void UiReadMinProgAddr(WandUi *ui) { if (!UiReadProg( ui, KERNEL_HEADER_ADDR, sizeof(ui->headerWand), 0)) { memcpy(&ui->headerWand, ui->wandProg + 0x10, sizeof(ui->headerWand)); } else { memset(&ui->headerWand, 0, sizeof(ui->headerWand)); } UiCheckAddrMaxMin(ui); } //=========================================================================== // UiCmdDumpEEProm() show eeprom contents //=========================================================================== static int UiCmdDumpEEProm(WandUi *ui, char *args) { AcHexAddress addr; AcHexAddress start; AcHexAddress end; unsigned long vals[2]; int cnt; int rv = 0; cnt = UiGetArgs(ui, &args, vals, 2); if (*args) { AcLogPrintf(0,4,"0:Error: need 0-2 address arguments\n"); return -1; } if (cnt == 1) { start = vals[0]; end = vals[0]; } else if (cnt == 2) { start = vals[0]; end = vals[1]; } else { start = 0; end = 0xff; } for (addr=start; addr<=end; addr++) { if (WandCmdf(ui->wand, "E%04x",(int)(addr&0xffffUL))) { rv = -1; break; } } return rv; } //=========================================================================== // UiCmdInvalProg() - invalidate prog mem //=========================================================================== static int UiCmdInvalProg(WandUi *ui, char *args) { const char *reply; // // Confirm inval // AcLogPrintf(0,4,"0:\nSure you want to invalidata prog mem cp? [y/n] "); fflush(stdout); reply = GetReply(); if (toupper(reply[0]) != 'Y') { AcLogPrintf(0,4,"0:Aborting kload command\n"); return -1; } UiSetProgDirty(ui, 0,0); return 0; } //=========================================================================== // UiCmdDumpProg() - show program in wand //=========================================================================== static int UiCmdDumpProg(WandUi *ui, char *args) { AcHexAddress start; AcHexAddress end; unsigned long vals[2]; int cnt; int force_read = 0; cnt = UiGetArgs(ui, &args, vals, 2); if (*args == 'f') { force_read = 1; args++; } while(isspace(*args)) args++; if ((cnt && cnt != 2) || *args) { AcLogPrintf(0,4,"0:Error: need 2 address arguments\n"); return -1; } if (cnt == 2) { start = vals[0]; end = vals[1]; } else { UiReadMinProgAddr(ui); start = ui->addrMin; end = ui->addrMax; } if (!ui->wandProgAllClean || force_read) { AcLogPrintf(0,4,"6:Reading wand...\n"); if (UiReadProg(ui,start,end-start,force_read)) return -1; } AcLogPrintf(0,4,"4:Wand Contents:\n"); AcBytePrint((char*)ui->wandProg + start,end-start,start,1); printf("\n"); return 0; } //=========================================================================== // UiCmdDumpVars() - dump variable memory //=========================================================================== static int UiCmdDumpVars(WandUi *ui, char *args) { AcHexByte buf[10000]; unsigned long start, end, p; int lastGood = 0; int end_at_zeros=0; int zcnt=0; int dots=0; int rv = 0; unsigned long vals[2]; int cnt; cnt = UiGetArgs(ui, &args, vals, 2); if (*args == 'z') { end_at_zeros = 1; args++; } while(isspace(*args)) args++; if (cnt != 2 || *args) { AcLogPrintf(0,4,"0:Error: need 2 address arguments\n"); return -1; } start = vals[0]; end = vals[1]; if (end < start) { AcLogPrintf(0,4,"0:Error: start follows end\n"); return -1; } end++; if (end - start > sizeof(buf)) { AcLogPrintf(0,4,"0:Error: too long a range requested\n"); return -1; } AcLogPrintf(0,4,"6:Reading wand..."); fflush(stdout); for (p=start; p<end; ) { int retry = 3; for (; retry; retry--) { char *res; char *s; if (lastGood) { res = WandCmdfStr(ui->wand,""); } else { res = WandCmdfStr(ui->wand,"V%04x",p); } lastGood = 0; if (!res) continue; s = res; while(*s && *s != ':') s++; if (*s == ':') { unsigned long oldp = p; while(p<end) { char *e; int val; s++; val = strtoul(s,&e,16); if (e != s+2) break; buf[p-start] = val; if (val ==0) { zcnt++; } else { zcnt = 0; } s = e; p++; lastGood = 1; } if (p == oldp) continue; break; } } if (zcnt >= 32 && end_at_zeros) { AcLogPrintf(0,4,"9:\nFound 32 zeros - ending\n"); end = p; break; } if (!retry) { AcLogPrintf(0,4,"0:\nFailed to read register %04lx\n",p); end = p; rv = -1; break; } if (end-start > 0x200) { if ((p&3)==0) { AcLogPrintf(0,4,"3:."); fflush(stdout); dots=1; } } } if (dots) { AcLogPrintf(0,4,"3:\n"); } memset(gbuf,0,sizeof(gbuf)); memcpy(gbuf,buf,end-start); if (end > start) { AcBytePrint(buf,end-start,start,1); } return rv; } //=========================================================================== // UiDoWandOut() - show motions //=========================================================================== static void UiDoWandOut(void *data, const char *str) { WandUi *ui = data; #if 0 static char *dirStr[] = { "up","right","down","left" }; int i=0; #endif if (!str) str = ui->lastOut; if (!str) return; if (!strncmp(str,"Motion=",7)) { if (ui->lastSaveName) { free(ui->lastSaveName); ui->lastSaveName = 0; } if (!UiCmdGraph(ui, "auto")) { if (ui->lastSaveName) { char cmdBuf[100]; snprintf(cmdBuf,sizeof(cmdBuf), "fmtb_parse -s -o < %s | grep RESULT | tee mresult.txt", ui->lastSaveName); system(cmdBuf); system("grep '[*+]' mresult.txt > mresult2.txt"); //system("post -H < mresult.txt"); sprintf(cmdBuf,"post -t%s -H < mresult2.txt",ui->lastSaveName); system(cmdBuf); AcLogPrintf(0,4,"4:Ran command: %s\n",cmdBuf); } } } #if 0 if (strncmp(str,"Motion=",7)) return; if (!ui->lastOut || strcmp(ui->lastOut,str)) { if (ui->lastOut) { free(ui->lastOut); } ui->lastOut = strdup(str); } str +=7; while(*str) { unsigned int v; char *e; while(isspace(*str)) str++; if (!isdigit(*str)) break; v = strtol(str,&e,16); if (e==str) break; str = e; if (0 && i==0) { AcLogPrintf(0,4,"4: %d motions:\n",v); } else if (v & 0xf) { AcLogPrintf(0,4, "4: [%2d]=0x%02x circle cnt=%d.%d rot=%s start=%d %s\n", i, v, #if 0 (v>>1)&0x7, (v&1)?5:0, #else (v & 0xf), 0, #endif (v&0x40)?"ccw":"cw", (v>>4)&3, dirStr[(v>>4)&3]); } else { AcLogPrintf(0,4, "4: [%2d]=0x%02x end dir=%d %s\n", i, v, (v>>4)&3, dirStr[(v>>4)&3]); } i++; } #endif (void)ui; } //=========================================================================== // UiCmdMotion() - show motions //=========================================================================== static int UiCmdMotion(WandUi *ui, char *args) { int i; if (UiCmdDumpVars(ui,"0x800 0x900 z")) { AcLogPrintf(0,4,"0:Unable to read memory\n"); return -1; } for (i=0; i<sizeof(gbuf); i++) { unsigned int v = gbuf[i]; if (v == 0xff) break; if (i==0) { AcLogPrintf(0,4,"4: %d motions:\n",v); } else if (v & 0xf) { AcLogPrintf(0,4, "4: [%2d]=0x%02x circle cnt=%d.%d rot=%s start=%d\n", i, v, (v>>1)&0x7, (v&1)?5:0, (v&0x40)?"ccw":"cw", (v>>4)&3); } else { AcLogPrintf(0,4, "4: [%2d]=0x%02x end dir=%d\n", i, v, (v>>4)&3); } } return 0; } //=========================================================================== // UiCmdSaveName() - set saveName //=========================================================================== static int UiCmdSaveName(WandUi *ui, char *args) { while(isspace(*args)) args++; if (*args == 0) { if (ui->saveName) { free(ui->saveName); } ui->saveName = strdup(""); } else if (isupper(*args) || islower(*args) || *args == '_') { if (ui->saveName) { free(ui->saveName); } ui->saveName = strdup(args); args = ui->saveName; while(*args) { if (*args == 0) break; if (*args == 0 || isspace(*args)) { *args = 0; break; } if (isdigit(*args) || isupper(*args) || islower(*args) || *args == '_') { args++; } else { *(args++) = '_'; } } } else { AcLogPrintf(0,4,"0:Bad savename: '%s'\n",args); return -1; } AcLogPrintf(0,4,"3:Setting saveName='%s'\n",ui->saveName); return 0; } //=========================================================================== // UiCmdShowbuf() - show wand output buffer //=========================================================================== static int UiCmdShowbuf(WandUi *ui, char *args) { double ct_tap = 0; double ct = 0; int was_running = 0; int i; was_running = WandIsRunning(ui->wand); if (WandHalt(ui->wand)) { AcLogPrintf(0,4,"3:Unable to halt wand\n"); return -1; } if (UiCmdDumpVars(ui,"0x400 0x800 z")) { AcLogPrintf(0,4,"0:Unable to read memory\n"); return -1; } if (gbuf[0] == 0 && gbuf[1] == 0 && gbuf[2] == 0 && gbuf[3] == 0 && gbuf[4] == 0 && gbuf[5] == 0 && gbuf[6] == 0 && gbuf[7] == 0) { AcLogPrintf(0,4,"3:\nNo data found - not saving file\n\n"); return -1; } for (i=0; i<sizeof(gbuf); i+=4) { int t,imp,a, u; double tsec; if (gbuf[i+0] == 0 && gbuf[i+1] == 0 && gbuf[i+2] == 0 && gbuf[i+3] == 0) break; printf(" %02x %02x %02x %02x ", gbuf[i+0], gbuf[i+1], gbuf[i+2], gbuf[i+3]); t = (gbuf[i+0] <<8 ) + gbuf[i+1]; u = gbuf[i+2]; a = gbuf[i+3]; tsec = (double)t * 640.0/(1000*1000); if (a < 0x20) { int imp, magn, magx; char *dirStr[] = { "Down ", "Right", "Up ", "Left ", }; i+=4; imp = (gbuf[i+0] <<8 ) + gbuf[i+1]; magn = gbuf[i+2]; magx = gbuf[i+3]; printf("Angle t=%04x = %12.6f %12.6f sec " "Angle=0x%02x %d=%s imp=%04x " "mag=%02x %02x %02x", t, tsec, ct, a, ((a+4)&0x1f)>>3, dirStr[((a+4)&0x1f)>>3], imp, magn, imp/t, magx); if (magx >= 0x20) { printf(" taptime=%04x %12.6f", (int)((ct - ct_tap)*1000*1000/640), ct - ct_tap); ct_tap = ct; } printf("\n"); ct += tsec; } else if (a == 0xff) { printf("Pause t=%04x = %12.6f %12.6f sec\n", t, tsec, ct); ct += tsec; } else if (a == 0x81) { printf("nz t=%04x = %12.6f sec\n", imp, (double)imp * 640.0/(1000*1000)); } else if (a == 0x82) { printf("n t=%04x = %12.6f sec\n", imp, (double)imp * 640.0/(1000*1000)); } else if (a == 0x83) { printf("n imp=%04x \n", imp); } else { printf("0x%02x ?=%04x = %12.6f sec\n", a, imp, (double)imp * 640.0/(1000*1000)); } } #if 0 if (ui->lastOut) { UiDoWandOut(ui,0); } #endif if (was_running) { AcLogPrintf(0,4,"3:Running wand (debug mode)\n"); return WandCmdf(ui->wand, "D"); } return 0; } //=========================================================================== // UiCmdGraph() - get acc data from wand & draph it //=========================================================================== static int UiCmdGraph(WandUi *ui, char *args) { int was_running = 0; char *saveName; char name[1000]; FILE *fp; int i; int cnt; while(isspace(*args)) args++; if (*args != 0) { if (UiCmdSaveName(ui,args)) { return -1; } } was_running = WandIsRunning(ui->wand); if (WandHalt(ui->wand)) { AcLogPrintf(0,4,"3:Unable to halt wand\n"); return -1; } saveName = ui->saveName ? ui->saveName : ""; for (i=0; i<100000; i++) { if (i>=99999) { AcLogPrintf(0,4,"0:Could not find free filename\n"); return -1; } snprintf(name,sizeof(name)-1,"wpic%s%05d.txt",saveName,i); fp = fopen(name,"r"); if (!fp) break; fclose(fp); } AcLogPrintf(0,4,"3:\nGetting data for graph '%s'\n\n",name); cnt=0; while (1) { if (!UiCmdDumpVars(ui,"0x700 0xe00 z")) break; AcLogPrintf(0,4,"0:Unable to read memory\n"); if (++cnt > 4) { AcLogPrintf(0,4,"0:FAILED - GET ACORN\n"); return -1; } AcLogPrintf(0,4,"0:Retrying\n"); } if (gbuf[0] == 0 && gbuf[1] == 0 && gbuf[2] == 0 && gbuf[3] == 0 && gbuf[4] == 0 && gbuf[5] == 0 && gbuf[6] == 0 && gbuf[7] == 0) { AcLogPrintf(0,4,"3:\nNo data found - not saving file\n\n"); return -1; } fp = fopen(name,"w"); #define USE_WG_FMTB 1 #if USE_WG_FMTB // // new format: // // pause record // 1 relatve time (h) (sample count) // 0 relatve time (l) // 2 unused (0xff) // 3 angle (0xff indicates pause) // // non-pause record // 0 relatve time (h) (sample count) // 1 relatve time (l) // 2 unused (0xff) // 3 angle // 4 impulse (h) // 5 impulse (l) // 6 min mag // 7 max mag // // // if (fp) { fprintf(fp,"# formatB\n"); } { int tm = 0; int gotangle = 0; for (i=0; i<sizeof(gbuf); ) { int dt,a; if (gbuf[i+0] == 0 && gbuf[i+1] == 0 && gbuf[i+2] == 0 && gbuf[i+3] == 0 && gbuf[i+4] == 0 && gbuf[i+5] == 0 && gbuf[i+6] == 0 && gbuf[i+7] == 0) break; dt = (gbuf[i+0] <<8 ) + gbuf[i+1]; a = gbuf[i+3]; if (a==0xfe) { printf("Found end @ offset 0x%04x\n", i); break; } if (a==0xff) { printf(" ACC: 0x%04x: %08x pause %04x\n", i, tm,dt); if (gotangle) { if (fp) { fprintf(fp,"%8.1f %8.1f %8.1f %8.1f %8.1f %8.1f\n", (double)tm, (double)a, (double)0.0, (double)0.0, (double)0.0, (double)0.0); } tm += dt; } i += 4; } else { int imp = (gbuf[i+4] <<8 ) + gbuf[i+5]; int minmag = gbuf[i+6]; int maxmag = gbuf[i+2]; int flags = gbuf[i+7]; printf(" ACC: 0x%04x: %08x move %04x a=%02x " "imp=%04x min=%02x max=%02x flg=0x%02x\n", i, tm,dt, a,imp,minmag,maxmag,flags); if (fp) { fprintf(fp, "%8.1f %8.1f %8.1f %8.1f %8.1f %8.1f\n", (double)tm, (double)a, (double)imp, (double)minmag, (double)maxmag, (double)flags); } gotangle = 1; tm += dt; i+= 8; } } } #else // // old format: // byte // 0 abs time h (TMR1 time - 244usec period) // 1 abs time l // 2 angle // 3 mag // for (i=0; i<sizeof(gbuf); i+=4) { float time,x,y; if (gbuf[i+0] == 0 && gbuf[i+1] == 0 && gbuf[i+2] == 0 && gbuf[i+3] == 0) break; time = (gbuf[i+0] <<8 ) + gbuf[i+1]; x = gbuf[i+2]; y = gbuf[i+3]; if (fp) { fprintf(fp,"%8.1f %8.1f %8.1f\n", time,x,y); } } #endif if (fp) { static char cmd[1000]; fclose(fp); #if 0 #if USE_WG_FMTB snprintf(cmd,sizeof(cmd)-1,"wgg -b %s",name); #else snprintf(cmd,sizeof(cmd)-1,"wgg -a %s",name); #endif #endif AcLogPrintf(0,4,"3:Wrote %d points to %s\n",i/4,name); system(cmd); } sleep(1); AcLogPrintf(0,4,"3:\n\nSaved graph as '%s'\n\n\n",name); if (ui->lastSaveName) { free(ui->lastSaveName); } ui->lastSaveName = strdup(name); #if 0 if (ui->lastOut) { UiDoWandOut(ui,0); } #endif if (was_running) { AcLogPrintf(0,4,"3:Running wand (debug mode)\n"); return WandCmdf(ui->wand, "D"); } return 0; } //=========================================================================== // UiGetFileBuffer() - return what the file wants (merged with what wand has) //=========================================================================== // // Where file is known - set to file byte // else where wand is known - set to wand byte // else set to 0xff // // Returned buffer is a malloced buffer ui->addrMax bytes long // static void *UiGetFileBuffer(WandUi *ui, AcHexAddress *endp) { AcHexAddress start; AcHexAddress end; AcHexAddress size; AcHexByte *buf; if (!ui->hexFile) { AcLogPrintf(0,4,"0:No HEX file loaded\n"); return 0; } ui->addrMaxWand = AC_HEX_INVALID_ADDRESS; UiReadMinProgAddr(ui); start = ui->addrMin; end = (ui->addrMax + 64 + 63) & ~63UL; if (UiReadProg(ui,start,end-start,0)) return 0; size = end; if (size < ui->addrMaxFile) { size = ui->addrMaxFile; } buf = malloc(size); if (buf) { // // start all 0xff // memset(buf, 0xff, size); // // overwrite from wand // memcpy(buf+start, ui->wandProg+start, end-start); // // overwrite from file // AcHexGetBytes(ui->hexFile,0,buf,ui->addrMaxFile); } if (endp) *endp = end - 64; return buf; } //=========================================================================== // UiCompareProg() - compare wand program to buffer //=========================================================================== static int UiCompareProg( WandUi *ui, AcHexAddress addr, AcHexByte *data, AcHexOffset size) { unsigned long cnt = 0; AcHexAddress a; AcHexAddress end = addr + size; AcHexAddress errStart = 0; int isErr = 0; if (UiReadProg(ui,addr, end-addr, 0)) { AcLogPrintf(0,4,"0:\nError reading wand in UiCompareProg()\n"); return -1; } if (!data) return -1; for (a=addr; ; a++) { if (a>=end || data[a-addr] == ui->wandProg[a]) { if (isErr) { if (errStart == a-1) { AcLogPrintf(0,4,"3:Different at 0x%04lx\n", errStart); } else { AcLogPrintf(0,4,"3:Different from 0x%04lx - 0x%04lx\n", errStart, a-1); } isErr = 0; } if (a>=end) break; } else { if (!isErr) { isErr = 1; errStart = a; } AcLogPrintf(0,4,"6:Different at %08lx: file=%02x wand=%02x\n", (unsigned long)a, data[a-addr], ui->wandProg[a]); cnt++; } } AcLogPrintf(0,4,"0:Checked 0x%08lx - 0x%08lx\n", (unsigned long)ui->addrMin, (unsigned long)end); AcLogPrintf(0,4,"0:%lu bytes differ.\n",cnt); return cnt ? -1 : 0; } //=========================================================================== // UiCmdCmpProg() - compare wand program to hex file //=========================================================================== static int UiCmdCmpProg(WandUi *ui, char *args) { AcHexAddress end; AcHexByte *buf = UiGetFileBuffer(ui, &end); int rv = 0; if (end > ui->addrMax) { end = ui->addrMax; } if (ui->addrMin < end) { rv = UiCompareProg(ui, ui->addrMin, buf+ui->addrMin, end-ui->addrMin); } free(buf); return rv; } //=========================================================================== // UiDoProgram64() - program a 64 byte section of the wand //=========================================================================== static int UiDoProgram64( WandUi *ui, AcHexAddress addr, AcHexByte *buf, int force) { char cmdBuf[64*3+10]; char *s = cmdBuf; int i; int change = 0; char *reply; if (force) { change = 1; } else { for (i=0; i<64; i++) { if (ui->wandProg[addr+i] != buf[i]) change = 1; s += sprintf(s,"%02x ",buf[i]); } } if (!change) { AcLogPrintf(0,4,"4: %08lx - %08lx unchanged - skipping\n", (unsigned long)addr, (unsigned long)addr+63); return 0; } s[-1] = 0; UiSetProgDirty(ui, addr-64, addr+64); // // program command // reply = WandCmdfStr(ui->wand, "P%04x:%s",addr,cmdBuf); if (reply) { int err = 0; AcLogPrintf(0,4,"3:Wand Reply = '%s'\n",reply); if (strlen(reply) < 13) { err = -1; } else { reply[8] = 'X'; reply[9] = 'X'; reply[10] = 'X'; reply[11] = 'X'; if (strcmp(reply,"flash 0xXXXX: -> Written")) { err = -1; } } free(reply); return err; } else { AcLogPrintf(0,4,"0:Wand programming error\n"); return -1; } } //=========================================================================== // UiDoProgram() - program the wand //=========================================================================== // // confirm - ask for confirmation if this is set // addr - destination address in flash (must be multiple of 64) // size - number of bytes (must be multiple of 64) // data - bytes to write // // returns // 0 success // -1 failure // static int UiDoProgram( WandUi *ui, int confirm, AcHexAddress addr, AcHexByte *data, AcHexOffset size, int force) { AcHexAddress end = addr + size; AcHexAddress a; const char *reply; int errCnt = 2; if (!data) { return -1; } if (addr & 63) { AcLogPrintf(0,4,"0:\nBad addr in UiDoProgram: %04lx\n",(long)addr); return -1; } if (end & 63) { AcLogPrintf(0,4,"0:\nBad size in UiDoProgram: %04lx\n",(long)size); return -1; } // // read current vals if not known // if (!force) { if (UiReadProg(ui,addr, end-addr, 0)) { AcLogPrintf(0,4,"0:\nError reading wand in UiDoProgram()\n"); return -1; } } // // Confirm program request // if (confirm) { AcLogPrintf(0,4,"0:\nSure you want to program the wand? [y/n] "); fflush(stdout); reply = GetReply(); if (toupper(reply[0]) != 'Y') { AcLogPrintf(0,4,"0:Aborting program command\n"); return -1; } } // // program each section // for (a=addr; a<end; a+=64) { if (UiDoProgram64(ui,a,data + (a - addr),force)) { errCnt++; if (errCnt > 9) { AcLogPrintf(0,4,"7:Error while programming addr=%08lx!\n", (unsigned long)a); WandRecoverWait(ui->wand); return -1; } WandRecoverWait(ui->wand); a -= 64; } else if (errCnt) { errCnt--; } } AcLogPrintf(0,4,"3:Programmed 0x08lx - 0x%08lx\n", (long)addr, (long)end); AcLogPrintf(0,4,"3:Verifying...\n"); return UiCompareProg(ui, addr, data, size); } //=========================================================================== // UiCmdProgram() - program the wand //=========================================================================== static int UiCmdProgram(WandUi *ui, char *args) { AcHexAddress end; AcHexByte *buf = UiGetFileBuffer(ui, &end); AcHexAddress size = end - ui->addrMin; int rv; rv = UiDoProgram(ui, 1, ui->addrMin, buf + ui->addrMin, size, 0); free(buf); return rv; } //=========================================================================== // UiDoLoadKernel() - load new kernel //=========================================================================== static int UiDoLoadKernel(WandUi *ui, const char *basename, int confirm, int force) { char fn2[1000]; const char *filename; AcHexFile *hx = 0; AcHexByte *buf = 0; AcHexOffset loaderSize; AcHexOffset bufSize;; const char *reply; FILE *fp; if (!basename) basename=""; while(isspace(*basename)) basename++; if (!basename[0]) { basename = "kload.hex"; } filename = basename; if (WandHalt(ui->wand)) { AcLogPrintf(0,4,"3:Unable to halt wand\n"); return -1; } fp = fopen(filename,"r"); if (!fp) { snprintf(fn2,sizeof(fn2),"../sw/%s",basename); filename = fn2; fp = fopen(filename,"r"); } if (!fp) { snprintf(fn2,sizeof(fn2),"../sw/Archive/%s",basename); filename = fn2; fp = fopen(filename,"r"); } if (!fp) { snprintf(fn2,sizeof(fn2),"../sw/Archive/kload.v%s.hex",basename); filename = fn2; fp = fopen(filename,"r"); } if (!fp) { AcLogPrintf(0,4,"0:Could not find file %s\n",basename); return -1; } fclose(fp); hx = AcHexLoadFile(filename,0); if (!hx) { AcLogPrintf(0,4,"0:Error loading hex file '%s'\n",filename); return -1; } AcLogPrintf(0,4,"3:Loaded hex file '%s'\n",filename); do { kernelHeader hdr; AcHexOffset len; AcHexAddress oldAppMain; AcHexAddress newAppMain; AcHexAddress oldEnd; AcHexAddress newEnd; AcHexAddress dst; AcHexByte *bp; UiReadMinProgAddr(ui); if (!UiHeaderValid(ui, &ui->headerWand)) { AcLogPrintf(0,4,"3:Current Kernel header is invalid\n"); break; } if (ui->headerWand.version < KERNEL_MIN_VERSION) { AcLogPrintf(0,4,"3:Bad Current Kernel version (%d)\n", ui->headerWand.version); AcLogPrintf(0,4,"3:(Need version %d or higher\n", KERNEL_MIN_VERSION); break; } oldAppMain = (ui->headerWand.kk_app_main_high << 8) | ui->headerWand.kk_app_main_low; oldEnd = oldAppMain + 64; if (oldAppMain & 0x3f) { AcLogPrintf(0,4,"3:Bad old kk_app_main alignment: 0x%04x\n", oldAppMain); break; } if (oldEnd > KERNEL_LOADER_BEGIN) { AcLogPrintf(0,4,"3:old kk_app_main is too big: 0x%04x\n", oldAppMain); break; } len = AcHexGetBytes(hx, KERNEL_HEADER_ADDR, &hdr, sizeof(hdr)); if (len != sizeof(hdr)) { AcLogPrintf(0,4,"3:Could not get new kernel header\n"); break; } if (!UiHeaderValid(ui, &hdr)) { AcLogPrintf(0,4,"3:new Kernel header is invalid\n"); break; } if (hdr.version < KERNEL_MIN_VERSION) { AcLogPrintf(0,4,"3:Bad new Kernel version (%d)\n",hdr.version); AcLogPrintf(0,4,"3:(Need version %d or higher\n", KERNEL_MIN_VERSION); break; } newAppMain = (hdr.kk_app_main_high << 8) | hdr.kk_app_main_low; newEnd = newAppMain + 64; if (newAppMain & 0x3f) { AcLogPrintf(0,4,"3:Bad new kk_app_main alignment: 0x%04x\n", oldAppMain); break; } if (newEnd > KERNEL_LOADER_BEGIN) { AcLogPrintf(0,4,"3:new kk_app_main is too big: 0x%04x\n", oldAppMain); break; } loaderSize = AcHexGetRegion(hx, KERNEL_LOADER_BEGIN, 0, 0); if (loaderSize < 10) { AcLogPrintf(0,4,"3:Bad loader size (too small): 0x%lx\n", (long)loaderSize); break; } if (loaderSize > KERNEL_LOADER_NEW_KERNEL-KERNEL_LOADER_BEGIN) { AcLogPrintf(0,4,"3:Bad loader size (too big): 0x%lx\n", (long)loaderSize); break; } // // get buffer // bufSize = loaderSize; if (bufSize < newEnd) { bufSize = newEnd; } if (bufSize < 64) { bufSize = 64; } buf = malloc(bufSize + 64); if (!buf) break; // // Program the new kernel into flash // if (UiReadProg(ui, KERNEL_LOADER_NEW_KERNEL, newEnd, 0)) { break; } memcpy(buf, ui->wandProg+KERNEL_LOADER_NEW_KERNEL, newEnd + 64); AcHexGetBytes(hx, 0, buf, newAppMain); // // fill in app with return statements // bp = buf + newAppMain + KERNEL_APP_MAIN_OFFSET; bp[0] = 0x12; // return opcode bp[1] = 0x00; bp = buf + newAppMain + KERNEL_APP_ISR_LOW_OFFSET; bp[0] = 0x12; // return opcode bp[1] = 0x00; bp = buf + newAppMain + KERNEL_APP_ISR_HIGH_OFFSET; bp[0] = 0x11; // retfie 1 opcode bp[1] = 0x00; if (UiDoProgram(ui, confirm, KERNEL_LOADER_NEW_KERNEL, buf, newEnd, force)) { break; } // // Program the loader into flash // if (UiReadProg(ui, KERNEL_LOADER_BEGIN, loaderSize, 0)) { break; } memcpy(buf, ui->wandProg+KERNEL_LOADER_BEGIN, loaderSize + 64); AcHexGetBytes(hx, KERNEL_LOADER_BEGIN, buf, loaderSize); if (UiDoProgram( ui, confirm, KERNEL_LOADER_BEGIN, buf, (loaderSize + 63) & ~63UL, force)) { break; } // // Make kk_app_main jump to KERNEL_LOADER_BEGIN // Make kk_app_isr_low jump to KERNEL_LOADER_BEGIN // Make kk_app_isr_high jump to KERNEL_LOADER_BEGIN // if (UiReadProg(ui, oldAppMain, 64, 0)) { break; } memcpy(buf, ui->wandProg + oldAppMain, 64); dst = KERNEL_LOADER_BEGIN; bp = buf + KERNEL_APP_MAIN_OFFSET; bp[0] = ((dst >> 1) & 0xff); bp[1] = 0xEF; // goto opcode bp[2] = ((dst >> 9) & 0xff); bp[3] = ((dst >> 17) & 0xff) | 0xf0; bp = buf + KERNEL_APP_ISR_LOW_OFFSET; bp[0] = ((dst >> 1) & 0xff); bp[1] = 0xEF; // goto opcode bp[2] = ((dst >> 9) & 0xff); bp[3] = ((dst >> 17) & 0xff) | 0xf0; bp = buf + KERNEL_APP_ISR_HIGH_OFFSET; bp[0] = ((dst >> 1) & 0xff); bp[1] = 0xEF; // goto opcode bp[2] = ((dst >> 9) & 0xff); bp[3] = ((dst >> 17) & 0xff) | 0xf0; // // Confirm running // if (confirm) { AcLogPrintf(0,4,"0:\nSure you want to load kernel %d? [y/n] ", hdr.version); fflush(stdout); reply = GetReply(); if (toupper(reply[0]) != 'Y') { AcLogPrintf(0,4,"0:Aborting kload command\n"); break; } } if (UiDoProgram(ui, 0, oldAppMain, buf, 64, force)) { break; } // // invalidate stuff // UiSetProgDirty(ui, 0, newEnd+64); // // Run the loader // AcLogPrintf(0,4,"0:\nRunning the kernel loader...\n"); if (WandCmdf(ui->wand, "D")) { break; } if (buf) { free(buf); } AcHexDelete(hx); return 0; } while(0); AcLogPrintf(0,4,"0:\n\n"); AcLogPrintf(0,4,"0:ERROR: Failed to load new kernel\n"); AcLogPrintf(0,4,"0:\n\n"); if (buf) { free(buf); } AcHexDelete(hx); return -1; } //=========================================================================== // UiCmdLoadKernel() - load new kernel //=========================================================================== static int UiCmdLoadKernel(WandUi *ui, char *args) { return UiDoLoadKernel(ui,args ? args : "",1,0); } //=========================================================================== // UiCmdShowFile() - show hex file //=========================================================================== static int UiCmdShowFile(WandUi *ui, char *args) { if (!ui->hexFile) { AcLogPrintf(0,4,"0:No HEX file loaded\n"); return -1; } AcHexPrint(ui->hexFile,1); return 0; } //=========================================================================== // AcSystemCmdf() - run a system command and get output //=========================================================================== // rvp - if not NULL return value oes here // lenp - length of stdio (chars) returned here if not NULL // fmt,... - command to run // // returns stdout of command (free it when done) // char *AcSystemCmdf(int *rvp, long *lenp, const char *fmt,...) { static const char *tmpfile = TMP_FILENAME; va_list va; char buf[1000]; int rv = -1; int cnt; char *out = 0; long len; va_start(va, fmt); cnt = vsnprintf(buf,sizeof(buf)-2,fmt,va); va_end(va); if (cnt) { cnt = snprintf(buf+cnt,sizeof(buf)-cnt-1," > %s",tmpfile); } if (cnt && cnt < sizeof(buf)-3) { rv = system(buf); } if (rv == 0) { FILE *fp = fopen(tmpfile,"r"); if (fp) { fseek(fp,0,SEEK_END); len = ftell(fp); fseek(fp,0,SEEK_SET); out = malloc(len+1); if (len) { len = fread(out,1,len,fp); } fclose(fp); } } if (rvp) *rvp = rv; if (lenp) *lenp = len; return out; } //=========================================================================== // UiGetSym() - lookup a symbol to get addr and val (both optional) //=========================================================================== // ui - // sym - name of symbol (use addr=0x00 if NULL) // offset - add this to symbol to get address // addrp - if not null, return address here // valp - if not null, return value here // // return 0 on success, -1 on fail static int UiGetSym( WandUi *ui, char *sym, long offset, unsigned long *addrp, unsigned long *valp) { FILE *fp; char buf[1000]; int rv = 0; int err = 0; int gotfirst = 0; if (sym) { snprintf(buf,sizeof(buf),"./ws '\\<%s\\>' > %s",sym,TMP_FILENAME); buf[sizeof(buf)-1]=0; rv = system(buf); } else { fp = fopen(TMP_FILENAME, "w"); if (!fp) return -1; fprintf(fp,"v_null = 0, type = constant\n"); fclose(fp); } if (rv) { return -1; } fp = fopen(TMP_FILENAME, "r"); if (!fp) { return -1; } while(1) { unsigned long addr = 0; unsigned long val = 0; int gotaddr = 0; int gotval = 0; char *s = buf; char *t = ""; int c; while(1) { c = getc(fp); if (c == EOF || c == '\n' || isspace(c) || c=='=') break; if (s-buf > sizeof(buf)-2) break; *(s++) = c; } *(s++) = 0; while(c==' ' || c=='=') { c = getc(fp); } while(isxdigit(c)) { gotaddr = 1; addr *= 16; addr += isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10); c = getc(fp); } if (c==',') { char *tp = s; while(c!='t' && c!='\n' && c!=EOF) c = getc(fp); if (c!='t') break; c = getc(fp); if (c!='y') break; c = getc(fp); if (c!='p') break; c = getc(fp); if (c!='e') break; c = getc(fp); while(c==' ' || c=='=') c = getc(fp); while(isalpha(c)) { if (s-buf > sizeof(buf)-2) break; *(s++) = c; c = getc(fp); } *(s++) = 0; t = tp; } while(c!=EOF && c!='\n') { c = getc(fp); } if (gotaddr && (t[0] || !gotfirst)) { addr += offset; if (!strcmp(t,"constant") || buf[0]=='v') { int try=5; while(try--) { char *wand_output; if (!valp) break; wand_output = WandCmdfStr(ui->wand,"V%04x",addr); val = 0; if (wand_output) { char *e; AcLogPrintf(0,4,"9:wand_output='%s'\n",wand_output); s = wand_output; while(*s && *s!=':') s++; if (*s) s++; val = strtoul(s,&e,16); if (e && e != s) { gotval = 1; try = 0; } else { val = 0; } free(wand_output); } } } else if (valp) { err = -1; } if (gotval || buf[0] || addr) { if (gotfirst && ((addrp && *addrp != addr) || (valp && *valp != val))) { err = -1; // more than 1 matching symbol } if (addrp) { *addrp = addr; } if (valp) { *valp = val; } gotfirst = 1; } } if (c==EOF) break; } fclose(fp); if (!gotfirst) err = -1; return err; } //=========================================================================== // UiCmdShowSyms() - load a hex file //=========================================================================== static int UiCmdShowSyms(WandUi *ui, char *args) { FILE *fp; char buf[1000]; int rv; const char *pattern = args; snprintf(buf,sizeof(buf),"./ws '%s' > %s",pattern,TMP_FILENAME); buf[sizeof(buf)-1]=0; rv = system(buf); if (rv) { AcLogPrintf(0,4,"3:No symbols match pattern '%s'\n",pattern); return -1; } fp = fopen(TMP_FILENAME, "r"); if (!fp) { AcLogPrintf(0,4,"0:Could not read tmp file '%s'\n",TMP_FILENAME); return -1; } while(1) { unsigned long addr = 0; int val = 0; int gotval = 0; char *s = buf; char *t = ""; int c; while(1) { c = getc(fp); if (c == EOF || c == '\n' || isspace(c) || c=='=') break; if (s-buf > sizeof(buf)-2) break; *(s++) = c; } *(s++) = 0; while(c==' ' || c=='=') { c = getc(fp); } while(isxdigit(c)) { addr *= 16; addr += isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10); c = getc(fp); } if (c==',') { char *tp = s; while(c!='t' && c!='\n' && c!=EOF) c = getc(fp); if (c!='t') break; c = getc(fp); if (c!='y') break; c = getc(fp); if (c!='p') break; c = getc(fp); if (c!='e') break; c = getc(fp); while(c==' ' || c=='=') c = getc(fp); while(isalpha(c)) { if (s-buf > sizeof(buf)-2) break; *(s++) = c; c = getc(fp); } *(s++) = 0; t = tp; } while(c!=EOF && c!='\n') { c = getc(fp); } if (!strcmp(t,"constant") || buf[0]=='v') { int try=5; while(try--) { char *wand_output = WandCmdfStr(ui->wand,"V%04x",addr); if (wand_output) { char *e; AcLogPrintf(0,4,"9:wand_output='%s'\n",wand_output); s = wand_output; while(*s && *s!=':') s++; if (*s) s++; val = strtoul(s,&e,16); if (e && e != s) { gotval = 1; try=0; } free(wand_output); } } } if (gotval || buf[0] || addr) { if (gotval) { AcLogPrintf(0,4,"3: 0x%02x = %3d = ",val,val); } else { AcLogPrintf(0,4,"3: "); } AcLogPrintf(0,4,"3:*0x%04lx = *%s\n",addr,buf); } if (c==EOF) break; } fclose(fp); return 0; } //=========================================================================== // UiCmdParseError() //=========================================================================== static int UiCmdParseError(WandUi *ui, char *args) { unsigned long rcon; unsigned long stkptr; unsigned long error; unsigned long val; char *prompt = WandGetPrompt(ui->wand); int err = 0; WandQuiet(ui->wand); AcLogPrintf(0,4,"0:\n"); if (UiGetSym(ui,"vk_boot0_rcon",0,0,&rcon)) { rcon = 0xff; } if (UiGetSym(ui,"vk_boot0_stkptr",0,0,&stkptr)) { stkptr = 0; } if (!strncmp(prompt+3,"Error>",6)) { char *e; err = strtoul(prompt,&e,16); if (!e || e == prompt) { err = 0; } } if (UiGetSym(ui,"vk_boot0_error",0,0,&error)) { error = err; } else { if (!err) err = error; } if ( (rcon & 0x02) == 0) { AcLogPrintf(0,4,"0: POWER UP RESET\n"); } else if ((rcon & 0x10) == 0) { if (err) { AcLogPrintf(0,4,"0: RESET INSTR FOR Error 0x%02x\n",err); } else { AcLogPrintf(0,4,"0: RESET INSTRUCTION\n"); } } else if ((rcon & 0x01) == 0) { AcLogPrintf(0,4,"0: BROWN-OUT RESET\n"); } else if ((stkptr & 0x80)) { AcLogPrintf(0,4,"0: STACK OVERFLOW RESET\n"); } else if ((stkptr & 0x40)) { AcLogPrintf(0,4,"0: STACK UNDEFLOW RESET\n"); } else if ((rcon & 0x08) == 0) { AcLogPrintf(0,4,"0: WATCHDOG TIMEOUT RESET\n"); } else if ((rcon & 0x04) == 0) { AcLogPrintf(0,4,"0: INTERRUPTED FROM SLEEP\n"); } else { AcLogPrintf(0,4,"0: RESET BUTTON WAS PRESSED\n"); } AcLogPrintf(0,4,"0:\n"); AcLogPrintf(0,4,"0: rcon = 0x%02x\n",rcon); AcLogPrintf(0,4,"0: stkptr = 0x%02x\n",stkptr); AcLogPrintf(0,4,"0: error = 0x%02x\n",err); AcLogPrintf(0,4,"0:\n"); AcLogPrintf(0,4,"0:Wand Error 0x%02x\n",err); if (error && (error != err)) { AcLogPrintf(0,4,"0:vk_boot0_error = 0x%02x\n",error); } system("grep -h '^ERROR_[^;]*[Ee][Qq][Uu]' " "../sw/kernel.inc ../sw/wand.asm | " "detab"); UiCmdShowSyms(ui,"boot._error"); AcLogPrintf(0,4, "0:RCON: IPEN SBOREN <rsvd> /RI | /TO /PD /POR /BOR\n"); UiCmdShowSyms(ui,"\\<RCON\\>"); UiCmdShowSyms(ui,"boot._rcon"); AcLogPrintf(0,4, "0:STKPTR: STKFUL STKUNF <rsvd> SP4 | SP3 SP2 SP1 SP0\n"); UiCmdShowSyms(ui,"STKPTR"); UiCmdShowSyms(ui,"boot._stkptr"); AcLogPrintf(0,4, "0:bbits: 0 0 0 0 | 0 <cold> <first> <serial>\n"); UiCmdShowSyms(ui,"vk_boot0_bbits"); AcLogPrintf(0,4, "0:boot0_runstate: 00=run 04=debug 08=halt 0c=error 10=breakpt\n"); UiCmdShowSyms(ui,"vk_boot0_runstate"); AcLogPrintf(0,4, "0:runstate_bits: 00=run 01=debug 03=halt 0b=error 07=breakpt\n"); UiCmdShowSyms(ui,"vki_runstate_bits"); if (UiGetSym(ui,"vk_where",0x500,0,&val)) { AcLogPrintf(0,4,"3:Could not lookup symbol 'vk_where'\n"); } else { AcLogPrintf(0,4, "0:vk_where = %3d = 0x%02x (last DB_WHERE macro call)\n", (int)val, (int)val); } if (UiGetSym(ui,"vk_where2",0x500,0,&val)) { AcLogPrintf(0,4,"3:Could not lookup symbol 'vk_where2'\n"); } else { AcLogPrintf(0,4, "0:vk_where2 = %3d = 0x%02x (last DB_WHERE2 macro call)\n", (int)val, (int)val); } if (UiGetSym(ui,"vk_iwhere",0x500,0,&val)) { AcLogPrintf(0,4,"3:Could not lookup symbol 'vk_iwhere'\n"); } else { AcLogPrintf(0,4, "0:vk_iwhere = %3d = 0x%02x (last DB_IWHERE macro call)\n", (int)val, (int)val); } AcLogPrintf(0,4,"0:Stack:\n"); UiCmdDumpVars(ui,"0x400 0x41f"); AcLogPrintf(0,4,"0:\nvalues of 0x000-0x0ff at boot:\n"); UiCmdDumpVars(ui,"0x500 0x5ff"); AcLogPrintf(0,4,"0:\n"); WandUnQuiet(ui->wand); free(prompt); return 0; } //=========================================================================== // UiCmdLoadHex() - load a hex file //=========================================================================== static int UiCmdLoadHex(WandUi *ui, char *args) { const char *filename = args; AcHexFile *hx; if (!filename || !filename[0]) { filename = ui->hexFile ? AcHexGetFilename(ui->hexFile) : 0; if (!filename || !filename[0]) { filename = DEFAULT_HEX_FILE; } } hx = AcHexLoadFile(filename,0); if (!hx) { AcLogPrintf(0,4,"0:Error in AcHexLoadFile(\"%s\")\n",filename); return -1; } AcLogPrintf(0,4,"3:Loaded hex file \"%s\"\n",filename); if (ui->hexFile) { AcHexDelete(ui->hexFile); } ui->hexFile = hx; // // get top address we care about // { AcHexAddress addr = 0; AcHexAddress addrMax = 0; while (1) { AcHexOffset len; len = AcHexGetRegion(hx,addr,&addr,0); if (!len) break; if (addr > addrMax && addr+len <= PROG_MAX) { addrMax = addr+len; } addr += len; } AcHexGetBytes(hx,0x10,&ui->headerFile,sizeof(ui->headerFile)); ui->addrMaxUser = AC_HEX_INVALID_ADDRESS; ui->addrMinUser = AC_HEX_INVALID_ADDRESS; ui->addrMaxFile = (addrMax + 63) & ~63UL; UiCheckAddrMaxMin(ui); } return 0; } //=========================================================================== // UiCmdMake() //=========================================================================== static int UiCmdMake(WandUi *ui, char *args) { int rv = system("cd .. && make"); if (rv) { AcLogPrintf(0,4,"0:\n\nBUILD FAILED - not loading hex file\n"); return -1; } AcLogPrintf(0,4,"3:\n*****Build success! - Reloading file*****\n\n"); return UiCmdLoadHex(ui,""); } //=========================================================================== // UiInitLog() //=========================================================================== static void UiInitLog(WandUi *ui, int append) { if (ui->log) { AcLogDestroy(ui->log); } ui->log = AcLogCreate("wwlog.txt",append,1); ui->logToWand = AcLogCreateSource(ui->log,"+ ToWand"); ui->logFromWand = AcLogCreateSource(ui->log,"+FromWand"); ui->logCmd = AcLogCreateSource(ui->log," Cmd"); ui->logMsg = AcLogCreateSource(ui->log," Messages"); // // Program assumes static log source assignment as follows // if (ui->logToWand != 1) { printf("Error: ui->logToWand = %d != 1\n",ui->logToWand); exit(1); } if (ui->logFromWand != 2) { printf("Error: ui->logToWand = %d != 2\n",ui->logFromWand); exit(1); } if (ui->logCmd != 3) { printf("Error: ui->logToWand = %d != 3\n",ui->logMsg); exit(1); } if (ui->logMsg != 4) { printf("Error: ui->logToWand = %d != 4\n",ui->logMsg); exit(1); } } //=========================================================================== // UiCmdHelp() //=========================================================================== static int UiCmdHelp(WandUi *ui, char *args) { const UiCmd *c; int maxlen = 0; AcLogPrintf(0,4,"0:" "LEDS (X=on B=blink -=off ?=dont-care) (from base to tip)\n" "---------------------------------------------------------\n" "(base) (tip)\n" " ------ = Debug/Run\n" " X--B-? = Halt\n" " XXXB-? = Error\n" " XX-B-? = Breakpoint\n" " X-B--- = Sync\n" "\n" "Commands\n" "--------\n"); for(c=ui->cmdList; c->name; c++) { int l = c->namelen; if (c->helpArgs) { l += strlen(c->helpArgs) + 2; } if (c->help1 && l > maxlen) { maxlen = l; } } for(c=ui->cmdList; c->name; c++) { if (c->help1) { int l = 0; l += AcLogPrintf(0,4,"0:%s ",c->name); if (c->helpArgs) { l += AcLogPrintf(0,4,"0:%s ",c->helpArgs); } if (l < maxlen) { AcLogPrintf(0,4,"0:%*s",maxlen-l,""); } AcLogPrintf(0,4,"0:- %s\n", c->help1); } } AcLogPrintf(0,4,"0:" "\n" "Wand Commands (preceded by ':')\n" "-------------------------------\n"); WandCmdf(ui->wand, "I"); return 0; } //=========================================================================== // UiCmdQuit() //=========================================================================== static int UiCmdQuit(WandUi *ui, char *args) { ui->quit = 1; return 0; } //=========================================================================== // UiCmdHalt() //=========================================================================== static int UiCmdHalt(WandUi *ui, char *args) { return WandHalt(ui->wand); } //=========================================================================== // UiCmdDebug() //=========================================================================== static int UiCmdDebug(WandUi *ui, char *args) { return WandCmdf(ui->wand, "D"); } //=========================================================================== // UiCmdInitLog() //=========================================================================== static int UiCmdInitLog(WandUi *ui, char *args) { UiInitLog(ui,0); return 0; } //=========================================================================== // UiCmdRun() //=========================================================================== static int UiCmdRun(WandUi *ui, char *args) { const char *reply; AcLogPrintf(0,4,"0:Are you sure you want to RUN? (Y/N) "); fflush(stdout); reply = GetReply(); if (toupper(reply[0]) == 'Y') { return WandCmdf(ui->wand, "R"); } return -1; } //=========================================================================== // UiCmdTime() //=========================================================================== static int UiCmdTime(WandUi *ui, char *args) { int rv; int doSet = 0; unsigned long hourOld, hourOld2, hourAddr, hourNew, hourNow; unsigned long minOld, minOld2, minAddr, minNew, minNow; unsigned long secOld, secNew, secNow; unsigned long qsecOld, qsecAddr, qsecNew; signed long hourDelta, minDelta, secDelta; struct timeval timeNow; struct tm tmNow; while(1) { if (UiGetSym(ui,"vk_hour",0,&hourAddr,&hourOld)) { AcLogPrintf(0,4,"0:Error finding smbol vk_hour\n"); return -1; } if (UiGetSym(ui,"vk_minute",0,&minAddr,&minOld)) { AcLogPrintf(0,4,"0:Error finding smbol vk_min\n"); return -1; } if (UiGetSym(ui,"vk_qsec",0,&qsecAddr,&qsecOld)) { AcLogPrintf(0,4,"0:Error finding smbol vk_qsec\n"); return -1; } if (gettimeofday(&timeNow,0)) { AcLogPrintf(0,4, "0:Error in gettimeofday\n"); return -1; } if (UiGetSym(ui,"vk_minute",0,&minAddr,&minOld2)) { AcLogPrintf(0,4,"0:Error finding smbol vk_min\n"); return -1; } if (UiGetSym(ui,"vk_hour",0,&hourAddr,&hourOld2)) { AcLogPrintf(0,4,"0:Error finding smbol vk_hour\n"); return -1; } if (hourOld2 == hourOld && minOld2 == minOld) break; } secOld = qsecOld/4; // // Get current local time // localtime_r(&timeNow.tv_sec, &tmNow); hourNow = tmNow.tm_hour; minNow = tmNow.tm_min; secNow = tmNow.tm_sec; switch(tmNow.tm_wday) { case 0: hourNow += 24 * 2; break; case 6: hourNow += 24; break; default: break; } if (args && args[0] ) { while(isspace(*args)) args++; if (!strncmp(args,"now",3)) { args += 3; while(isspace(*args)) args++; if (*args) { AcLogPrintf(0,4, "0:Error - trailing characters\n"); return -1; } hourNew = hourNow; minNew = minNow; secNew = secNow; qsecNew = secNew * 4; doSet = 1; args = 0; } } if (args && args[0]) { char *e; while(isspace(*args)) args++; hourNew = strtol(args,&e,0); if (!e || e == args || *e != ':') { AcLogPrintf(0,4, "0:Error in format(h). Use hh:mm:ss (decimal or 0xhex)\n"); return -1; } args = e+1; while(isspace(*args)) args++; minNew = strtol(args,&e,0); if (!e || e == args || *e != ':') { AcLogPrintf(0,4, "0:Error in format(m). Use hh:mm:ss (decimal or 0xhex)\n"); return -1; } args = e+1; while(isspace(*args)) args++; secNew = strtol(args,&e,0); if (!e || e == args) { AcLogPrintf(0,4, "0:Error in format(s). Use hh:mm:ss (decimal or 0xhex)\n"); return -1; } args = e; while(isspace(*args)) args++; if (*args) { AcLogPrintf(0,4, "0:Error in format. Trailing characters\n"); return -1; } if (hourNew<0 || hourNew>255) { AcLogPrintf(0,4, "0:Error in format. Bad hour (0-255)\n"); return -1; } if (minNew<0 || minNew>255) { AcLogPrintf(0,4, "0:Error in format. Bad minute (0-60)\n"); return -1; } if (secNew<0 || secNew>255) { AcLogPrintf(0,4, "0:Error in format. Bad second (0-59)\n"); return -1; } qsecNew = secNew * 4; doSet = 1; } if (doSet) { // // setting takes about 3 sec - add 3 sec // qsecNew += 3*4; while (qsecNew >= 60*4) { qsecNew -= 60*4; minNew += 1; } while (minNew >= 60) { minNew -= 60; hourNew += 1; } rv = WandRecoverWait(ui->wand); if (rv) { AcLogPrintf(0,4, "0:Unable to recover wand prompt (s0)\n"); return -1; } rv = WandCmdf(ui->wand, "V%04x:%02x", (int)qsecAddr,1); if (rv) { AcLogPrintf(0,4, "0:Error writing qsec(0)\n"); return -1; } rv = WandRecoverWait(ui->wand); if (rv) { AcLogPrintf(0,4, "0:Unable to recover wand prompt (m0)\n"); return -1; } rv = WandCmdf(ui->wand, "V%04x:%02x", (int)minAddr,1); if (rv) { AcLogPrintf(0,4, "0:Error writing minute(0)\n"); return -1; } rv = WandRecoverWait(ui->wand); if (rv) { AcLogPrintf(0,4, "0:Unable to recover wand prompt (h)\n"); return -1; } rv = WandCmdf(ui->wand, "V%04x:%02x", (int)hourAddr, (int)hourNew); if (rv) { AcLogPrintf(0,4, "0:Error writing hour\n"); return -1; } rv = WandRecoverWait(ui->wand); if (rv) { AcLogPrintf(0,4, "0:Unable to recover wand prompt (m)\n"); return -1; } rv = WandCmdf(ui->wand, "V%04x:%02x", (int)minAddr, (int)minNew); if (rv) { AcLogPrintf(0,4, "0:Error writing minute\n"); return -1; } rv = WandRecoverWait(ui->wand); if (rv) { AcLogPrintf(0,4, "0:Unable to recover wand prompt (s)\n"); return -1; } rv = WandCmdf(ui->wand, "V%04x:%02x", (int)qsecAddr, (int)qsecNew); if (rv) { AcLogPrintf(0,4, "0:Error writing qsec\n"); return -1; } rv = WandRecoverWait(ui->wand); if (rv) { AcLogPrintf(0,4, "0:Unable to recover wand prompt (e)\n"); return -1; } } AcLogPrintf(0,4, "0:%s wand time is %d:%02d:%02d (0x%02x:0x%02x:0x%02x)\n", doSet?"Old ":"Current", (int)hourOld,(int)minOld,(int)qsecOld/4, (int)hourOld,(int)minOld,(int)qsecOld/4); secDelta = secOld - secNow; minDelta = minOld - minNow; hourDelta = hourOld - hourNow; while(secDelta < 0) { secDelta += 60; minDelta -= 1; } while(minDelta < 0) { minDelta += 60; hourDelta -= 1; } if (hourDelta == 0 && minDelta==0 && secDelta==0) { AcLogPrintf(0,4, "0:Wand clock %s ON TIME +/- 1 sec\n", doSet?"was":"is"); } else if (hourDelta >= 0) { AcLogPrintf(0,4, "0:Wand clock %s AHEAD %2d:%02d:%02d\n", doSet?"was":"is", hourDelta, minDelta, secDelta); } else { hourDelta = -hourDelta; minDelta = -minDelta; secDelta = -secDelta; while(secDelta < 0) { secDelta += 60; minDelta -= 1; } while(minDelta < 0) { minDelta += 60; hourDelta -= 1; } AcLogPrintf(0,4, "0:Wand clock %s BEHIND %2d:%02d:%02d\n", doSet?"was":"is", hourDelta, minDelta, secDelta); } if (doSet) { AcLogPrintf(0,4, "0:\nNew wand time is %d:%02d:%02d (0x%02x:0x%02x:0x%02x)\n", (int)hourNew,(int)minNew,(int)qsecNew/4, (int)hourNew,(int)minNew,(int)qsecNew/4); UiCmdTime(ui, 0); } return 0; } //=========================================================================== // UiCmdSetTop() //=========================================================================== static int UiCmdSetTop(WandUi *ui, char *args) { int err = -1; char *e=0; unsigned long n; n = strtol(args,&e,16); if (e && e!=args && n > 100) { ui->addrMaxUser = (n + 63) & ~63UL; UiCheckAddrMaxMin(ui); err = 0; } ui->wandProgAllClean = 0; AcLogPrintf(0,4,"0:Ignoring addresses above %08lx\n", (unsigned long)ui->addrMax); return err; } //=========================================================================== // UiCmdSetBottom() //=========================================================================== static int UiCmdSetBottom(WandUi *ui, char *args) { int err = -1; char *e=0; unsigned long n; n = strtol(args,&e,16); if (e && e!=args) { ui->addrMinUser = n & ~63UL; UiCheckAddrMaxMin(ui); err = 0; } ui->wandProgAllClean = 0; AcLogPrintf(0,4,"0:Ignoring addresses below %08lx\n", (unsigned long)ui->addrMin); return err; } //=========================================================================== // UiCmdDebugLevel() //=========================================================================== static int UiCmdDebugLevel(WandUi *ui, char *args) { static const int DEFAULT_DEBUG_LEVEL = 4; int val = ui->debugLevel; if (args) { while(isspace(args[0])) args++; if (args[0]) { char *e; val = strtol(args,&e,0); if (!e || e==args) { val = DEFAULT_DEBUG_LEVEL; } } } if (val < 0) { val = DEFAULT_DEBUG_LEVEL; } else { AcLogPrintf(0,4,"0:Wand debugLevel is now %d\n",val); AcLogPrintf(0,4,"0:" " 0 = minimal\n" " 3 = sparse\n" " 4 = normal (default)\n" " 5 = show wand errors\n" " 8 = verbose\n" " 9 = debug messges - all\n" ); } ui->debugLevel = val; WandDebugLevel(ui->wand,val); AcLogSetDebugLevel(ui->log,val); return 0; } //=========================================================================== // UiCmdNewInit() //=========================================================================== static int UiCmdNewInit(WandUi *ui, char *cmdline) { AcHexAddress end; AcHexByte *buf; AcHexAddress size; int rv; const char *reply; AcLogPrintf(0,4, "0:\nSure you want to program entire wand from scratch? [y/n] "); fflush(stdout); reply = GetReply(); if (toupper(reply[0]) != 'Y') { AcLogPrintf(0,4,"0:Aborting NEW command\n"); return -1; } // // invalidate local copy of wand mem // UiSetProgDirty(ui, 0,0); // // load latest kernel // rv = UiDoLoadKernel(ui,0,0,0); if (rv) { AcLogPrintf(0,4,"0:Error loading kernel\n"); return rv; } // // wait for kernel load to complete // while(1) { rv = WandRecoverWait(ui->wand); // // -2 means timeout. Loop until non-timeout. // if (rv != -2) break; } if (rv!=0) { AcLogPrintf(0,4,"0:Aborting NEW command while loading kernel!!\n"); return -1; } // // set time // UiCmdTime(ui,"now"); // // load latest program // buf = UiGetFileBuffer(ui, &end); size = end - ui->addrMin; rv = UiDoProgram(ui, 0, ui->addrMin, buf + ui->addrMin, size, 0); free(buf); // // check time and set it again // UiCmdTime(ui,"now"); return rv; } //=========================================================================== // UiWandCommand() //=========================================================================== static int UiWandCommand(WandUi *ui, char *cmdline) { int rv; if (cmdline[0] == 'R') { return UiCmdRun(ui,cmdline); } rv = WandCmdf(ui->wand, "%s",cmdline); if (!rv) { // allow wand command to take up to a minute rv = WandPromptWaitUsec(ui->wand,60 * 1000000); } return rv; } //=========================================================================== // UiInitGetCmdList() //=========================================================================== static void UiInitGetCmdList(WandUi *ui) { static UiCmd g_cmd_list[] = { { UiCmdQuit, "quit", UI_CFLG_NOARGS,0, "quit", }, { UiCmdHalt, "halt", UI_CFLG_NOARGS,0, "halt the wand", }, { UiCmdDebug, "debug", UI_CFLG_NOARGS,0, "debug (run) the program", }, { UiCmdRun, "RUN", UI_CFLG_NOARGS,0, "run the program in RUN mode", }, { UiCmdNewInit, "NEW", UI_CFLG_NOARGS,0, "initialize/verify a new wand", }, { UiCmdHelp, "?", 0,0, "print this help (/ works too)", }, { UiCmdHelp, "/", 0,}, { UiCmdShowSyms, "symbol", UI_CFLG_NEEDARGS,0, "lookup a symbol (show its value too)", }, { UiCmdLoadHex, "load", 0,"<file>", "load a hex file (default = reload same)",}, { UiCmdSetTop, "top", UI_CFLG_NEEDARGS,"<addr>", "set max address we care about in " "program memory", }, { UiCmdSetBottom, "bottom", UI_CFLG_NEEDARGS,"<addr>", "set min address we care about in " "program memory", }, { UiCmdInvalProg, "inval", UI_CFLG_NOARGS|UI_CFLG_EXACTMATCH,0, "invalidate local copy of wand prog data",}, { UiCmdShowFile, "file", UI_CFLG_NOARGS,0, "show contents of file", }, { UiCmdDebugLevel, "DEBUG", 0,0, "set toggle wand debugging level", }, { UiCmdProgram, "prog", UI_CFLG_NOARGS|UI_CFLG_EXACTMATCH,0, "program the wand", }, { UiCmdDumpProg, "pdump", 0,0, "dump *cached* program (from read cmd)", }, { UiCmdDumpVars, "vdump", UI_CFLG_NEEDARGS,"<s> <e>", "dump variable memory from <s> to <e>", }, { UiCmdDumpEEProm, "eeprom", 0,0, "dump the wand eeprom", }, { UiCmdCmpProg, "compare", UI_CFLG_NOARGS,0, "compare file vs *cached* wand program", }, { UiCmdSaveName, "Savename", 0,0, "set the base name for saving files",}, { UiCmdGraph, "graph", 0,0, "graph data from 0x400 - 0x800",}, { UiCmdShowbuf, "Bufshow", 0,0, "show buffer 0x400 - 0x800",}, { UiCmdMotion, "motion", UI_CFLG_NOARGS,0, "show motions at 0x800-0x900", }, { UiCmdInitLog, "killlog", UI_CFLG_NOARGS,0, "empty the log file", }, { UiCmdLoadKernel, "kload", 0,"<kload.hex>", "Load a new kernel", }, { UiCmdParseError, "error", UI_CFLG_NOARGS,0, "show error info", }, { UiCmdMake, "make", UI_CFLG_NOARGS,0, "run make in the sw dir and reload prog", }, { UiCmdTime, "time", 0,"<time>", "print or set time hh:mm:ss (decimal)", }, { 0,0,0,0, }, }; UiCmd *c = g_cmd_list; while (c->name) { c->namelen = strlen(c->name); if (!c->help2 || !c->help2[0]) { c->help2 = c->help1; } c++; } ui->cmdList = g_cmd_list; } //=========================================================================== // UiFindCommand() - parse cmdline into info //=========================================================================== static const UiCmd *UiFindCommand( WandUi *ui, char *cmdline, char **args) { static UiCmd wand_command = { UiWandCommand, ":", 0, "Send a command to the wand", }; const UiCmd *best = 0; const UiCmd *c; char *s; int len; while(isspace(*cmdline)) cmdline++; for (s=cmdline; *s && !isspace(*s); s++); len = s-cmdline; if (*cmdline == ':') { if (args) *args = cmdline+1; return &wand_command; } for(c=ui->cmdList; c->name; c++) { if (len > c->namelen) continue; if (!strncmp(cmdline,c->name,len)) { if (best) { AcLogPrintf(0,4,"0:Error: Ambiguous command\n"); best = 0; break; } best = c; } } if (best) { while(isspace(*s)) s++; if (args) *args = s; if ((best->flags & UI_CFLG_NOARGS) && *s) { AcLogPrintf(0,4,"0:Error: No args allowed with command '%s'\n", best->name); return 0; } if ((best->flags & UI_CFLG_NEEDARGS) && !*s) { AcLogPrintf(0,4,"0:Error: Argument(s) required with command '%s'\n", best->name); return 0; } if ((best->flags & UI_CFLG_EXACTMATCH) && len != best->namelen) { return 0; } } return best; } //=========================================================================== // UiHandleStdin() //=========================================================================== static int UiHandleStdin(int fd, void *data) { WandUi *ui = data; char buf[1000]; int cnt = read(fd, buf, sizeof(buf)-1); char *s = buf; int rv = 0; // // strip off CR/LF // buf[cnt] = 0; while(1) { if (!*s || *s == '\n' || *s == '\r') { *s = 0; break; } s++; } for (s=buf; isspace(*s); s++); AcLogPrintf(ui->log,ui->logCmd,"%s\n",buf); AcLogFlush(ui->log); AcLogPrompt(0,0,-2); if (s[0] != 0) { char *args = 0; const UiCmd *cmd = UiFindCommand(ui, buf, &args); if (cmd) { rv = cmd->func(ui,args); } else { AcLogPrintf(0,4,"0:Error: command line syntax\n"); rv = -1; } } WandPrompt(ui->wand); return ui->quit; } //=========================================================================== // UiCreate() //=========================================================================== static WandUi *UiCreate(void) { unsigned int size; WandUi *ui = calloc(1,sizeof(WandUi)); if (!ui) return 0; ui->saveName = strdup(""); UiInitLog(ui,1); UiInitGetCmdList(ui); ui->addrMaxUser = AC_HEX_INVALID_ADDRESS; ui->addrMaxFile = AC_HEX_INVALID_ADDRESS; ui->addrMaxWand = AC_HEX_INVALID_ADDRESS; ui->addrMinUser = AC_HEX_INVALID_ADDRESS; UiCheckAddrMaxMin(ui); ui->wandProg = malloc(PROG_MAX); if (!ui->wandProg) return 0; memset(ui->wandProg,0xff,PROG_MAX); size = sizeof(unsigned int) * ((PROG_MAX>>(6+5))+1); ui->wandProgDirty = malloc(size); if (!ui->wandProgDirty) return 0; memset(ui->wandProgDirty,0xff,size); // // initialize wand // ui->wand = WandInit(); if (!ui->wand) { AcLogPrintf(0,4,"0:Error in WandInit()\n"); return 0; } WandOutCallback(ui->wand, UiDoWandOut, ui); UiCmdDebugLevel(ui, "-1"); // set default debugLevel // // create select group // ui->selectGroup = AcFdGroupCreate(); if (!ui->selectGroup) { AcLogPrintf(0,4,"0:Error in AcFdGroupCreate\n"); free(ui->wand); return 0; } // // add wand serial port handler // AcFdGroupAdd( ui->selectGroup, WandGetFd(ui->wand), WandHandleSerial, ui->wand); // // add stdin handler (fd=0) // AcFdGroupAdd(ui->selectGroup, 0, UiHandleStdin, ui); // // return pointers // return ui; } //=========================================================================== // UiDestroy() //=========================================================================== static void UiDestroy(WandUi *ui) { AcFdGroupDestroy(ui->selectGroup); WandShutdown(ui->wand); if (ui->saveName) { free(ui->saveName); } AcLogDestroy(ui->log); } //=========================================================================== // main() //=========================================================================== int main(int argc, char *argv[]) { WandUi *ui = UiCreate(); if (!ui) { printf("Error in UiCreate()\n"); return 1; } UiCmdLoadHex(ui,0); WandPromptWaitUsec(ui->wand,1000000); // // This loops waiting for wand or stdin input until "q" command // input from wand calls WandHandleSerial() // input from stdin calls UiHandleStdin() // WandPrompt(ui->wand); AcFdGroupLoop(ui->selectGroup); UiDestroy(ui); printf("\n"); return 0; } |
This file Copyright (C) 2006 by Nathan (Acorn) Pooley
Go to TOP Wand page
Go to Acorn's personal webpage
Go to Hogwarts website: www.gotohogwarts.com
Snout: www.snout.org/game
Gadgets of Justice Unlimited
Snout GC (Wiki)
Snout Wiki
File created by do_doc at Wed May 30 03:30:03 PDT 2007