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

📄 logterm.c

📁 ARM入门的好帮手.包含了从简单到相对较复杂的程序.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* -*-C-*-
 *
 * $Revision: 1.1.2.4 $
 *   $Author: rivimey $
 *     $Date: 1998/01/12 21:22:34 $
 *
 * Copyright (c) 1997 Advanced RISC Machines Limited.
 * All Rights Reserved.
 *
 *   Project: ANGEL
 *
 *     Title: Debug interface via Serial writes to 16c552 serial port B.
 */

#if DEBUG == 1 && (!defined(MINIMAL_ANGEL) || MINIMAL_ANGEL == 0)

#include <string.h>

#include "channels.h"
#include "pid.h"
#include "st16c552.h"
#include "logging.h"
#include "logging/logterm.h"
#include "debug.h"
#include "support.h"

#define SAVEBUFSIZE     2048    /* max #words in save buffer -- min 6 words/message */
#define MAXARGS         32      /* max number of distinct args on cmd line */
#define CMDBUFSIZE      128     /* max number of characters on command line */
#define OUTPUTBUFSIZE   64      /* number of buffered characters from message before flush */

#ifndef UNUSED
#define UNUSED(x)       (0 ? (x) = (x) : 0)
#endif

static unsigned long msgsavebuf[SAVEBUFSIZE];
static struct LogSaveBuffer savebuf;

static char log_commandbuf[CMDBUFSIZE];
static int log_cursor = 0;

static WarnLevel logterm_level;
static char  logterm_buf[OUTPUTBUFSIZE];
static char *logterm_pos;
static char *logterm_end;
static int log_tracing = TRUE;
static int log_deferredprompt = FALSE;
static int log_buflock = FALSE;
static int log_cmdlock = FALSE;

/* static void setupsave(void); */
void log_emitch(char ch);
void log_emitstr(char *str);
static void log_output(int enable);
static void log_processchar(char ch, unsigned int empty_stack);

static int log_dump(int argc, char **argv);
static int log_echo(int argc, char **argv);
static int log_ver(int argc, char **argv);
static int log_help(int argc, char **argv);
static int log_trace(int argc, char **argv);
static int log_go(int argc, char **argv);
static int log_pause(int argc, char **argv);
static int log_stat(int argc, char **argv);
static int log_level(int argc, char **argv);
static int log_format(int argc, char **argv);

static struct 
{
    char *str;
    int (*pfn)(int argc, char **argv);
    char *desc, *helpstr;
} log_cmds[] =
{   /* These must be kept in sorted order by name */
    { "dump",  log_dump,  "Dump\n",
                          "syntax: dump <start addr> [ <end addr> | +<len> ]\n"
    },
    { "echo",  log_echo,  "Echo\n",
                          "syntax: echo <words>\n"
    },
    { "format",log_format,"Show / set the per-line format string\n",
                          "syntax: format [<new string>]\n"
    },
    { "go",    log_go,    "Undo pause; reenable ints\n",
                          "syntax: go\n"
    },
    { "help",  log_help,  "Command help\n",
                          "syntax: help [command]\n"
    },
    { "pause", log_pause, "Pause Angel; disable ints\n",
                          "syntax: pause\n"
    },
    { "stat",  log_stat,  "Display internal statistics info\n",
                          "syntax: stat\n"
    },
    { "level", log_level,  "Set the minimum log level displayed.\n",
                          "syntax: level [info|warn|err]\n"
    },
    { "trace", log_trace, "Enable/disable tracing or display trace buffer\n",
                          "syntax: trace           -- display current settings\n"
                          "        trace <n>       -- show <n> lines of buffer\n"
                          "        trace <n>       -- show <n> lines of buffer\n"
                          "        trace on | off  -- enable/disable run-time trace\n"
    },
    { "ver",   log_ver,   "Display Angel version info\n",
                          "syntax: ver\n"
    },
};
static const int log_ncmds = sizeof(log_cmds)/sizeof(log_cmds[0]);

/*
 * NT's HyperTerminal needs CRLF, not just LF!
 */
#define LOGTERM_ADD_CR_TO_LF

#pragma no_check_stack

#if DEFBAUD == 9600
# define BAUDVALUE Baud9600

#elif DEFBAUD == 19200
# define BAUDVALUE Baud19200

#elif DEFBAUD == 38400
# define BAUDVALUE Baud38400

