From 04bf39a184e283298f15aaad1fbb29238ef301b6 Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Fri, 20 Apr 2012 14:00:43 +0200 Subject: added M escape for Kermit to run low-level command line monitor tool --- x-loader/common/Makefile | 2 +- x-loader/common/cmd_load.c | 6 +- x-loader/common/cmd_monitor.c | 361 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 367 insertions(+), 2 deletions(-) create mode 100644 x-loader/common/cmd_monitor.c diff --git a/x-loader/common/Makefile b/x-loader/common/Makefile index 8f4ee2c..beb58eb 100644 --- a/x-loader/common/Makefile +++ b/x-loader/common/Makefile @@ -27,7 +27,7 @@ LIB = $(obj)libcommon.a AOBJS = -COBJS = cmd_load.o +COBJS = cmd_load.o cmd_monitor.o SRCS := $(AOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(AOBJS) $(COBJS)) diff --git a/x-loader/common/cmd_load.c b/x-loader/common/cmd_load.c index 94901a9..122b797 100644 --- a/x-loader/common/cmd_load.c +++ b/x-loader/common/cmd_load.c @@ -81,6 +81,7 @@ static void set_kerm_bin_mode(unsigned long *); static int k_recv(void); static ulong load_serial_bin (ulong offset); +extern int lowlevel_monitor (void); char his_eol; /* character he needs at end of packet */ int his_pad_count; /* number of pad chars he needs */ @@ -93,7 +94,7 @@ int do_load_serial_bin (ulong offset, int baudrate) int rcode = 0; printf ("## Ready for binary (kermit) download " - "to 0x%08lX at %d bps...\n", + "to 0x%08lX at %d bps. Press 'M' to break into low level monitor.\n", offset, baudrate); addr = load_serial_bin (offset); @@ -432,6 +433,9 @@ static int k_recv (void) goto START; case ETX_CHAR: /* ^C waiting for packet */ return (0); + case 'M': + lowlevel_monitor(); + break; default: ; } diff --git a/x-loader/common/cmd_monitor.c b/x-loader/common/cmd_monitor.c new file mode 100644 index 0000000..05ff5df --- /dev/null +++ b/x-loader/common/cmd_monitor.c @@ -0,0 +1,361 @@ +/* + * (C) Copyright 2000-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * Simple command line monitor + * run in Kermit mode by starting with "M" + */ +#include +#include + +#define putc serial_putc +#define tstc serial_tstc + +/******************************************************* + * Routine: delay + * Description: spinning delay to use before udelay works + ******************************************************/ +static inline void delay(unsigned long loops) +{ + __asm__ volatile ("1:\n" "subs %0, %1, #1\n" + "bne 1b":"=r" (loops):"0"(loops)); +} +static inline void udelay(unsigned long us) +{ + delay(us * 200); /* approximate */ +} + +typedef struct gpio { + unsigned char res1[0x34]; + unsigned int oe; /* 0x34 */ + unsigned int datain; /* 0x38 */ + unsigned char res2[0x54]; + unsigned int cleardataout; /* 0x90 */ + unsigned int setdataout; /* 0x94 */ +} gpio_t; + +// unclear if the functional clocks are enabled! + +static gpio_t *blocks[]={ // GPIO1 .. 6 + OMAP34XX_GPIO1_BASE, + OMAP34XX_GPIO2_BASE, + OMAP34XX_GPIO3_BASE, + OMAP34XX_GPIO4_BASE, + OMAP34XX_GPIO5_BASE, + OMAP34XX_GPIO6_BASE +}; + +static inline int gpio_get(int n) +{ + int bit=n % 32; + gpio_t *base=blocks[n/32]; + return (base->datain >> bit)&1; +} + +static inline int gpio_is_input(int n) +{ // geht nicht richtig + int bit=n % 32; + gpio_t *base=blocks[n/32]; + return (base->oe >> bit)&1; +} + +int strcmp(char *s1, char *s2) +{ + while(*s1 == *s2) { + if(*s1 == 0) + return 0; // same + s1++; + s2++; + } + return *s1 > *s2?1:-1; +} + +long xtol(char *s) +{ + long val=0; + while(1) + { + if(*s >= '0' && *s <= '9') + val=16*val+(*s++-'0'); + else if(*s >= 'A' && *s <= 'F') + val=16*val+(*s++-'A'+10); + else if(*s >= 'a' && *s <= 'f') + val=16*val+(*s++-'a'+10); + else + break; + } + return val; +} + +static char *addr=(char *) CFG_LOADADDR; +static char line[100]; +static char *argv[10]; + +#define __raw_readl(a) (*(volatile unsigned int *)(a)) +#define __raw_writel(v,a) (*(volatile unsigned int *)(a) = (v)) +#define __raw_readw(a) (*(volatile unsigned short *)(a)) +#define __raw_writew(v,a) (*(volatile unsigned short *)(a) = (v)) + +#define MUX_VAL(OFFSET,VALUE)\ +__raw_writew((VALUE), OMAP34XX_CTRL_BASE + (OFFSET)); + +#define CP(x) (CONTROL_PADCONF_##x) + +void testfn(void) +{ // code can be copied to SDRAM (assuming that it is position-independent!) + int i; + for(i=0; i<10; i++) { + if(i & 1) + MUX_VAL(CP(GPMC_nCS6), (IEN | PTD | EN | M4)) /*GPT_PWM11/GPIO57*/ + else + MUX_VAL(CP(GPMC_nCS6), (IEN | PTU | EN | M4)) /*GPT_PWM11/GPIO57*/ + udelay(500*1000); + } +} + +int lowlevel_monitor (void) +{ // add testing code here + int i=0; + printf("Hello World!\n"); + while(1) { + char *c; + int argc=0; + int pos=0; + printf ("$ "); + while(1) { + line[pos]=getc(); + switch(line[pos]) { + case '\b': + case 0x7f: + if(pos > 0) { + putc('\b'); + pos--; + } + continue; + case 0: + case '\n': + continue; // ignore + case '\r': + break; // command + default: + if(pos < sizeof(line)/sizeof(line[0])) { + putc(line[pos]); + pos++; + } + continue; + } + line[pos]=0; + printf("\n"); + break; + } + c=line; + while(argc < sizeof(argv)/sizeof(argv[0])) { + while (*c == ' ' || *c == '\t') + c++; + if(*c == 0) + break; + argv[argc]=c; + while(*c != 0 && *c != '\t' && *c != ' ') + c++; + argc++; + if(*c == 0) + break; + *c=0; // substitute + c++; + } + if(argc == 0) + continue; // empty line +// printf("argc=%d argv[0]=%s\n", argc, argv[0]); + if(strcmp(argv[0], "c") == 0) { // c - copy test function to SDRAM and execute + extern void * memcpy(void * dest,const void *src,size_t count); + void (*fn)(void) = &testfn; + size_t cnt = 0x1000; + addr=(char *) CFG_LOADADDR; + printf("%08x (%d) --> %08x\n", fn, cnt, addr); + memcpy(addr, fn, cnt); + (*fn)(); + } + else if(strcmp(argv[0], "x") == 0) { // x [addr] - execute code + void (*fn)(void) = addr; + if(argc > 1) + fn = (void *) xtol(argv[1]); + (*fn)(); + } + else if(strcmp(argv[0], "l") == 0) { // l - loop + int d=1; + while(1) + printf ("Welcome to uart-monitor (%d)\n", d++), udelay(500*1000); + } + else if(strcmp(argv[0], "a") == 0) { // a [addr] + if(argc > 1) + addr=(char *) xtol(argv[1]); + printf("%08x\n", addr); + } + else if(strcmp(argv[0], "r") == 0) { // r [size] + int i; + int n=1; + if(argc > 1) + n=xtol(argv[1]); + printf("%08x:", addr); + for(i=0; i 1) + n=xtol(argv[1]); + printf("%08x:", addr); + for(i=0; i 1) + val=xtol(argv[1]); + if(argc > 2) + n=xtol(argv[2]); + for(i=0; i> 8) + (((unsigned int) addr) >> 16) + (((unsigned int) addr) >> 24); // build from address + if((((unsigned int)addr) & 0xfffff) == 0) // approx. 1 MByte per second + printf("%08x: %02x\n", addr, val); + *addr=val; // fill ram with prime pattern + } + printf("\nchecking\n"); + for(addr=(char *) CFG_LOADADDR; addr < 512*1024*1024+(char *) 0x80000000; addr++) { + unsigned char r=*addr; // read back + val=(unsigned int) addr + (((unsigned int) addr) >> 8) + (((unsigned int) addr) >> 16) + (((unsigned int) addr) >> 24); + if((((unsigned int)addr) & 0xfffff) == 0) + printf("%08x\n", addr); + if(r != val) // check RAM + printf("read error %8x: %2x %2x\n", addr, r, val); + } + printf("\ndone\n"); + addr=(char *) CFG_LOADADDR; + } +#if 0 + else if(strcmp(argv[0], "clk") == 0) { // clk + extern u32 osc_clk; + printf("clk=%d\n", osc_clk); + } +#endif + else if(strcmp(argv[0], "bl") == 0) { // blink backlight + int i; + for(i=0; i<10; i++) { + printf("blink %d\n", i+1); + // works only on GTA04A3 board since R209 is high compared to PTU + if(i & 1) + MUX_VAL(CP(GPMC_nCS6), (IEN | PTD | EN | M4)) /*GPT_PWM11/GPIO57*/ + else + MUX_VAL(CP(GPMC_nCS6), (IEN | PTU | EN | M4)) /*GPT_PWM11/GPIO57*/ + udelay(500*1000); + } + } + else if(strcmp(argv[0], "g") == 0) { // g - read GPIO + unsigned int i; + int n=32*sizeof(blocks)/sizeof(blocks[0]); + printf("GPIO1 data: %08x\n", ((gpio_t *) OMAP34XX_GPIO1_BASE) -> datain); + printf("%03d:", 0); + for(i=0; i>= 16; + } + if(addr == 0x48002264) { + addr=0x480025DC; + printf("\n%08x", addr); + cols=0; + } + else { + addr+=4; + if(++cols == 8) + printf("\n%08x", addr), cols=0; + } + } + printf("\n"); + } + else if(strcmp(argv[0], "k") == 0) { // k - back to kermit mode + printf("Going back to Kermit mode\n"); + break; + } + else + { + printf("uart-monitor unknown command: %s\n", argv[0]); + printf("a: \n"); + printf("bl: \n"); + printf("c: \n"); + printf("f: fill RAM with pattern\n"); + printf("g: read GPIO\n"); + printf("k: back to Kermit mode\n"); + printf("l: \n"); + printf("m: read Pinmux\n"); + printf("r: \n"); + printf("ram: \n"); + printf("rl: \n"); + printf("rt: RAM test\n"); + printf("x: \n"); + } + } + return 0; +} + -- cgit v1.1