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

📄 memtrace.c

📁 umon bootloader source code, support mips cpu.
💻 C
字号:
/* memtrace.c:
 *	This file contains CLI and API code to support a simple memory trace
 *	capability that allows application developers to call mon_memtrace()
 *	with a "printf-like" formatted arglist and the formatted string is
 *	put into a circular buffer in some allocated RAM space.
 *	The circular buffer is established by "mtrace cfg" command, then all
 *	subsequent calls to mon_memtrace() will have the formatted string
 *	destined for that buffer.
 *
 *	To keep the output formatted clean, the user of mon_memtrace() should
 *	not include any line-feeds in the string.  Each time mon_memtrace() is
 *	called, a line feed and sequence number is prepended to the string.
 *	This allows the dump to simply run through the buffer using putchar().
 *
 *  Both the mon_memtrace() API function and the dump facility in the CLI
 *  will deal with buffer wrapping.
 *
 *	General notice:
 *	This code is part of a boot-monitor package developed as a generic base
 *	platform for embedded system designs.  As such, it is likely to be
 *	distributed to various projects beyond the control of the original
 *	author.  Please notify the author of any enhancements made or bugs found
 *	so that all may benefit from the changes.  In addition, notification back
 *	to the author will allow the new user to pick up changes that may have
 *	been made by other users after this version of the code was distributed.
 *
 *	Note1: the majority of this code was edited with 4-space tabs.
 *	Note2: as more and more contributions are accepted, the term "author"
 *		   is becoming a mis-representation of credit.
 *
 *	Original author:	Ed Sutter
 *	Email:				esutter@lucent.com
 *	Phone:				908-582-2351
 */

#include "config.h"
#include <stdarg.h>
#include "stddefs.h"
#include "genlib.h"
#include "cli.h"

#if INCLUDE_MEMTRACE

#define MINBUFSIZE 512
#define MAXLINSIZE MINBUFSIZE/2

#define MODE_PRINT		(1<<0)		/* mtrace text is output to console */
#define MODE_NOWRAP		(1<<1)		/* when mtrace buffer fills, stop */

/* struct mtInfo:
 *	This structure is at the base of the memory space allocated for
 *	the print buffer.  The control structure is part of the print buffer
 *	because the print buffer is assumed to be outside of the bss area
 *	of the monitor; hence, if a reset occurs and the monitor clears out
 *	its bss space, this structure will still be accessible and contain
 *	the data prior to the reset.
 *	So, to initialize a memory trace buffer use...
 *		 mtrace cfg	BASE SIZE
 *	and to re-establish the trace after a reset, use...
 *		 mtrace mip	BASE
 */
struct mtInfo {
	char *base;		/* Base of ram space allocated for print buffer. */
	char *ptr;		/* Running pointer into circular print buffer. */
	char *end;		/* End of ram space allocated. */
	int	size;		/* Size of space originally allocated for mtrace. */
	int	off;		/* Set if tracing is disabled. */
	int	sno;		/* Sequence number of Mtrace() call. */
	int	wrap;		/* Wrap counter. */
	int	mode;		/* See MODE_XXX bits above. */
	int	reentered;	/* Reentry counter. */
};

static struct mtInfo *Mip;

/* Mtrace():
 * Memory trace... This function can be used to place some trace statements
 * (readable text) in some memory location specified by the
 * setting of mtracebuf.  This was originally written for debugging Xmodem
 * because you can't use printf() since the protocol is using the serial 
 * port.  I have since pulled it out of the Xmodem.c file and placed it in
 * generally accessible space so that it can be made available to the
 * application code and other monitor code.
 */

int
Mtrace(char *fmt,...)
{
	static	int inMtraceNow;
	int len;
	char *eolp;
	va_list argp;
	
	/* Mtrace not configured or disabled, so just return.
	 */
	if (!Mip || Mip->off)
		return(0);

	/* This may be called from interrupt and/or non-interrupt space of
	 * an application, so we must deal with possible reentrancy here.
	 */
	if (inMtraceNow) {
		Mip->reentered++;
		return(0);	
	}

	inMtraceNow = 1;

	Mip->ptr += snprintf(Mip->ptr,MAXLINSIZE,"\n<%04d> ",Mip->sno++);

	va_start(argp,fmt);
	len = vsnprintf(Mip->ptr,MAXLINSIZE,fmt,argp);
	va_end(argp);

	/* Strip all CR/LFs from the incoming string.
	 * The incoming string can have CR/LFs in it; however, they are stripped
	 * so that the format of the dump is stable (one line per Mtrace call).
	 * Notice that the top line of this function inserts a newline ahead
	 * of the sequence number; hence, additional CR/LFs in the text would
	 * just confuse the output.
	 */
	eolp = Mip->ptr;
	while(*eolp) {
		if ((*eolp == '\r') || (*eolp == '\n')) {
			strcpy(eolp,eolp+1);
			len--;
		}
		else
			eolp++;
	}

	/* If print flag is set, then dump to the console...
	 */
	if (Mip->mode & MODE_PRINT) {
		int	i;
		for(i=0;i<len;i++)
			putchar(*Mip->ptr++);
		putchar('\n');
	}
	else
		Mip->ptr += len;

	if (Mip->ptr >= Mip->end) {
		Mip->ptr = Mip->base;
		if (Mip->mode & MODE_NOWRAP)
			Mip->off = 1;
		else
			Mip->wrap++;
	}

	/* Flush the d-cache of the mtrace buffer and Mip structure after each
	 * transfer...
	 * This is important because if this is being accessed from an
	 * application that has d-cache enabled, then the hardware is reset,
	 * there is a chance that the data written was in cache and would be
	 * lost.
	 */
	flushDcache((char *)Mip,sizeof(struct mtInfo));
	flushDcache((char *)Mip->base,Mip->end - Mip->base);

	inMtraceNow = 0;
	return(len);
}