#elif DEFBAUD == 57600
# define BAUDVALUE Baud57600

#elif DEFBAUD == 115200
# define BAUDVALUE Baud115200

#else
# error invalid baud rate
#endif

#include "banner.h"
#define LOGONMESSAGE "\n\n" ANGEL_BANNER "Type 'help' for more info.\n\n"
#define PROMPT       "% "

/*
 * the Interrupt Enable register is write-only, so we use the
 * scratch register to keep track of currently enabled Ints
 */
#define IER_set(u, f)   ((u)->ier = ((u)->spr |= (f)))
#define IER_clr(u, f)   ((u)->ier = ((u)->spr &= (~(f))))
#define IER_reset(u)    ((u)->ier = ((u)->spr = 0));

/*
 * macros to control Interrupt Enable Register in various sensible ways
 */
#define st16c552_EnableTxInterrupt(u)  (IER_set((u), TxReadyInt))
#define st16c552_DisableTxInterrupt(u) (IER_clr((u), TxReadyInt))
#define st16c552_EnableRxInterrupt(u)  (IER_set((u), RxReadyInt))
#define st16c552_DisableRxInterrupt(u) (IER_clr((u), RxReadyInt))

/*
 * macros to get and put serial characters
 */
#define st16c552_GetChar(u)     ((u)->rhr)
#define st16c552_PutChar(u, c)  ((u)->thr = (c))

/*
 * macro to test "fullness" of transmit buffer
 */
#define st16c552_TxBuffFull(u)   (((u)->lsr & (1 << 5)) == 0)
#define st16c552_TxBuffEmpty(u)  (((u)->lsr & (1 << 6)) != 0)

#define st16c552_RxBuffEmpty(u)  (((u)->lsr & (1 << 0)) == 0)


/*
 * prefix for lines not at start of message -- see stuff in putchar too
 */
#define PREFIXLEN   6

/*
 * prototypes
 */

/*
 *  Function: stoi
 *   Purpose: string to integer conversion; like atoi but doesn't pull in
 *            the rest of the c library!
 *
 *  Pre-conditions: none.
 *
 *    Params:
 *       Input: s - pointer to (base-10) number in ASCII
 *
 *       Output: e - pointer to last character converted
 *              
 *   Returns: number converted
 */

static int stoi(char *s, char **e)
{
    int i, sign = 0, base = 10;
    while(*s == ' ')
        s++;

    switch(*s)
    {
        case '-':
            sign = -1;
            s++;
            break;

        case '0':
            if (s[1] == 'x')
            {
                base = 16;
                s+=2;
            }
            break;

        case '+':
            s++;
            sign = 1;
            break;

        default:
            sign = 1;
            break;
    }
    i = 0;
    if (base == 10)
    {
        while(*s >= '0' && *s <= '9')
        {
            i = (i * 10) + (*s - '0');
            s++;
        }
    }
    else
    {
        while((*s >= '0' && *s <= '9') || (*s >= 'a' && *s <= 'f'))
        {
            if (*s >= 'a')
                i = (i * 16) + (*s - 'a' + 10);
            else
                i = (i * 16) + (*s - '0');
            s++;
        }
    }
    i *= sign;
    *e = s;
    
    return i;
}

void logterm_flushbuf(void);

/*
 *  Function: logterm_Initialise
 *   Purpose: 
 *
 *  Pre-conditions: none.
 *
 *    Params:
 *       Input: 
 *
 *   Returns: 0.
 */

