Browse Source

clean up finsh shell code.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@734 bbd45198-f89e-11dd-88c7-29a3b14d5316
bernard.xiong@gmail.com 15 years ago
parent
commit
1e1b85b9c7
3 changed files with 314 additions and 204 deletions
  1. 55 0
      components/finsh/cmd.c
  2. 200 204
      components/finsh/shell.c
  3. 59 0
      components/finsh/shell.h

+ 55 - 0
components/finsh/cmd.c

@@ -107,6 +107,61 @@ long list_thread(void)
 }
 FINSH_FUNCTION_EXPORT(list_thread, list thread);
 
+#if 0
+long dump_thread(rt_thread_t tid)
+{
+	rt_uint8_t *ptr;
+	rt_uint32_t sp;
+	rt_thread_t thread;
+
+	rt_kprintf(" thread  pri  status      sp     stack size max used   left tick  error\n");
+	rt_kprintf("-------- ---- ------- ---------- ---------- ---------- ---------- ---\n");
+
+	thread = rt_thread_self();
+	if ((thread == tid) || (tid == RT_NULL)) /* it's current thread */
+	{
+		ptr = (rt_uint8_t*)thread->stack_addr;
+		while (*ptr == '#')ptr ++;
+		sp = (rt_uint32_t)__current_sp();
+		rt_kprintf("%-8s 0x%02x", thread->name, thread->current_priority);
+
+		if (thread->stat == RT_THREAD_READY)		rt_kprintf(" ready  ");
+		else if (thread->stat == RT_THREAD_SUSPEND) rt_kprintf(" suspend");
+		else if (thread->stat == RT_THREAD_INIT)	rt_kprintf(" init   ");
+
+		rt_kprintf(" 0x%08x 0x%08x 0x%08x 0x%08x %03d\n",
+			thread->stack_size + ((rt_uint32_t)thread->stack_addr - sp),
+			thread->stack_size,
+			thread->stack_size - ((rt_uint32_t) ptr - (rt_uint32_t)thread->stack_addr),
+			thread->remaining_tick,
+			thread->error);
+	}
+	else
+	{
+		thread = tid;
+		sp = (rt_uint32_t)thread->sp;
+
+		ptr = (rt_uint8_t*)thread->stack_addr;
+		while (*ptr == '#')ptr ++;
+
+		rt_kprintf("%-8s 0x%02x", thread->name, thread->current_priority);
+
+		if (thread->stat == RT_THREAD_READY)		rt_kprintf(" ready  ");
+		else if (thread->stat == RT_THREAD_SUSPEND) rt_kprintf(" suspend");
+		else if (thread->stat == RT_THREAD_INIT)	rt_kprintf(" init   ");
+
+		rt_kprintf(" 0x%08x 0x%08x 0x%08x 0x%08x %03d\n",
+			thread->stack_size + ((rt_uint32_t)thread->stack_addr - sp),
+			thread->stack_size,
+			thread->stack_size - ((rt_uint32_t) ptr - (rt_uint32_t)thread->stack_addr),
+			thread->remaining_tick,
+			thread->error);
+	}
+
+	return 0;
+}
+#endif
+
 static void show_wait_queue(struct rt_list_node* list)
 {
 	struct rt_thread *thread;

+ 200 - 204
components/finsh/shell.c

@@ -22,85 +22,14 @@
 #include <rthw.h>
 
 #include "finsh.h"
-
-/*
- * Add by caoxl 2009-10-14
- *
- */
-#ifdef QEMU_CAOXL
-#define  memcpy(a,b,c)	rt_memcpy(a,b,c)
-extern char rt_serial_getc(void);
-#endif
-
-#define FINSH_USING_HISTORY
-
-#if defined(__CC_ARM)					/* ARMCC compiler */
-  #ifdef FINSH_USING_SYMTAB
-    extern int FSymTab$$Base;
-    extern int FSymTab$$Limit;
-    extern int VSymTab$$Base;
-    extern int VSymTab$$Limit;
-  #endif
-#elif defined(__ICCARM__)               /* for IAR compiler */
-  #ifdef FINSH_USING_SYMTAB
-    #pragma section="FSymTab"
-    #pragma section="VSymTab"
-  #endif
-#elif defined(__GNUC__)
-  #ifdef FINSH_USING_SYMTAB
-  extern int __fsymtab_start;
-  extern int __fsymtab_end;
-  extern int __vsymtab_start;
-  extern int __vsymtab_end;
-  #endif
-#endif
+#include "shell.h"
 
 /* finsh thread */
-#ifndef FINSH_THREAD_PRIORITY
-#define FINSH_THREAD_PRIORITY 20
-#endif
-#ifndef FINSH_THREAD_STACK_SIZE
-#define FINSH_THREAD_STACK_SIZE 2048
-#endif
-struct rt_thread finsh_thread;
-char finsh_thread_stack[FINSH_THREAD_STACK_SIZE];
-struct rt_semaphore uart_sem;
-rt_device_t finsh_device;
-#ifdef FINSH_USING_HISTORY
-enum input_stat
-{
-	WAIT_NORMAL,
-	WAIT_SPEC_KEY,
-	WAIT_FUNC_KEY,
-};
-#ifndef FINSH_HISTORY_LINES
-#define FINSH_HISTORY_LINES 5
-#endif
-#ifndef FINSH_CMD_SIZE
-#define FINSH_CMD_SIZE		80
-#endif
-char finsh_cmd_history[FINSH_HISTORY_LINES][FINSH_CMD_SIZE];
-rt_uint16_t finsh_history_count = 0;
-#endif
+static struct rt_thread finsh_thread;
+static char finsh_thread_stack[FINSH_THREAD_STACK_SIZE];
+struct finsh_shell* shell;
 
 #if !defined (RT_USING_NEWLIB) && !defined (RT_USING_MINILIBC)
-void *memccpy(void *dst, const void *src, int c, size_t count)
-{
-	char *a = dst;
-	const char *b = src;
-	while (count--)
-	{
-		*a++ = *b;
-		if (*b==c)
-		{
-			return (void *)a;
-		}
-
-		b++;
-	}
-	return 0;
-}
-
 int strcmp (const char *s1, const char *s2)
 {
 	while (*s1 && *s1 == *s2) s1++, s2++;
@@ -156,8 +85,10 @@ int isprint(unsigned char ch)
 
 static rt_err_t finsh_rx_ind(rt_device_t dev, rt_size_t size)
 {
+	RT_ASSERT(shell != RT_NULL);
+
 	/* release semaphore to let finsh thread rx data */
-	rt_sem_release(&uart_sem);
+	rt_sem_release(&shell->rx_sem);
 
 	return RT_EOK;
 }
@@ -166,16 +97,17 @@ void finsh_set_device(const char* device_name)
 {
 	rt_device_t dev = RT_NULL;
 
+	RT_ASSERT(shell != RT_NULL);
 	dev = rt_device_find(device_name);
 	if (dev != RT_NULL && rt_device_open(dev, RT_DEVICE_OFLAG_RDWR) == RT_EOK)
 	{
-		if (finsh_device != RT_NULL)
+		if (shell->device != RT_NULL)
 		{
 			/* close old finsh device */
-			rt_device_close(finsh_device);
+			rt_device_close(shell->device);
 		}
 
-		finsh_device = dev;
+		shell->device = dev;
 		rt_device_set_rx_indicate(dev, finsh_rx_ind);
 	}
 	else
@@ -184,6 +116,25 @@ void finsh_set_device(const char* device_name)
 	}
 }
 
+const char* finsh_get_device()
+{
+	RT_ASSERT(shell != RT_NULL);
+	return shell->device->parent.name;
+}
+
+void finsh_set_echo(rt_uint32_t enable)
+{
+	RT_ASSERT(shell != RT_NULL);
+	shell->echo_mode = enable;
+}
+
+rt_uint32_t finsh_get_echo()
+{
+	RT_ASSERT(shell != RT_NULL);
+
+	return shell->echo_mode;
+}
+
 void finsh_auto_complete(char* prefix)
 {
 	extern void list_prefix(char* prefix);
@@ -194,7 +145,7 @@ void finsh_auto_complete(char* prefix)
 }
 
 extern const char* finsh_error_string_table[];
-void finsh_run_line(struct finsh_parser *parser, const char* line)
+void finsh_run_line(struct finsh_parser* parser, const char *line)
 {
 	rt_kprintf("\n");
 	finsh_parser_run(parser, (unsigned char*)line);
@@ -234,179 +185,202 @@ void finsh_run_line(struct finsh_parser *parser, const char* line)
     finsh_flush(parser);
 }
 
-void finsh_thread_entry(void* parameter)
-{
-	struct finsh_parser parser;
-    char line[256], ch;
-	int  pos ;
 #ifdef FINSH_USING_HISTORY
-	enum input_stat stat;
-	unsigned short  current_history, use_history;
-#endif
+rt_bool_t finsh_handle_history(struct finsh_shell* shell, char ch)
+{
+	/*
+	 * handle up and down key
+	 * up key  : 0x1b 0x5b 0x41
+	 * down key: 0x1b 0x5b 0x42
+	 */
+	if (ch == 0x1b)
+	{
+		shell->stat = WAIT_SPEC_KEY;
+		return RT_TRUE;
+	}
 
-	pos = 0;
-	stat = WAIT_NORMAL;
-	current_history = 0;
-	use_history = 0;
-	memset(line, 0, sizeof(line));
+	if ((shell->stat == WAIT_SPEC_KEY))
+	{
+		if (ch == 0x5b)
+		{
+			shell->stat = WAIT_FUNC_KEY;
+			return RT_TRUE;
+		}
 
-    finsh_init(&parser);
-	rt_kprintf("finsh>>");
+		shell->stat = WAIT_NORMAL;
+		return RT_FALSE;
+	}
 
-	while (1)
+	if (shell->stat == WAIT_FUNC_KEY)
 	{
-		if (rt_sem_take(&uart_sem, RT_WAITING_FOREVER) != RT_EOK) continue;
+		shell->stat = WAIT_NORMAL;
 
-		/* read one character from device */
-		while (rt_device_read(finsh_device, 0, &ch, 1) == 1)
+		if (ch == 0x41) /* up key */
 		{
-			#ifdef FINSH_USING_HISTORY
-			/*
-			 * handle up and down key
-			 * up key  : 0x1b 0x5b 0x41
-			 * down key: 0x1b 0x5b 0x42
-			 */
-			if (ch == 0x1b)
+			/* prev history */
+			if (shell->current_history > 0)shell->current_history --;
+			else
 			{
-				stat = WAIT_SPEC_KEY;
-				continue;
+				shell->current_history = 0;
+				return RT_TRUE;
 			}
 
-			if ((stat == WAIT_SPEC_KEY) && (ch == 0x5b))
+			/* copy the history command */
+			memcpy(shell->line, &shell->cmd_history[shell->current_history][0],
+				FINSH_CMD_SIZE);
+			shell->line_position = strlen(shell->line);
+			shell->use_history = 1;
+		}
+		else if (ch == 0x42) /* down key */
+		{
+			/* next history */
+			if (shell->current_history < shell->history_count - 1)
+				shell->current_history ++;
+			else
 			{
-				if (ch == 0x5b)
+				/* set to the end of history */
+				if (shell->history_count != 0)
 				{
-					stat = WAIT_FUNC_KEY;
-					continue;
+					shell->current_history = shell->history_count - 1;
 				}
-				stat = WAIT_NORMAL;
+				else return RT_TRUE;
 			}
 
-			if (stat == WAIT_FUNC_KEY)
-			{
-				stat = WAIT_NORMAL;
+			memcpy(shell->line, &shell->cmd_history[shell->current_history][0],
+				FINSH_CMD_SIZE);
+			shell->line_position = strlen(shell->line);
+			shell->use_history = 1;
+		}
 
-				if (ch == 0x41) /* up key */
-				{
-					/* prev history */
-					if (current_history > 0)current_history --;
-					else
-					{
-						current_history = 0;
-						continue;
-					}
-
-					/* copy the history command */
-					memcpy(line, &finsh_cmd_history[current_history][0],
-						FINSH_CMD_SIZE);
-					pos = strlen(line);
-					use_history = 1;
-				}
-				else if (ch == 0x42) /* down key */
-				{
-					/* next history */
-					if (current_history < finsh_history_count - 1)
-						current_history ++;
-					else
-					{
-						/* set to the end of history */
-						if (finsh_history_count != 0)
-						{
-							current_history = finsh_history_count - 1;
-						}
-						else continue;
-					}
-
-					memcpy(line, &finsh_cmd_history[current_history][0],
-						FINSH_CMD_SIZE);
-					pos = strlen(line);
-					use_history = 1;
-				}
+		if (shell->use_history)
+		{
+			rt_kprintf("\033[2K\r");
+			rt_kprintf("%s%s", FINSH_PROMPT, shell->line);
+			return RT_TRUE;;
+		}
+	}
 
-				if (use_history)
-				{
-					rt_kprintf("\033[2K\r");
-					rt_kprintf("finsh>>%s", line);
-					continue;
-				}
+	return RT_FALSE;
+}
+
+void finsh_push_history(struct finsh_shell* shell)
+{
+	if ((shell->use_history == 0) && (shell->line_position != 0))
+	{
+		/* push history */
+		if (shell->history_count >= FINSH_HISTORY_LINES)
+		{
+			/* move history */
+			int index;
+			for (index = 0; index < FINSH_HISTORY_LINES - 1; index ++)
+			{
+				memcpy(&shell->cmd_history[index][0],
+					&shell->cmd_history[index + 1][0], FINSH_CMD_SIZE);
 			}
+			memset(&shell->cmd_history[index][0], 0, FINSH_CMD_SIZE);
+			memcpy(&shell->cmd_history[index][0], shell->line, shell->line_position);
+
+			/* it's the maximum history */
+			shell->history_count = FINSH_HISTORY_LINES;
+		}
+		else
+		{
+			memset(&shell->cmd_history[shell->history_count][0], 0, FINSH_CMD_SIZE);
+			memcpy(&shell->cmd_history[shell->history_count][0], shell->line, shell->line_position);
+
+			/* increase count and set current history position */
+			shell->history_count ++;
+		}
+	}
+	shell->current_history = shell->history_count;
+}
+#endif
+
+#ifndef RT_USING_HEAP
+struct finsh_shell _shell;
+#endif
+void finsh_thread_entry(void* parameter)
+{
+    char ch;
+
+	/* normal is echo mode */
+	shell->echo_mode = 1;
+
+    finsh_init(&shell->parser);
+	rt_kprintf(FINSH_PROMPT);
+
+	while (1)
+	{
+		/* wait receive */
+		if (rt_sem_take(&shell->rx_sem, RT_WAITING_FOREVER) != RT_EOK) continue;
+
+		/* read one character from device */
+		while (rt_device_read(shell->device, 0, &ch, 1) == 1)
+		{
+			/* handle history key */
+			#ifdef FINSH_USING_HISTORY
+			if (finsh_handle_history(shell, ch) == RT_TRUE) continue;
 			#endif
 
+			/* handle CR key */
+			if (ch == '\r')
+			{
+				char next;
+
+				if (rt_device_read(shell->device, 0, &next, 1) == 1)
+					ch = next;
+				else ch = '\r';
+			}
 			/* handle tab key */
-			if (ch == '\t')
+			else if (ch == '\t')
 			{
 				/* auto complete */
-				finsh_auto_complete(&line[0]);
+				finsh_auto_complete(&shell->line[0]);
 				/* re-calculate position */
-				pos = strlen(line);
+				shell->line_position = strlen(shell->line);
 				continue;
 			}
 			/* handle backspace key */
 			else if (ch == 0x7f || ch == 0x08)
 			{
-				if (pos != 0)
+				if (shell->line_position != 0)
 				{
 					rt_kprintf("%c %c", ch, ch);
 				}
-				if (pos <= 0) pos = 0;
-				else pos --;
-				line[pos] = 0;
+				if (shell->line_position <= 0) shell->line_position = 0;
+				else shell->line_position --;
+				shell->line[shell->line_position] = 0;
 				continue;
 			}
+
 			/* handle end of line, break */
-			else if (ch == 0x0d || ch == 0x0a)
+			if (ch == '\r' || ch == '\n')
 			{
 				/* change to ';' and break */
-				line[pos] = ';';
+				shell->line[shell->line_position] = ';';
 
 				#ifdef FINSH_USING_HISTORY
-				if ((use_history == 0) && (pos != 0))
-				{
-					/* push history */
-					if (finsh_history_count >= FINSH_HISTORY_LINES)
-					{
-						/* move history */
-						int index;
-						for (index = 0; index < FINSH_HISTORY_LINES - 1; index ++)
-						{
-							memcpy(&finsh_cmd_history[index][0],
-								&finsh_cmd_history[index + 1][0], FINSH_CMD_SIZE);
-						}
-						memset(&finsh_cmd_history[index][0], 0, FINSH_CMD_SIZE);
-						memcpy(&finsh_cmd_history[index][0], line, pos);
-
-						/* it's the maximum history */
-						finsh_history_count = FINSH_HISTORY_LINES;
-					}
-					else
-					{
-						memset(&finsh_cmd_history[finsh_history_count][0], 0, FINSH_CMD_SIZE);
-						memcpy(&finsh_cmd_history[finsh_history_count][0], line, pos);
-
-						/* increase count and set current history position */
-						finsh_history_count ++;
-					}
-				}
-				current_history = finsh_history_count;
+				finsh_push_history(shell);
 				#endif
 
-				if (pos != 0) finsh_run_line(&parser, line);
+				if (shell->line_position != 0) finsh_run_line(&shell->parser, shell->line);
 				else rt_kprintf("\n");
 
-				rt_kprintf("finsh>>");
-				memset(line, 0, sizeof(line));
-				pos = 0;
+				rt_kprintf(FINSH_PROMPT);
+				memset(shell->line, 0, sizeof(shell->line));
+				shell->line_position = 0;
 
 				break;
 			}
 
 			/* it's a large line, discard it */
-			if (pos >= 256) pos = 0;
+			if (shell->line_position >= FINSH_CMD_SIZE) shell->line_position = 0;
 
 			/* normal character */
-			line[pos] = ch; ch = 0;
-			rt_kprintf("%c", line[pos++]);
-			use_history = 0; /* it's a new command */
+			shell->line[shell->line_position] = ch; ch = 0;
+			if (shell->echo_mode) rt_kprintf("%c", shell->line[shell->line_position]);
+			shell->line_position ++;
+			shell->use_history = 0; /* it's a new command */
 		} /* end of device read */
 	}
 }
@@ -423,14 +397,23 @@ void finsh_system_var_init(void* begin, void* end)
 	_sysvar_table_end = (struct finsh_sysvar*) end;
 }
 
+#if defined(__ICCARM__)               /* for IAR compiler */
+  #ifdef FINSH_USING_SYMTAB
+    #pragma section="FSymTab"
+    #pragma section="VSymTab"
+  #endif
+#endif
 /* init finsh */
 void finsh_system_init(void)
 {
 	rt_err_t result;
-	rt_sem_init(&uart_sem, "uart", 0, 0);
 
 #ifdef FINSH_USING_SYMTAB
 #ifdef __CC_ARM                 /* ARM C Compiler */
+    extern int FSymTab$$Base;
+    extern int FSymTab$$Limit;
+    extern int VSymTab$$Base;
+    extern int VSymTab$$Limit;
 	finsh_system_function_init(&FSymTab$$Base, &FSymTab$$Limit);
 	finsh_system_var_init(&VSymTab$$Base, &VSymTab$$Limit);
 #elif defined (__ICCARM__)      /* for IAR Compiler */
@@ -439,11 +422,24 @@ void finsh_system_init(void)
     finsh_system_var_init(__section_begin("VSymTab"),
                           __section_end("VSymTab"));
 #elif defined (__GNUC__)        /* GNU GCC Compiler */
+	extern int __fsymtab_start;
+	extern int __fsymtab_end;
+	extern int __vsymtab_start;
+	extern int __vsymtab_end;
 	finsh_system_function_init(&__fsymtab_start, &__fsymtab_end);
 	finsh_system_var_init(&__vsymtab_start, &__vsymtab_start);
 #endif
 #endif
 
+	/* create or set shell structure */
+#ifdef RT_USING_HEAP
+	shell = (struct finsh_shell*)rt_malloc(sizeof(struct finsh_shell));
+#else
+	shell = &_shell;
+#endif
+	memset(shell, 0, sizeof(struct finsh_shell));
+
+	rt_sem_init(&(shell->rx_sem), "shrx", 0, 0);
 	result = rt_thread_init(&finsh_thread,
 		"tshell",
 		finsh_thread_entry, RT_NULL,

+ 59 - 0
components/finsh/shell.h

@@ -0,0 +1,59 @@
+#ifndef __SHELL_H__
+#define __SHELL_H__
+
+#include <rtthread.h>
+
+#define FINSH_USING_HISTORY
+#ifndef FINSH_THREAD_PRIORITY
+#define FINSH_THREAD_PRIORITY 20
+#endif
+#ifndef FINSH_THREAD_STACK_SIZE
+#define FINSH_THREAD_STACK_SIZE 2048
+#endif
+#define FINSH_CMD_SIZE		80
+
+#define FINSH_OPTION_ECHO	0x01
+#define FINSH_PROMPT		"finsh>>"
+
+#ifdef FINSH_USING_HISTORY
+enum input_stat
+{
+	WAIT_NORMAL,
+	WAIT_SPEC_KEY,
+	WAIT_FUNC_KEY,
+};
+	#ifndef FINSH_HISTORY_LINES
+		#define FINSH_HISTORY_LINES 5
+	#endif
+#endif
+
+struct finsh_shell
+{
+	struct rt_semaphore rx_sem;
+
+	enum input_stat stat;
+
+	rt_uint8_t echo_mode:1;
+	rt_uint8_t use_history:1;
+
+#ifdef FINSH_USING_HISTORY
+	rt_uint8_t current_history;
+	rt_uint16_t history_count;
+
+	char cmd_history[FINSH_HISTORY_LINES][FINSH_CMD_SIZE];
+#endif
+
+	struct finsh_parser parser;
+
+	char line[FINSH_CMD_SIZE];
+	rt_uint8_t line_position;
+
+	rt_device_t device;
+};
+
+void finsh_set_echo(rt_uint32_t enable);
+rt_uint32_t finsh_get_echo(void);
+
+void finsh_set_device(const char* device_name);
+
+#endif