void
MtraceReset(void)
{
	Mip->ptr = Mip->base;
	Mip->sno = 1;
	Mip->wrap = 0;
	Mip->off = 0;
	Mip->mode = 0;
	Mip->reentered = 0;
	memset(Mip->base,0,Mip->size-sizeof(struct mtInfo));
}

void
MtraceInit(char *base, int size)
{
	if (size < MINBUFSIZE)
		return;

	Mip = (struct mtInfo *)base;
	Mip->base = base + sizeof(struct mtInfo);
	Mip->size = size;
	Mip->end = (Mip->base + size - MAXLINSIZE);
	MtraceReset();
}

char *
mDump(char *bp, int more)
{
	int	line;

	line = 0;

	while((bp < Mip->end) && (*bp)) {
		putchar(*bp);
		if (more && (*bp == '\n')) {
			if (++line == 24) {
				line = 0;
				if (!More())
					return(0);
			}
		}
		bp++;
	}
	while(*bp) {
		putchar(*bp);
		if (more && (*bp == '\n')) {
			if (++line == 24) {
				line = 0;
				if (!More())
					return(0);
			}
		}
		bp++;
	}
	return(bp);
}

/* If Mip pointer is configured, return 1; else return zero
 * and print an error message.
 */
static int
MipConfigured(void)
{
	if (Mip)
		return(1);
	printf("Not configured\n");
	return(0);
}

char *MtraceHelp[] = {
	"Configure/Dump memory trace.",
	"-[nm] {cmd} [cmd specific args]",
#if INCLUDE_VERBOSEHELP
	"Options:",
	" -m  enable 'more' flag for dump.",
	" -n  disable wrapping.",
	"Cmd:",
	" on",
	" off",
	" dump",
	" pron",
	" reset",
	" log {msg}",
	" mip {base}",
	" cfg [{base} {size}]",
#endif
	0
};

int
MtraceCmd(int argc,char *argv[])
{
	char	*bp;
	int		more, opt, nowrap;

	more = 0;
	nowrap = 0;
	while((opt=getopt(argc,argv,"nm")) != -1) {
		switch(opt) {
		case 'n':
			nowrap = 1;
			break;
		case 'm':
			more = 1;
			break;
		default:
			return(CMD_PARAM_ERROR);
		}
	}

	if (argc <= optind)
		return(CMD_PARAM_ERROR);

	if (!strcmp(argv[optind],"cfg")) {
		if (argc == optind + 3) {
			MtraceInit((char *)strtoul(argv[optind+1],0,0),
				strtoul(argv[optind+2],0,0));
			if (nowrap)
				Mip->mode |= MODE_NOWRAP;
		}
		else if (argc == optind + 1) {
			if (MipConfigured()) {
				printf("Base: 0x%lx, End: 0x%lx\n",
					(ulong)Mip->base,(ulong)Mip->end);
				printf("Ptr:  0x%lx, Sno: %d\n",(ulong)Mip->ptr,Mip->sno);
				printf("Wrap: %d\n",Mip->wrap);
			}
		}
		else
			return(CMD_PARAM_ERROR);
	}
	else if (!strcmp(argv[optind],"on")) {
		if (MipConfigured()) {
			Mip->mode &= ~MODE_PRINT;
			Mip->off = 0;
		}
	}
	else if (!strcmp(argv[optind],"pron")) {
		if (MipConfigured()) {
			Mip->mode |= MODE_PRINT;
			Mip->off = 0;
		}
	}
	else if (!strcmp(argv[optind],"off")) {
		if (MipConfigured()) 
			Mip->off = 1;
	}
	else if (!strcmp(argv[optind],"reset")) {
		if (MipConfigured())
			MtraceReset();
	}
	else if (!strcmp(argv[optind],"mip")) {
		if (argc != optind + 2)
			return(CMD_PARAM_ERROR);
		Mip = (struct mtInfo *)strtoul(argv[optind+1],0,0);
	}
	else if (!strcmp(argv[optind],"log")) {
		if (argc != optind + 2)
			return(CMD_PARAM_ERROR);
		Mtrace(argv[optind+1]);
	}
	else if (!strcmp(argv[optind],"dump")) {
		if (MipConfigured()) {
			if (Mip->reentered)
				printf("Reentry count: %d\n",Mip->reentered); 
			if (Mip->wrap) {
				printf("Buffer wrapped...\n");
				bp =  Mip->ptr;
				while(bp < Mip->end) {
					if (*bp == '\n') {
						bp = mDump(bp,more);
						break;
					}
					bp++;
				}
				if (bp) {
					bp =  Mip->base;
					while(bp < Mip->ptr)
						putchar(*bp++);
				}
			}
			else {
				bp = mDump(Mip->base,more);
			}
			printf("\n\n");
		}
	}
	else
		return(CMD_PARAM_ERROR);

	return(CMD_SUCCESS);
}

#else

void
MtraceInit(char *base, int size)
{
	printf("Mtrace() facility not built in.\n");
}

int
Mtrace(char *fmt, ...)
{
	return(0);
}

#endif

⌨️ 快捷键说明

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