/* REMEMBER: This routine gets called VERY EARLY!! */
bool logterm_Initialise(void)
{
    ST16C552Reg *const serchip = (LOGTERM_PORT == ST16C552_IDENT_A) ?
        (ST16C552Reg *)NISA_SER_A : (ST16C552Reg *)NISA_SER_B;

    /*
     * Interrupt Enable Register - all interrupts off
     */
    IER_reset(serchip);

    /*
     * wait for current transmits to finish
     */
    while (!st16c552_TxBuffEmpty(serchip))
        continue;

    /*
     * Modem Control Register - DTR* and RTS* outputs high; INT
     * pin tri-stated; Rx and Tx "disabled" by setting chip in
     * loopback mode.
     */
    serchip->mcr = 0x10;

    /*
     * FIFO Control Register - FIFO enabled, but Rx and Tx
     * FIFOs empty; RxRDY and TxRDY mode 1; FIFO interrupt
     * trigger level = 1.
     */
    serchip->fcr = 0x0f;

    /*
     * Enable divisor latch via the Line Control Register, and
     * set the baud rates
     */
    serchip->lcr = 0x80;
    serchip->dll = (unsigned char)(BAUDVALUE & 0xff);
    serchip->dlm = (unsigned char)((BAUDVALUE >> 8) & 0xff);

    /*
     * OK, set the operational values for the LCR: 8-bit words,
     * 1 stop bit, no parity
     */
    serchip->lcr = 0x03;

    /*
     * take the chip out of loopback, and enable interrupts; DTR* and
     * RTS* outputs are forced low.
     */
    serchip->mcr = 0x0b;

    /*
     * output is polled, but input is interrupt-driven.
     */
    st16c552_DisableTxInterrupt(serchip);
    st16c552_EnableRxInterrupt(serchip);
    
    /*
     * print a logon banner to say we're here!
     */
    log_emitstr(LOGONMESSAGE);
    log_emitstr(PROMPT);
    
    log_deferredprompt = FALSE;
    log_tracing = TRUE;
    
    log_setupsave(&savebuf, msgsavebuf, SAVEBUFSIZE);    
    log_set_logging_options(WL_SAVEMSG|WL_PRINTMSG);
    log_set_log_id(LOG_ALWAYS, 1);

    /* this works because it's polled input... interrupts
     * are disabled in this code
     */
    log_pause(0,0);
    
    return 0;
}

struct LogSaveBuffer *log_getlogtermbuf(void)
{
    return &savebuf;
}

bool logterm_PreWarn(WarnLevel level)
{
    /*
     * set up the buffer pointers... reset in flushbuf
     */
    logterm_pos = logterm_buf;
    logterm_end = (logterm_buf + sizeof(logterm_buf) - 1);
    logterm_level = level;
    return TRUE;
}

void logterm_flushbuf(void)
{
    char *p;
    
    p = logterm_buf;
    while(p < logterm_pos)
    {
        log_emitch(*p++);
    }

    logterm_pos = logterm_buf;
    logterm_end = logterm_buf + sizeof(logterm_buf) - 1;
}


int logterm_PutChar(char c)
{
    if (logterm_pos >= logterm_end)
        logterm_flushbuf();

    *logterm_pos++ = c;

    return 0;
}

void logterm_PostWarn(unsigned int len)
{
    if (len > 0)
        logterm_flushbuf();
}


/*
 * Show a number nlines of messages from the trace buffer, working
 * back from the current insert position.
 *
 * This is done by starting at the insert position and using the
 * count value (which is at 'insert' - 1) to skip backwards through
 * the buffer until either the oldest data is reached or the required
 * number of lines is found.
 *
 * Then work forward, calling log_logprint() to print the text.
 *
 */
static void log_showitems(struct LogSaveBuffer *sb, int nlines)
{
    int count, message_start = sb->message;
    unsigned long *ptr = sb->current;

    if (ptr == 0 || *ptr == 0) /* nothing to do */
        return;

    ptr--;      /* normally, savebufinsert points at next free slot */

    /*
     * while we haven't got to the start point  -- either the start of
     * data, or the item we want to start with, or the oldest item in
     * the buffer is reached, skip back from the insert point.
     *
     * Note: 'start of data' and 'oldest' are differently encoded -- start
     * of data is indicated by a zero count, written when the buffer is
     * set up. 'oldest' is reached when the current pointer is larger
     * than the insert pointer, and (ptr - count) is less.
     */
    count = nlines;
    while(count > 0 && *ptr != 0)
    {
        /*
         * got to oldest; no more (complete) messages available.
         */
        if (ptr >= sb->current && (ptr - (*ptr & 0xff)) < sb->current)
            break;

        /*
         * if this message marks the end of a line (flagged by the top
         * bits of the word being set), decrement the message number too.
         */
        if (*ptr & ~0xff)
        {
            message_start--;
            count--;
        }

        /* skip one more back, wrapping around the beginning. */
        ptr -= (*ptr & 0xff);
        if (ptr < sb->start)
                ptr += sb->size;
    }

    /*
     * now run forward, printing each line from the data in the buffer. Of
     * course, pointer values are printed from memory, and so may be incorrect
     * if the program changed that memory in the meantime....
     */
    count = nlines;
    while(count > 0)
    {

⌨️ 快捷键说明

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