📄 logterm.c
字号:
extern List angel_TQI_Run;extern struct angel_TaskLog* angel_DebugTaskBase;extern struct angel_TaskLog* angel_DebugTaskArea;extern int angel_DebugStartTaskCount;extern int angel_DebugQueueTaskCount;extern angel_TaskQueueItem angel_TQ_Pool[POOLSIZE];static char *rbnames[6] ={ "Intr", "SWI", "Undef", "Abort", "Yield", "Fatal"};static char *typenames[11] ={ "", "StartTsk", "QueueTsk", "IntHand", "SaveTsk", "Yield", "SWIHand", "BRKHand", "Wait", "Abort", "DelTask"};static char *tasknames[7] ={ "IdleLoop", "AngelInit", "Application", "AngelCallBack", "ApplCallBack", /* not used */ "PollLoop", "AngelWantLock"};static char *taskstates[5] ={ "Undefined", "Defined", "Runnable", "Running", "Blocked"};static void log_RegblockName(void *rb){ if (rb == 0) logterm_PutString(" "); else if (rb >= (void *)&Angel_GlobalRegBlock[0] && rb < (void *)&Angel_GlobalRegBlock[RB_NumRegblocks]) { int index = (angel_RegBlock*)rb - &Angel_GlobalRegBlock[0]; log_printf("RB %5s", rbnames[index]); } else if (rb >= (void *)&angel_TQ_Pool[0] && rb < (void *)&angel_TQ_Pool[POOLSIZE]) { int index = (angel_TaskQueueItem*)rb - &angel_TQ_Pool[0]; log_printf("TQ %5d", index); } else log_printf("rb%6lx", rb);}static void log_ShowRegblock(angel_RegBlock *rb){ log_printf(" pc = %08lx cpsr = %08lx\n", rb->pc, rb->cpsr); log_printf(" r0 = %08lx r1 = %08lx r2 = %08lx r3 = %08lx\n", rb->r0, rb->r1, rb->r2, rb->r3); log_printf(" r4 = %08lx r5 = %08lx r6 = %08lx r7 = %08lx\n", rb->r4, rb->r5, rb->r6, rb->r7); log_printf("USR: r8 = %08lx r9 = %08lx r10 = %08lx r11 = %08lx\n", rb->r8usr, rb->r9usr, rb->r10usr, rb->r11usr); log_printf(" r12 = %08lx r13 = %08lx r14 = %08lx\n", rb->r12usr, rb->r13usr, rb->r14usr); log_printf("FIQ: r8 = %08lx r9 = %08lx r10 = %08lx r11 = %08lx\n", rb->r8fiq, rb->r9fiq, rb->r10fiq, rb->r11fiq); log_printf(" r12 = %08lx r13 = %08lx r14 = %08lx spsr = %08lx\n", rb->r12fiq, rb->r13fiq, rb->r14fiq, rb->spsrirq); log_printf("IRQ: r13 = %08lx r14 = %08lx spsr = %08lx\n", rb->r13irq, rb->r14irq, rb->spsrirq); log_printf("SVC: r13 = %08lx r14 = %08lx spsr = %08lx\n", rb->r13svc, rb->r14svc, rb->spsrsvc); log_printf("UND: r13 = %08lx r14 = %08lx spsr = %08lx\n", rb->r13und, rb->r14und, rb->spsrund); log_printf("ABT: r13 = %08lx r14 = %08lx spsr = %08lx\n", rb->r13abt, rb->r14abt, rb->spsrabt);}static void log_ShowTaskItem(int tqi, angel_TaskQueueItem *tq){ log_printf("Task Queue %d: (%08lx) %s\n" "Next = %08lx, Index = %d, Type = %s, State = %s, Priority = %u\n", tqi, tq, (tq->n.n_name) ? tq->n.n_name : "", tq->n.n.mn_next, tq->n.n_type, tasknames[tq->type], taskstates[tq->state], tq->n.n_pri); log_printf("Stack Base = %08lx, Limit = %08lx, Entrypoint = %08lx\n", tq->stack->stackBase, tq->stack->stackLimit, tq->entryPoint); log_printf("Signal Wait = %08lx, Signal Bits = %08lx\n", tq->signalWaiting, tq->signalReceived); log_ShowRegblock(&angel_TQ_Pool[tqi].rb);}/* * Function: log_task * Purpose: The trace action. trace syntax is: * task show current task stats * task <number> show <number> prior task switches * * Pre-conditions: none. * * Params: * Input: argc, argv - "main" argc/argv pair containing args. argv[0] * is name of command (i.e. "trace"). * * Returns: 0 */static int log_task(int argc, char **argv){ if (argc == 1) /* no args */ { logterm_PreWarn(WL_INFO); log_printf("Log Base: %8lx\n", angel_DebugTaskBase); log_printf("Next Entry @: %8lx\n", angel_DebugTaskArea); log_printf("Started Tasks: %8ld\n", angel_DebugStartTaskCount); log_printf("Queued Tasks: %8ld\n", angel_DebugQueueTaskCount); log_printf("Deferred Block %8ld\n", angel_SWIDeferredBlock); log_printf("Processing SWI %8ld\n", angel_SWIReturnToApp); logterm_PostWarn(0); } else if (argc > 1 && __rt_strcmp(argv[1], "list") == 0) /* at least one arg */ { angel_TaskQueueItem *tq = (angel_TaskQueueItem *)FirstNode(&angel_TQI_Run); logterm_PreWarn(WL_INFO); while(!AtEndOfList((MinNode*)tq)) { log_ShowTaskItem(tq->n.n_type, tq); tq = (angel_TaskQueueItem *)Succ((MinNode*)tq); if (!AtEndOfList((MinNode*)tq)) logterm_PutString("\n"); } logterm_PostWarn(0); } else if (argc > 1 && __rt_strcmp(argv[1], "log") == 0) /* at least one arg */ { int ntasks; char *ep; struct angel_TaskLog *tl = angel_DebugTaskArea; struct angel_TaskLog *tlbase = angel_DebugTaskBase; logterm_PreWarn(WL_INFO); ntasks = stoi(argv[2], &ep); if (ep > argv[1] && ntasks > 0 && ntasks < 100000) { tl--; /* tl starts off pointing at next free block */ while(ntasks > 0 && tl >= tlbase) { log_printf("%9d: %8s ", tl->count, typenames[tl->id]); log_RegblockName(tl->taskblock); logterm_PutString(", "); log_RegblockName(tl->regblock); log_printf(", from: [cpsr %08lx, sp %08lx] ", tl->cur_CPSR, tl->cur_SP); log_printf("to: [pc %08lx, cpsr %08lx, sp %08lx, r0 %08lx]\n", tl->rb_PC, tl->rb_CPSR, tl->rb_SP, tl->rb_r0); logterm_flushbuf(); tl--; ntasks--; } } else logterm_PutString("task: not a number\n"); logterm_PostWarn(0); } else if (argc > 2 && __rt_strcmp(argv[1], "rb") == 0) { int i; logterm_PreWarn(WL_INFO); for (i = 0; i < RB_NumRegblocks; i++) { if (__rt_strcmp(argv[2], rbnames[i]) == 0) { log_printf("Global Regblock %s:\n", rbnames[i]); log_ShowRegblock(&Angel_GlobalRegBlock[i]); break; } } logterm_PostWarn(0); } else if (argc > 2 && __rt_strcmp(argv[1], "tq") == 0) { char *ep; int tqi = stoi(argv[2], &ep); logterm_PreWarn(WL_INFO); if (ep > argv[2] && tqi >= 0 && tqi < POOLSIZE) { angel_TaskQueueItem *tq = &angel_TQ_Pool[tqi]; log_ShowTaskItem(tq->n.n_type, tq); } else logterm_PutString("Invalid queue index\n"); logterm_PostWarn(0); } return 0;}/* * Function: log_execute * Purpose: Accept a command string which will be split up by into * overwriting spaces into individual strings indexed by * an array of string pointers, to create a C library like * argc/argv pair. Look up the command (the first such string, * if any) in the list of known commands, and if found call * the execution function. If the command is not found, print * an error message ("Eh?"!!) and return. * * Unless the command set log_deferredprompt, print a prompt * for the user once command processing complete. * * Pre-conditions: log_Initialise called * * Params: * Input: cmd - pointer to command string. * * Returns: nothing. */static void log_execute(char *cmd){ char *s = cmd; char *argv[MAXARGS]; int argc, i; for(argc = 0; argc < MAXARGS && *s != '\0';) { while(*s == ' ' || *s == '\t') s++; /* * if quoted arg, search for end of quote; * else search for next whitespace. */ if (*s == '\"') { argv[argc++] = ++s; while(*s != '\"' && *s != '\0') s++; } else { argv[argc++] = s; while(*s != ' ' && *s != '\t' && *s != '\0') s++; } /* * replace character which ended search (if not EOS) * with EOS (to terminate this arg) and increment s * so we can search for more... */ if (*s == ' ' || *s == '\t' || *s == '\"') { *s = '\0'; s++; } } argv[argc] = NULL; if (argv[0] == NULL) goto finish; for (i = 0; i < log_ncmds; i++) { switch(__rt_strcmp(argv[0], log_cmds[i].str)) { case 0: /* match ! */ log_cmds[i].pfn(argc, argv); goto finish; case -1: /* no match found */ log_emitstr("Eh? Didn't understand: "); log_emitstr(argv[0]); log_emitch('\n'); goto finish; case 1: /* still looking; */ break; } }finish: if (log_deferredprompt == FALSE) log_emitstr(PROMPT); return;}/* main_table "", do_nothing, 0, "help", do_execute, helptable, NULL, helptable "", do_general_help, helptable, "stat", do_specific_help, "Print Statistics\0syntax: ..." *//* * Function: log_serialexecute * Purpose: Wrapper for log_execute, when that function is being called * from the serializer. It basically maintains various locks, * and resets the command buffer... * * Pre-conditions: none. * * Params: * Input: cmd - the command to execute * * Output: none * * Returns: none. */static void log_serialexecute(char *cmd){ static char buf[CMDBUFSIZE]; __rt_strcpy(buf, cmd); log_commandbuf[0] = '\0'; log_cursor = 0; log_buflock = FALSE; log_emitstr("Executing: "); log_emitstr(buf); log_output(TRUE); log_commandbuf[0] = '\0'; log_cursor = 0; log_execute(buf); log_cmdlock = FALSE;}/* * Function: log_processchar * Purpose: CALLED AS AN INTERRUPT ROUTINE! * * Process a character received from the controlling * terminal. Form a command string for execution by * log_execute, using the serialiser to enable the * commands to overcome the 'fast' limitation of int * handlers. * * Handle some simplistic echo/deletion codes too. * * If log_deferredprompt is set, we must print a prompt * before eching the character. We must also bracket * the operation with a request to kill run time trace * ouptut temporarily while a command is typed. * * Pre-conditions: log_Initialise, interrupt handler set up * * Params: * Input: ch - the character read from the terminal * empty-stack - passed in by the int handler for the * serialiser. * * Returns: nothing. */static void log_processchar(char ch, unsigned int empty_stack){ /* can't process -- previous command hasn't copied buffer yet */ if (log_buflock) return; if (log_deferredprompt) { log_emitstr(PROMPT); log_output(FALSE); log_deferredprompt = FALSE; } switch(ch) { case '\b': /* backspace */ case '\177': /* delete */ if (log_cursor > 0) { log_emitstr("\b \b"); /* delete */ log_commandbuf[log_cursor--] = '\0'; log_commandbuf[log_cursor] = '\0'; } if (log_cursor == 0) { log_deferredprompt = TRUE; log_emitstr("\b\b \b\b"); /* length of prompt */ log_output(TRUE); } break; case '\n': case '\r': log_emitch('\n'); if ( 1 /* empty_stack == 0*/ ) /* if called from 'pause' */ { log_output(TRUE); log_execute(log_commandbuf); log_commandbuf[0] = '\0'; log_cursor = 0; } else { /* can't execute; previous command hasn't finished yet */ if (log_cmdlock) break; /* lock buffer while we're copying it from log_commandbuf; lock command interp. until command completed */ log_cmdlock = TRUE; log_buflock = TRUE; Angel_SerialiseTask(0, (angel_SerialisedFn)log_serialexecute, (void *)log_commandbuf, empty_stack, &Angel_GlobalRegBlock[RB_Interrupted]); } break; default: if (ch >= 32) /* note: ch signed, so only 32-126 get through (127 above)! */ { log_commandbuf[log_cursor++] = ch; log_commandbuf[log_cursor] = '\0'; log_emitch(ch); log_output(FALSE); } break; }}/* * Function: log_output * Purpose: To enable/disable real-time trace output while commands are * being typed. If log_tracing is TRUE, then overall we want tracing, * while if false, we don't. log_ouptut is intended to bracket * regions of code when trace would be a bad idea. * * Pre-conditions: none. * * Params: * Input: enable true if we're leaving a sensitive area, * false if entering one. * * Returns: Nothing */static void log_output(int enable){ if (enable && log_tracing) { log_set_logging_options(log_get_logging_options() | WL_PRINTMSG); } else { log_set_logging_options(log_get_logging_options() & ~WL_PRINTMSG); }}void logterm_fatalhandler(void){ log_printf("\nFatal error. Type 'help' for command list.\n"); log_printf("CPU Registers:\n"); logterm_flushbuf(); log_ShowRegblock(&Angel_GlobalRegBlock[RB_Fatal]); log_printf("\n"); log_emitstr(PROMPT); log_deferredprompt = FALSE; log_paused = FALSE; log_pause(0, 0);}/* * Function: int_* * Purpose: Set of handlers for the various prioritised interrupts. * These routines do all the urgent processing required * for the interrupt condition * * Pre-conditions: Processor is in IRQ / FIQ mode, with a minimal stack, * AND NO STACK LIMIT SET UP. * * Params: * Input: devid device ID of the driver * port serial port identifier * empty_stack top of the stack * * Returns: Nothing */static void int_txrdy(unsigned int empty_stack){ unsigned int lsr; IGNORE(empty_stack); /* * we really couldn't care less about these signals (in * fact, we shouldn't really ever get this interrupt * because it is never enabled); read the status to clear * the interrupt and go away again */ lsr = LOG_GET_STATUS(LOGTERM_PORT) ;}static void int_rxrdy(unsigned int empty_stack){ unsigned int intStatus ; /* * keep looping for as long as there are characters * in the Rx FIFO */ intStatus = LOG_GET_STATUS(LOGTERM_PORT) ; if ( LOG_RX_DATA(intStatus) ) { do { unsigned char ch = LOG_GET_CHAR(LOGTERM_PORT); log_processchar(ch, empty_stack); intStatus = LOG_GET_STATUS(LOGTERM_PORT) ; } while ( LOG_RX_DATA(intStatus) ) ; }}/* * Function: angel_LogtermIntHandler * Purpose: Entry point for interrupts from the ST16C552 UART * See documentation for angel_IntHandlerFn in devdriv.h */void angel_LogtermIntHandler(unsigned int ident, unsigned int devid, unsigned int empty_stack){ unsigned int IntSource, IntStatus ; IGNORE(ident); IGNORE(devid); IntSource = LOG_READ_INTERRUPT(LOGTERM_PORT) ; if (IntSource & LOG_RX_INTERRUPT) { int_rxrdy(empty_stack) ; } else if (IntSource & LOG_TX_INTERRUPT) { int_txrdy(empty_stack) ; } else { /* Unknown interrupt source */ /* clear out any errors by reading the line status register */ IntStatus = LOG_GET_STATUS(LOGTERM_PORT) ; }}#endif /* DEBUG && !MINIMAL ANGEL *//* EOF logterm.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -