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

📄 kgdb-serial.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
字号:
/* * arch/arm/kernel/kgdb-serial.c * * Generic serial access routines for use by kgdb. * * Author: Deepak Saxena <dsaxena@mvista.com> * * Copyright 2002 MontaVista Software Inc. * *  This program is free software; you can redistribute  it and/or modify it *  under  the terms of  the GNU General  Public License as published by the *  Free Software Foundation;  either version 2 of the  License, or (at your *  option) any later version. * * Based on original KGDB code developed by various people: * * This is a simple middle layer that allows KGDB to run on * top of any serial device.  This layer expects the board * port to provide the following functions: * * 	void kgdb_serial_init(void) * 		initialize serial interface if needed * 	void kgdb_serial_putchar(unsigned char) * 		send a character over the serial connection * 	kgdb_serial_getchar() * 		get a character from the serial connection * * Note that this is not meant for debugging over sercons, but for * when you have a _dedicated_ serial port for kgdb.  To send debug * and console messages over the same port (ICK), you need to * turn on CONFIG_KGDB_CONSOLE, which uses kgb-console.c instead and * hooks into the console system. */#include <linux/types.h>#include <linux/kernel.h>#include <linux/signal.h>#include <linux/sched.h>#include <linux/mm.h>#include <linux/spinlock.h>#include <linux/personality.h>#include <linux/ptrace.h>#include <linux/elf.h>#include <linux/interrupt.h>#include <linux/init.h>#include <asm/atomic.h>#include <asm/io.h>#include <asm/pgtable.h>#include <asm/system.h>#include <asm/uaccess.h>#include <asm/unistd.h>#include <asm/kgdb.h>#ifdef CONFIG_KGDB_CONSOLE#include <linux/console.h>#endifstatic int kgdb_io_initialized = 0;static const char hexchars[]="0123456789abcdef";static inthex(unsigned char ch){  if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);  if ((ch >= '0') && (ch <= '9')) return (ch-'0');  if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);  return (-1);}/* * * Scan the serial stream for the sequence $<data>#<checksum> * */voidkgdb_get_packet(unsigned char *buffer, int buflen){	unsigned char checksum;	unsigned char xmitcsum;	int i;	int count;	char ch;	do {		/* Ignore everything until the start character */		while ((ch = kgdb_serial_getchar()) != '$') ;		checksum = 0;		xmitcsum = -1;		count = 0;		/* Now, read until a # or end of buffer is found */		while (count < (buflen - 1)) {			ch = kgdb_serial_getchar();			if (ch == '#')				break;			checksum = checksum + ch;			buffer[count] = ch;			count = count + 1;		}		buffer[count] = 0;		/* Continue to read checksum following # */		if (ch == '#') {			xmitcsum = hex(kgdb_serial_getchar()) << 4;			xmitcsum += hex(kgdb_serial_getchar());			/* Checksum */			if (checksum != xmitcsum)				kgdb_serial_putchar('-'); /* Failed checksum */			else {				/* Ack successful transfer */				kgdb_serial_putchar('+');				/* If a sequence char is present, reply				   the sequence ID */				if (buffer[2] == ':') {					kgdb_serial_putchar(buffer[0]);					kgdb_serial_putchar(buffer[1]);					/* Remove sequence chars from buffer */					count = strlen(buffer);					for (i = 3; i <= count; i++)						buffer[i - 3] = buffer[i];				}			}		}	} while (checksum != xmitcsum);	/* Keep trying while we fail */}/* * * Send packet in the buffer with run-length encoding as follows: * * $<packet info>#<checksum>. * */voidkgdb_put_packet(const unsigned char *buffer){	unsigned char checksum;	const unsigned char *src;	int runlen;	int encode;	do {		src = buffer;		kgdb_serial_putchar('$');		checksum = 0;		/* Continue while we still have chars left */		while (*src) {			/* Check for runs up to 99 chars long */			for (runlen = 1; runlen < 99; runlen++) {				if (src[0] != src[runlen])					break;			}			if (runlen > 3) {				/* Got a useful amount, send encoding */				encode = runlen + ' ' - 4;				kgdb_serial_putchar(*src);				checksum += *src;				kgdb_serial_putchar('*');				checksum += '*';				kgdb_serial_putchar(encode);				checksum += encode;				src += runlen;			} else {				/* Otherwise just send the current char */				kgdb_serial_putchar(*src);				checksum += *src;				src += 1;			}		}		/* '#' Separator, put high and low components of checksum */		kgdb_serial_putchar('#');		kgdb_serial_putchar(hexchars[(checksum >> 4) & 0xf]);		kgdb_serial_putchar(hexchars[checksum & 0xf]);	} while ((kgdb_serial_getchar()) != '+'); /* While no ack */}intkgdb_io_init(void){	if (kgdb_io_initialized)		return 0;	kgdb_serial_init();	kgdb_io_initialized = 1;	return 0;}/* * If only one serial port is available on the board or if you want * to send console messages over KGDB, this is a nice and easy way * to accomplish this. Just add "console=ttyKGDB" to the command line * and all console output will be piped to the GDB client. */#ifdef CONFIG_KGDB_CONSOLEstatic char kgdb_console_buf[4096];static voidkgdb_console_write(struct console *co, const char *s, unsigned count){	int i = 0;	static int j = 0;	if(!kgdb_active())		return;	kgdb_console_buf[0] = 'O';	j = 1;	for(i = 0; i < count; i++, s++)	{		kgdb_console_buf[j++] = hexchars[*s >> 4];		kgdb_console_buf[j++] = hexchars[*s & 0xf];		if(*s == '\n')		{			kgdb_console_buf[j] = 0;			kgdb_put_packet(kgdb_console_buf);			kgdb_console_buf[0]='O';			j = 1;		}	}	if(j != 1)	{		kgdb_console_buf[j] = 0;		kgdb_put_packet(kgdb_console_buf);	}}static kdev_tkgdb_console_device(struct console *c){	return 0;}static intkgdb_console_setup(struct console *co, char *options){	kgdb_io_init();	return 0;}static struct console kgdb_console = {	name:		"ttyKGDB",	write:		kgdb_console_write,	device:		kgdb_console_device,	setup:		kgdb_console_setup,	flags:		CON_PRINTBUFFER,	index:		-1};void __initkgdb_console_init(void){	register_console(&kgdb_console);}#endif // CONFIG_KGDB_CONSOLE

⌨️ 快捷键说明

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