# HG changeset patch # User Michael Spacefalcon # Date 1368428214 0 # Node ID 437f9365249c38d09aee540b8b7b62ad3904ca33 # Parent 65111e6eee9ec96f75c7d8237987f7d3d7c510bb loadagent: baud rate switching implemented diff -r 65111e6eee9e -r 437f9365249c target-utils/libcommon/Makefile --- a/target-utils/libcommon/Makefile Mon May 06 02:04:56 2013 +0000 +++ b/target-utils/libcommon/Makefile Mon May 13 06:56:54 2013 +0000 @@ -5,7 +5,8 @@ RANLIB= arm-elf-ranlib OBJS= cmdentry.o dispatch.o hexarg.o parseargs.o serio.o serflush.o uartsel.o\ - cmd_jump.o cmd_r8.o cmd_r16.o cmd_r32.o cmd_w8.o cmd_w16.o cmd_w32.o + cmd_baud_switch.o cmd_jump.o cmd_r8.o cmd_r16.o cmd_r32.o cmd_w8.o \ + cmd_w16.o cmd_w32.o all: libcommon.a diff -r 65111e6eee9e -r 437f9365249c target-utils/libcommon/cmd_baud_switch.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/target-utils/libcommon/cmd_baud_switch.c Mon May 13 06:56:54 2013 +0000 @@ -0,0 +1,112 @@ +/* + * Baud rate switching command + */ + +#include +#include "types.h" +#include "ns16550.h" + +extern struct ns16550_regs *uart_base; +extern int serial_in_poll(); + +static const struct tab { + int baud; + int divisor; +} rate_table[] = { + /* + * First support the rates and divisors implemented by the + * Calypso boot ROM. Dividing 13 MHz by 7 gives an approximation + * of 115200 (x16); the divisors used by the boot ROM code for + * the slower baud rates are all 7x the usual PC value. + */ + {115200, 7}, + {57600, 7 * 2}, + {38400, 7 * 3}, + {28800, 7 * 4}, + {19200, 7 * 6}, + /* + * Going faster than ~115200 baud means using a divisor + * less than 7, resulting in a non-standard baud rate. + * The /1, /2 and /4 seem like reasonable choices. + */ + {812500, 1}, + {406250, 2}, + {203125, 4}, + /* that's all we really need to support */ + {0, 0} +}; + +/* + * The following helper function actually switches the UART + * baud rate divisor. Call serial_flush() first. It returns the + * old divisor value. + * + * Note the u8 type for both the new and old divisor values. + * All supported divisors are well below 255, so we don't bother + * with the upper byte. + */ +static u8 +actually_switch_baud(newdiv) + u8 newdiv; +{ + volatile struct ns16550_regs *regs; + u8 save_lcr, save_old_baud; + + regs = uart_base; + save_lcr = regs->lcr; + regs->lcr = save_lcr | NS16550_LCR_DLAB; + save_old_baud = regs->datareg; + regs->datareg = newdiv; + regs->lcr = save_lcr; + return(save_old_baud); +} + +void +cmd_baud_switch(argbulk) + char *argbulk; +{ + char *argv[2]; + int baudarg; + struct tab *tp; + u8 save_old_baud; + int c; + + if (parse_args(argbulk, 1, 1, argv, 0) < 0) + return; + baudarg = atoi(argv[0]); + for (tp = rate_table; tp->baud; tp++) + if (tp->baud == baudarg) + break; + if (!tp->baud) { + printf("ERROR: invalid/unimplemented baud rate argument\n"); + return; + } + + /* do it */ + serial_flush(); + save_old_baud = actually_switch_baud(tp->divisor); + + /* + * After getting the echo of this command at the old baud rate + * (see the serial flush call just before switching the divisor), + * the line will go silent from the user's perspective. + * The user should wait just a little bit, then send us a 0x55 ('U') + * at the new baud rate - we should be in the below loop waiting + * for this character by then. Receiving that character + * correctly (0x55 was chosen for the bit pattern - unlikely to + * be received if the sender is sending at a wrong baud rate) + * will cause us to conclude this command and return a new '=' + * prompt at the new baud rate. + * + * If we get something else, we assume that someone messed up, + * switch back to the old baud rate, scribble an error message + * and return. + */ + do + c = serial_in_poll(); + while (c < 0); + if (c != 0x55) { + actually_switch_baud(save_old_baud); + printf("ERROR: no \'U\' received, switched back to old baud rate\n"); + } +} diff -r 65111e6eee9e -r 437f9365249c target-utils/loadagent/cmdtab.c --- a/target-utils/loadagent/cmdtab.c Mon May 06 02:04:56 2013 +0000 +++ b/target-utils/loadagent/cmdtab.c Mon May 13 06:56:54 2013 +0000 @@ -9,11 +9,13 @@ extern void cmd_w16(); extern void cmd_w32(); +extern void cmd_baud_switch(); extern void cmd_memdump_human(); extern void cmd_memdump_machine(); const struct cmdtab cmdtab[] = { {"DUMP", cmd_memdump_machine}, + {"baud", cmd_baud_switch}, {"crc32", cmd_crc32}, {"dump", cmd_memdump_human}, {"jump", cmd_jump},