[PATCH 1/3] i386/pc386: Add support for the gdb stub to use available console drivers.
Chris Johns
chrisj at rtems.org
Wed Apr 20 07:20:43 UTC 2016
Move the gdb stub from the i386 UART code to use the libchip drivers.
Use any ports discovered during the probes.
Add gdb control to the boot command line.
Change the device naming to the full device path, not a partial path.
For example /dev/com1.
---
c/src/lib/libbsp/i386/pc386/Makefile.am | 5 +-
c/src/lib/libbsp/i386/pc386/README | 23 ++-
c/src/lib/libbsp/i386/pc386/configure.ac | 6 +
c/src/lib/libbsp/i386/pc386/console/conscfg.c | 88 ++++++----
.../libbsp/i386/pc386/console/console_control.c | 39 +++--
.../lib/libbsp/i386/pc386/console/console_select.c | 106 +++--------
c/src/lib/libbsp/i386/pc386/console/gdb_select.c | 169 ++++++++++++++++++
c/src/lib/libbsp/i386/pc386/console/uart_bus_pci.c | 135 +++++++-------
c/src/lib/libbsp/i386/pc386/include/bsp.h | 3 +-
c/src/lib/libbsp/i386/pc386/include/bspimpl.h | 12 +-
c/src/lib/libbsp/i386/pc386/startup/bspstart.c | 29 ++-
c/src/lib/libbsp/i386/pc386/startup/ldsegs.S | 2 +-
c/src/lib/libbsp/i386/shared/comm/GDB.HOWTO | 134 +++++++-------
c/src/lib/libbsp/i386/shared/comm/i386-stub-glue.c | 195 ++++++++++++++-------
c/src/lib/libbsp/i386/shared/comm/i386-stub.c | 179 +++++++++++--------
c/src/lib/libbsp/shared/console.c | 43 ++++-
c/src/lib/libbsp/shared/console_private.h | 13 ++
17 files changed, 754 insertions(+), 427 deletions(-)
create mode 100644 c/src/lib/libbsp/i386/pc386/console/gdb_select.c
diff --git a/c/src/lib/libbsp/i386/pc386/Makefile.am b/c/src/lib/libbsp/i386/pc386/Makefile.am
index d9af7dd..22d4bf1 100644
--- a/c/src/lib/libbsp/i386/pc386/Makefile.am
+++ b/c/src/lib/libbsp/i386/pc386/Makefile.am
@@ -132,6 +132,7 @@ libbsp_a_SOURCES += console/printk_support.c
libbsp_a_SOURCES += console/exar17d15x.c
libbsp_a_SOURCES += console/rtd316.c
libbsp_a_SOURCES += console/uart_bus_pci.c
+libbsp_a_SOURCES += console/gdb_select.c
# gdb
libbsp_a_SOURCES += ../../i386/shared/comm/i386-stub.c
@@ -181,8 +182,8 @@ libbsp_a_SOURCES += ide/idecfg.c
endif
if HAS_SMP
-libbsp_a_SOURCES += ../../i386/shared/smp/getcpuid.c
-libbsp_a_SOURCES += ../../i386/shared/smp/smp-imps.c
+libbsp_a_SOURCES += ../../i386/shared/smp/getcpuid.c
+libbsp_a_SOURCES += ../../i386/shared/smp/smp-imps.c
project_lib_DATA += appstart.$(OBJEXT)
appcpustart.$(OBJEXT): start/start16.S
diff --git a/c/src/lib/libbsp/i386/pc386/README b/c/src/lib/libbsp/i386/pc386/README
index bfebf19..4ed8829 100644
--- a/c/src/lib/libbsp/i386/pc386/README
+++ b/c/src/lib/libbsp/i386/pc386/README
@@ -7,7 +7,7 @@ a Pentium or above, the TSC register is used for timing calibration
purposes rather than relying entirely on the i8254.
Partial support is implemented for more modern PCs which do not have
-a complete complement of legacy peripherals.
+a complete complement of legacy peripherals.
Console/Printk Device Selection
===============================
@@ -19,9 +19,9 @@ in the following order of priority:
+ VGA and keyboard
+ COM1 through COM4aaa
-+ Any COM devices on the PCI bus
++ Any COM devices on the PCI bus including IO and memory mapped.
-Beyond the dynamic probing for device presence, a combination of
+Beyond the dynamic probing for device presence, a combination of
configure and boot time options are available. By default, all devices
are enabled. The configure time options are:
@@ -45,7 +45,7 @@ specify the console and kernel debug IO device. The --printk
is then interpreted to specify the debug kernel IO device.
For example,
---console=com1 --printk=vgacons
+--console=/dev/com1 --printk=/dev/vgacons
specifies that com1 is to be used for stdin, stdout, and stderr
while the VGA console is to be used for kernel debug IO.
@@ -55,8 +55,21 @@ the RTEMS device /dev/com1.
The device name may be followed by a baud rate. The following
example illustrates this:
---console=com1,19200 --printk=vgacons
+--console=/dev/com1,19200 --printk=/dev/vgacons
If the specified device is not present, then a suitable fallback
device is selected. The fallback order is based upon the probe
order listed earlier.
+
+PCI UART devices are /dev/pcicom1 etc as they are probed and found.
+
+GDB
+===
+
+GDB can be support using:
+
+ --gdb=/dev/com1,115200 : where the device and baudrate are selectable.
+ --gdb-break : halt at a break point in the BSP and wait for GDB.
+ --gdb-remote-debug : Output the GDB remote protocol data to printk
+
+The GDB stub details and in shared/comm/GDB.HOWTO.
diff --git a/c/src/lib/libbsp/i386/pc386/configure.ac b/c/src/lib/libbsp/i386/pc386/configure.ac
index 17b7d02..d62a9b3 100644
--- a/c/src/lib/libbsp/i386/pc386/configure.ac
+++ b/c/src/lib/libbsp/i386/pc386/configure.ac
@@ -142,6 +142,12 @@ RTEMS_BSPOPTS_HELP([BSP_HAS_SMP],
[Always defined when on a pc386 to enable the pc386 support for
determining the CPU core number in an SMP configuration.])
+RTEMS_BSPOPTS_SET([BSP_GDB_STUB],[*],[1])
+RTEMS_BSPOPTS_HELP([BSP_GDB_STUB],
+[Defined by default. Enables use of the GDB stub for debugging via a
+ serial port.])
+AM_CONDITIONAL(BSP_GDB_STUB, test "$BSP_GDB_STUB" = "1")
+
## if this is an i386, does gas have good code16 support?
RTEMS_I386_GAS_CODE16
AM_CONDITIONAL(RTEMS_GAS_CODE16,[test "$RTEMS_GAS_CODE16" = "yes"])
diff --git a/c/src/lib/libbsp/i386/pc386/console/conscfg.c b/c/src/lib/libbsp/i386/pc386/console/conscfg.c
index 5b7ebc5..82d3cf9 100644
--- a/c/src/lib/libbsp/i386/pc386/console/conscfg.c
+++ b/c/src/lib/libbsp/i386/pc386/console/conscfg.c
@@ -16,13 +16,14 @@
*/
#include <bsp.h>
+#include <bsp/bspimpl.h>
#include <libchip/serial.h>
#include <libchip/ns16550.h>
#if BSP_ENABLE_VGA
#include "vgacons.h"
#endif
#include <bsp/irq.h>
-#include <rtems/pci.h>
+#include "../../../shared/console_private.h"
#if BSP_ENABLE_VGA
#define VGA_CONSOLE_FUNCTIONS &vgacons_fns
@@ -43,7 +44,7 @@
#define COM3_BASE_IO 0x2F8
#define COM4_BASE_IO 0x2E8
- #define CLOCK_RATE (115200 * 16)
+ #define CLOCK_RATE (115200 * 16)
static uint8_t com_get_register(uint32_t addr, uint8_t i)
{
@@ -57,21 +58,26 @@
{
outport_byte( (addr + i), val );
}
-
- extern bool pc386_com1_com4_enabled(int);
#endif
#if (BSP_IS_EDISON == 1 )
extern const console_fns edison_fns;
#endif
-console_tbl Console_Configuration_Ports[] = {
-#if (BSP_IS_EDISON == 1)
+/*
+ * Default to the PC VGA console if present and configured.
+ */
+console_tbl Console_Configuration_Ports[] = {
+#if BSP_ENABLE_VGA
+ /*
+ * If present the VGA console must always be minor 0.
+ * See console_control.
+ */
{
- "/dev/com1", /* sDeviceName */
- -1, /* deviceType */
- &edison_fns, /* pDeviceFns */
- NULL, /* deviceProbe */
+ "/dev/vgacons", /* sDeviceName */
+ VGA_CONSOLE, /* deviceType */
+ VGA_CONSOLE_FUNCTIONS, /* pDeviceFns */
+ vgacons_probe, /* deviceProbe */
NULL, /* pDeviceFlow */
16, /* ulMargin */
8, /* ulHysteresis */
@@ -83,16 +89,22 @@ console_tbl Console_Configuration_Ports[] = {
NULL, /* setRegister */
NULL,/* unused */ /* getData */
NULL,/* unused */ /* setData */
- 0X0, /* ulClock */
- 0x0 /* ulIntVector -- base for port */
+ 0x0, /* ulClock */
+ 0x0 /* ulIntVector -- base for port */
},
#endif
-#if BSP_ENABLE_VGA
+};
+
+unsigned long Console_Configuration_Count =
+ (sizeof(Console_Configuration_Ports)/sizeof(console_tbl));
+
+static console_tbl Legacy_Ports[] = {
+#if (BSP_IS_EDISON == 1)
{
- "/dev/vgacons", /* sDeviceName */
- VGA_CONSOLE, /* deviceType */
- VGA_CONSOLE_FUNCTIONS, /* pDeviceFns */
- vgacons_probe, /* deviceProbe */
+ "/dev/com1", /* sDeviceName */
+ -1, /* deviceType */
+ &edison_fns, /* pDeviceFns */
+ NULL, /* deviceProbe */
NULL, /* pDeviceFlow */
16, /* ulMargin */
8, /* ulHysteresis */
@@ -104,8 +116,8 @@ console_tbl Console_Configuration_Ports[] = {
NULL, /* setRegister */
NULL,/* unused */ /* getData */
NULL,/* unused */ /* setData */
- 0X0, /* ulClock */
- 0x0 /* ulIntVector -- base for port */
+ 0x0, /* ulClock */
+ 0x0 /* ulIntVector -- base for port */
},
#endif
#if BSP_ENABLE_COM1_COM4
@@ -113,7 +125,7 @@ console_tbl Console_Configuration_Ports[] = {
"/dev/com1", /* sDeviceName */
SERIAL_NS16550, /* deviceType */
COM_CONSOLE_FUNCTIONS, /* pDeviceFns */
- pc386_com1_com4_enabled, /* deviceProbe */
+ NULL, /* deviceProbe */
NULL, /* pDeviceFlow */
16, /* ulMargin */
8, /* ulHysteresis */
@@ -132,7 +144,7 @@ console_tbl Console_Configuration_Ports[] = {
"/dev/com2", /* sDeviceName */
SERIAL_NS16550, /* deviceType */
COM_CONSOLE_FUNCTIONS, /* pDeviceFns */
- pc386_com1_com4_enabled, /* deviceProbe */
+ NULL, /* deviceProbe */
NULL, /* pDeviceFlow */
16, /* ulMargin */
8, /* ulHysteresis */
@@ -147,12 +159,11 @@ console_tbl Console_Configuration_Ports[] = {
CLOCK_RATE, /* ulClock */
BSP_UART_COM2_IRQ /* ulIntVector -- base for port */
},
-
{
"/dev/com3", /* sDeviceName */
SERIAL_NS16550, /* deviceType */
COM_CONSOLE_FUNCTIONS, /* pDeviceFns */
- pc386_com1_com4_enabled, /* deviceProbe */
+ NULL, /* deviceProbe */
NULL, /* pDeviceFlow */
16, /* ulMargin */
8, /* ulHysteresis */
@@ -167,12 +178,11 @@ console_tbl Console_Configuration_Ports[] = {
CLOCK_RATE, /* ulClock */
BSP_UART_COM3_IRQ /* ulIntVector -- base for port */
},
-
{
"/dev/com4", /* sDeviceName */
SERIAL_NS16550, /* deviceType */
COM_CONSOLE_FUNCTIONS, /* pDeviceFns */
- pc386_com1_com4_enabled, /* deviceProbe */
+ NULL, /* deviceProbe */
NULL, /* pDeviceFlow */
16, /* ulMargin */
8, /* ulHysteresis */
@@ -188,12 +198,26 @@ console_tbl Console_Configuration_Ports[] = {
BSP_UART_COM4_IRQ /* ulIntVector -- base for port */
},
#endif
-
};
-/*
- * Define a variable that contains the number of statically configured
- * console devices.
- */
-unsigned long Console_Configuration_Count = \
- (sizeof(Console_Configuration_Ports)/sizeof(console_tbl));
+#define Legacy_Port_Count \
+ (sizeof(Legacy_Ports)/sizeof(console_tbl))
+
+void legacy_uart_probe(void)
+{
+#if BSP_ENABLE_COM1_COM4
+ const char *opt;
+ /*
+ * Check the command line to see if com1-com4 are disabled.
+ */
+ opt = bsp_cmdline_arg("--disable-com1-com4");
+ if ( opt ) {
+ printk( "COM1-COM4: disabled\n" );
+ } else {
+ if (Legacy_Port_Count) {
+ printk("Legacy UART Ports: COM1-COM4\n");
+ console_register_devices( Legacy_Ports, Legacy_Port_Count );
+ }
+ }
+#endif
+}
diff --git a/c/src/lib/libbsp/i386/pc386/console/console_control.c b/c/src/lib/libbsp/i386/pc386/console/console_control.c
index a0b9220..3a454d9 100644
--- a/c/src/lib/libbsp/i386/pc386/console/console_control.c
+++ b/c/src/lib/libbsp/i386/pc386/console/console_control.c
@@ -1,5 +1,5 @@
/*
- * This file is an extension of the generic console driver
+ * This file is an extension of the generic console driver
* shell used by all console drivers using libchip, it contains
* the console_control routine, This bsp needs its own version
* of this method to handle the keyboard and mouse as a single
@@ -44,27 +44,28 @@ rtems_device_driver console_control(
)
{
#if BSP_ENABLE_VGA
- rtems_libio_ioctl_args_t *args = arg;
+ if (minor == 0) {
+ rtems_libio_ioctl_args_t *args = arg;
- switch (args->command) {
- default:
- if( vt_ioctl( args->command, (unsigned long)args->buffer ) != 0 )
- return rtems_termios_ioctl (arg);
- break;
+ switch (args->command) {
+ default:
+ if( vt_ioctl( args->command, (unsigned long)args->buffer ) != 0 )
+ return rtems_termios_ioctl (arg);
+ break;
- case MW_UID_REGISTER_DEVICE:
- printk( "SerialMouse: reg=%s\n", args->buffer );
- register_kbd_msg_queue( args->buffer, 0 );
- break;
+ case MW_UID_REGISTER_DEVICE:
+ printk( "SerialMouse: reg=%s\n", args->buffer );
+ register_kbd_msg_queue( args->buffer, 0 );
+ break;
- case MW_UID_UNREGISTER_DEVICE:
- unregister_kbd_msg_queue( 0 );
- break;
+ case MW_UID_UNREGISTER_DEVICE:
+ unregister_kbd_msg_queue( 0 );
+ break;
+ }
+
+ args->ioctl_return = 0;
+ return RTEMS_SUCCESSFUL;
}
-
- args->ioctl_return = 0;
- return RTEMS_SUCCESSFUL;
-#else
- return rtems_termios_ioctl (arg);
#endif
+ return rtems_termios_ioctl (arg);
}
diff --git a/c/src/lib/libbsp/i386/pc386/console/console_select.c b/c/src/lib/libbsp/i386/pc386/console/console_select.c
index 6a91a96..f7e6bbc 100644
--- a/c/src/lib/libbsp/i386/pc386/console/console_select.c
+++ b/c/src/lib/libbsp/i386/pc386/console/console_select.c
@@ -3,7 +3,7 @@
*
* @ingroup Console
*
- * @brief pc397 console select
+ * @brief pc386 console select
*
* This file contains a routine to select the console based upon a number
* of criteria.
@@ -33,24 +33,6 @@
#include <crt.h>
#endif
-#include <bsp/bspimpl.h>
-
-/*
- * Forward prototype
- */
-extern bool pc386_com1_com4_enabled(int);
-
-/*
- * This method is used to determine if COM1-COM4 are enabled based upon
- * boot command line arguments.
- */
-static bool are_com1_com4_enabled;
-
-bool pc386_com1_com4_enabled(int minor)
-{
- return are_com1_com4_enabled;
-}
-
/*
* Method to return true if the device associated with the
* minor number probs available.
@@ -97,48 +79,6 @@ static rtems_device_minor_number bsp_First_Available_Device( void )
rtems_fatal_error_occurred(RTEMS_IO_ERROR);
}
-static bool bsp_find_console_entry(
- const char *match,
- size_t length,
- rtems_device_minor_number *match_minor
-)
-{
- rtems_device_minor_number minor;
- const char *name;
-
- for (minor=0; minor < Console_Port_Count ; minor++) {
- console_tbl *cptr = Console_Port_Tbl[minor];
-
- /*
- * Console table entries include /dev/ prefix, device names passed
- * in on command line do not.
- */
- name = cptr->sDeviceName + sizeof("/dev");
- if ( !strncmp( name, match, length ) ) {
- *match_minor = minor;
- return true;
- }
- }
-
- return false;
-}
-
-static void parse_com1_com4_enable(void)
-{
- static const char *opt;
-
- /*
- * Check the command line to see if com1-com4 are disabled.
- */
- opt = bsp_cmdline_arg("--disable-com1-com4");
- if ( opt ) {
- printk( "Disable COM1-COM4 per boot argument\n" );
- are_com1_com4_enabled = false;
- } else {
- are_com1_com4_enabled = true;
- }
-}
-
static bool parse_printk_or_console(
const char *param,
rtems_device_minor_number *minor_out
@@ -150,6 +90,7 @@ static bool parse_printk_or_console(
size_t length;
size_t index;
rtems_device_minor_number minor;
+ console_tbl *conscfg;
/*
* Check the command line for the type of mode the console is.
@@ -198,16 +139,14 @@ static bool parse_printk_or_console(
length = &opt[index] - option;
- if ( !bsp_find_console_entry( option, length, &minor ) ) {
+ conscfg = console_find_console_entry( option, length, &minor );
+ if ( conscfg == NULL ) {
return false;
}
*minor_out = minor;
if (comma) {
- console_tbl *conscfg = &Console_Configuration_Ports[minor];
-
option = comma + 1;
-
if (strncmp (option, "115200", sizeof ("115200") - 1) == 0)
conscfg->pDeviceParams = (void *)115200;
else if (strncmp (option, "57600", sizeof ("57600") - 1) == 0)
@@ -241,39 +180,34 @@ static inline const char *get_name(
*/
void pc386_parse_console_arguments(void)
{
- rtems_device_minor_number minor;
-
- /*
- * The console device driver must have its data structures initialized
- * before we can iterate the table of devices for names.
- */
- console_initialize_data();
-
- /*
- * Determine if COM1-COM4 were disabled.
- */
- parse_com1_com4_enable();
+ rtems_device_minor_number minor;
+ rtems_device_minor_number minor_console = 0;
+ rtems_device_minor_number minor_printk = 0;
/*
* Assume that if only --console is specified, that printk() should
* follow that selection by default.
*/
if ( parse_printk_or_console( "--console=", &minor ) ) {
- Console_Port_Minor = minor;
- BSPPrintkPort = minor;
+ minor_console = minor;
+ minor_printk = minor;
}
/*
* But if explicitly specified, attempt to honor it.
*/
if ( parse_printk_or_console( "--printk=", &minor ) ) {
- BSPPrintkPort = minor;
+ minor_printk = minor;
}
-#if 0
- printk( "Console device: %s\n", get_name(Console_Port_Minor) );
- printk( "printk device: %s\n", get_name(BSPPrintkPort) );
-#endif
+ printk( "Console: %s printk: %s\n",
+ get_name(minor_console),get_name(minor_printk) );
+
+ /*
+ * Any output after this can cause problems until termios is initialised.
+ */
+ Console_Port_Minor = minor_console;
+ BSPPrintkPort = minor_printk;
}
/*
@@ -283,6 +217,10 @@ void pc386_parse_console_arguments(void)
void bsp_console_select(void)
{
#ifdef RTEMS_RUNTIME_CONSOLE_SELECT
+ /*
+ * WARNING: This code is really needed any more and should be removed.
+ * references to COM1 and COM2 like they are wrong.
+ */
if ( BSP_runtime_console_select )
BSP_runtime_console_select(&BSPPrintkPort, &Console_Port_Minor);
diff --git a/c/src/lib/libbsp/i386/pc386/console/gdb_select.c b/c/src/lib/libbsp/i386/pc386/console/gdb_select.c
new file mode 100644
index 0000000..8e64658
--- /dev/null
+++ b/c/src/lib/libbsp/i386/pc386/console/gdb_select.c
@@ -0,0 +1,169 @@
+/**
+ * @file
+ *
+ * @ingroup GDB
+ *
+ * @brief pc386 gdb select
+ *
+ * This file contains a routine to enable and select the UART the gdb stub
+ * connects too. Currently limited to COM1 and COM2. See
+ * shared/comm/i386-stub-glue.c file.
+ */
+
+/*
+ * COPYRIGHT (c) 2016.
+ * Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <stdlib.h>
+
+#include <bsp.h>
+#include <rtems/libio.h>
+#include <rtems/console.h>
+#include <rtems/termiostypes.h>
+#include <libchip/serial.h>
+#include <libchip/ns16550.h>
+#include <bsp/bspimpl.h>
+
+#include "../../../shared/console_private.h"
+
+/*
+ * Used in the stub to print output.
+ */
+int remote_debug;
+/*
+ * Defined in the stub, used here.
+ */
+void set_debug_traps(void);
+
+/*
+ * Added here to get a valid baudrate. Needs to go once we
+ * move to the standard UART driver.
+ */
+int BSPBaseBaud;
+
+static bool gdb_port_probe(int minor)
+{
+ /* Return false as GDB has claimed the port */
+ return false;
+}
+
+void pc386_parse_gdb_arguments(void)
+{
+ static const char *opt;
+
+ /*
+ * Check the command line to see if com1-com4 are disabled.
+ */
+ opt = bsp_cmdline_arg("--gdb=");
+ if ( opt ) {
+ const char *option;
+ const char *comma;
+ size_t length;
+ size_t index;
+ rtems_device_minor_number minor;
+ uint32_t baudrate = 115200;
+ bool halt = false;
+ console_tbl *port;
+
+ /*
+ * Fine the length, there can be more command line visible.
+ */
+ length = 0;
+ while ((opt[length] != ' ') && (opt[length] != '\0')) {
+ ++length;
+ if (length > NAME_MAX) {
+ printk("invalid option (--gdb): too long\n");
+ return;
+ }
+ }
+
+ /*
+ * Only match up to a comma or NULL
+ */
+ index = 0;
+ while ((opt[index] != '=') && (index < length)) {
+ ++index;
+ }
+
+ if (opt[index] != '=') {
+ printk("invalid option (--gdb): no equals\n");
+ return;
+ }
+
+ ++index;
+ option = &opt[index];
+
+ while ((opt[index] != ',') && (index < length)) {
+ ++index;
+ }
+
+ if (opt[index] == ',')
+ comma = &opt[index];
+ else
+ comma = NULL;
+
+ length = &opt[index] - option;
+
+ port = console_find_console_entry( option, length, &minor );
+
+ if ( port == NULL ) {
+ printk("invalid option (--gdb): port not found\n");
+ return;
+ }
+
+ if (comma) {
+ option = comma + 1;
+ baudrate = strtoul(option, 0, 10);
+ switch (baudrate) {
+ case 115200:
+ case 57600:
+ case 38400:
+ case 19200:
+ case 9600:
+ case 4800:
+ port->pDeviceParams = (void*) baudrate;
+ BSPBaseBaud = baudrate; /* REMOVE ME */
+ break;
+ default:
+ printk("invalid option (--gdb): bad baudrate\n");
+ return;
+ }
+ }
+
+ /*
+ * Provide a probe that fails so the device is not part of termios. All
+ * functions are polling.
+ */
+ port->deviceProbe = gdb_port_probe;
+ port->pDeviceFns = &ns16550_fns_polled;
+
+ opt = bsp_cmdline_arg("--gdb-remote-debug");
+ if ( opt ) {
+ remote_debug = 1;
+ }
+
+ opt = bsp_cmdline_arg("--gdb-break");
+ if ( opt ) {
+ halt = true;
+ }
+
+ printk("GDB stub: enable %s%s%s\n",
+ port->sDeviceName,
+ remote_debug ? ", remote-debug" : "",
+ halt ? ", halting" : "");
+
+ i386_stub_glue_init(minor);
+ set_debug_traps();
+ i386_stub_glue_init_breakin();
+
+ if ( halt ) {
+ printk("GDB stub: waiting for remote connection..\n");
+ breakpoint();
+ }
+ }
+}
diff --git a/c/src/lib/libbsp/i386/pc386/console/uart_bus_pci.c b/c/src/lib/libbsp/i386/pc386/console/uart_bus_pci.c
index 36afb73..60d35e8 100644
--- a/c/src/lib/libbsp/i386/pc386/console/uart_bus_pci.c
+++ b/c/src/lib/libbsp/i386/pc386/console/uart_bus_pci.c
@@ -314,85 +314,88 @@ void pci_uart_probe(void)
&fun
);
if ( status == PCIB_ERR_SUCCESS ) {
+ uint8_t irq;
+ uint32_t base;
+
boards++;
conf[instance].found = true;
conf[instance].clock = pci_ns8250_ids[i].rclk;
conf[instance].ports = 1;
total_ports += conf[instance].ports;
- break;
- }
- }
-
- if ( status != PCIB_ERR_SUCCESS )
- continue;
- uint8_t irq;
- uint32_t base;
+ pci_read_config_byte( bus, dev, fun, PCI_INTERRUPT_LINE, &irq );
+ pci_read_config_dword( bus, dev, fun, PCI_BASE_ADDRESS_0, &base );
- pci_read_config_byte( bus, dev, fun, PCI_INTERRUPT_LINE, &irq );
- pci_read_config_dword( bus, dev, fun, PCI_BASE_ADDRESS_0, &base );
+ conf[instance].irq = irq;
+ conf[instance].base = base;
- conf[instance].irq = irq;
- conf[instance].base = base;
-
- printk(
- "Found %s #%d at 0x%08x IRQ %d with %d clock\n",
- pci_ns8250_ids[i].desc,
- instance,
- conf[instance].base,
- conf[instance].irq,
- conf[instance].clock
- );
+ printk(
+ "Found %s #%d at 0x%08x IRQ %d with %d clock\n",
+ pci_ns8250_ids[i].desc,
+ instance,
+ conf[instance].base,
+ conf[instance].irq,
+ conf[instance].clock
+ );
+ }
+ }
}
/*
* Now allocate array of device structures and fill them in
*/
- int device_instance;
- ports = calloc( total_ports, sizeof( console_tbl ) );
- port_p = ports;
- device_instance = 1;
- for ( b=0 ; b<MAX_BOARDS ; b++ ) {
- if ( conf[b].found == false )
- continue;
- char name[32];
-
- sprintf( name, "/dev/pcicom%d", device_instance++ );
- port_p->sDeviceName = strdup( name );
- port_p->deviceType = SERIAL_NS16550;
- if ( conf[b].irq <= 15 ) {
- port_p->pDeviceFns = &ns16550_fns;
- } else {
- printk(
- "%s IRQ=%d >= 16 requires APIC support, using polling\n",
- name,
- conf[b].irq <= 15
- );
- port_p->pDeviceFns = &ns16550_fns_polled;
- }
-
- port_p->deviceProbe = NULL;
- port_p->pDeviceFlow = NULL;
- port_p->ulMargin = 16;
- port_p->ulHysteresis = 8;
- port_p->pDeviceParams = (void *) 9600;
- port_p->ulCtrlPort1 = conf[b].base;
- port_p->ulCtrlPort2 = 0; /* NA */
- port_p->ulDataPort = 0; /* NA */
- port_p->getRegister = pci_ns16550_get_register;
- port_p->setRegister = pci_ns16550_set_register;
- port_p->getData = NULL; /* NA */
- port_p->setData = NULL; /* NA */
- port_p->ulClock = conf[b].clock;
- port_p->ulIntVector = conf[b].irq;
-
- port_p++;
- } /* end boards */
+ if (boards) {
+ int device_instance;
+
+ ports = calloc( total_ports, sizeof( console_tbl ) );
+ if (ports != NULL) {
+ port_p = ports;
+ device_instance = 1;
+ for (b = 0; b < MAX_BOARDS; b++) {
+ char name[32];
+ if ( conf[b].found == false )
+ continue;
+ sprintf( name, "/dev/pcicom%d", device_instance++ );
+ port_p->sDeviceName = strdup( name );
+ port_p->deviceType = SERIAL_NS16550;
+ if ( conf[b].irq <= 15 ) {
+ port_p->pDeviceFns = &ns16550_fns;
+ } else {
+ printk(
+ "%s IRQ=%d >= 16 requires APIC support, using polling\n",
+ name,
+ conf[b].irq
+ );
+ port_p->pDeviceFns = &ns16550_fns_polled;
+ }
- /*
- * Register the devices
- */
- if ( boards )
- console_register_devices( ports, total_ports );
+ port_p->deviceProbe = NULL;
+ port_p->pDeviceFlow = NULL;
+ port_p->ulMargin = 16;
+ port_p->ulHysteresis = 8;
+ port_p->pDeviceParams = (void *) 9600;
+ port_p->ulCtrlPort1 = conf[b].base;
+ port_p->ulCtrlPort2 = 0; /* NA */
+ port_p->ulDataPort = 0; /* NA */
+ port_p->getRegister = pci_ns16550_get_register;
+ port_p->setRegister = pci_ns16550_set_register;
+ port_p->getData = NULL; /* NA */
+ port_p->setData = NULL; /* NA */
+ port_p->ulClock = conf[b].clock;
+ port_p->ulIntVector = conf[b].irq;
+
+ port_p++;
+ } /* end boards */
+
+ /*
+ * Register the devices
+ */
+ console_register_devices( ports, total_ports );
+
+ /*
+ * Do not free the ports memory, the console hold this memory for-ever.
+ */
+ }
+ }
}
#endif
diff --git a/c/src/lib/libbsp/i386/pc386/include/bsp.h b/c/src/lib/libbsp/i386/pc386/include/bsp.h
index 34516f0..cdfbce6 100644
--- a/c/src/lib/libbsp/i386/pc386/include/bsp.h
+++ b/c/src/lib/libbsp/i386/pc386/include/bsp.h
@@ -197,7 +197,7 @@ void rtems_irq_mngt_init(void); /* from 'irq_init.c' */
*/
void *clock_driver_sim_idle_body(uintptr_t);
#define BSP_IDLE_TASK_BODY clock_driver_sim_idle_body
- /*
+ /*
* hack to kill some time. Hopefully hitting a hardware register is slower
* than an empty loop.
*/
@@ -255,6 +255,7 @@ void bsp_ide_cmdline_init(void);
void init_remote_gdb( void );
void i386_stub_glue_init(int uart);
void i386_stub_glue_init_breakin(void);
+int i386_stub_glue_uart(void);
void breakpoint(void);
#define BSP_MAXIMUM_DEVICES 6
diff --git a/c/src/lib/libbsp/i386/pc386/include/bspimpl.h b/c/src/lib/libbsp/i386/pc386/include/bspimpl.h
index 6503e0a..314fb91 100644
--- a/c/src/lib/libbsp/i386/pc386/include/bspimpl.h
+++ b/c/src/lib/libbsp/i386/pc386/include/bspimpl.h
@@ -1,7 +1,7 @@
/**
* @file
*
- * BSP specific helpers
+ * BSP specific helpers
*/
/*
@@ -30,6 +30,16 @@ const pci_config_access_functions *pci_io_initialize(void);
void pc386_parse_console_arguments(void);
/*
+ * Helper to parse boot command line arguments related to gdb
+ */
+void pc386_parse_gdb_arguments(void);
+
+/*
+ * Dynamically probe for Legacy UARTS
+ */
+void legacy_uart_probe(void);
+
+/*
* Dynamically probe for PCI UARTS
*/
void pci_uart_probe(void);
diff --git a/c/src/lib/libbsp/i386/pc386/startup/bspstart.c b/c/src/lib/libbsp/i386/pc386/startup/bspstart.c
index 41f858b..0559fbe 100644
--- a/c/src/lib/libbsp/i386/pc386/startup/bspstart.c
+++ b/c/src/lib/libbsp/i386/pc386/startup/bspstart.c
@@ -10,6 +10,9 @@
* It was subsequently adapted as part of the pc386 BSP by developers from
* the NavIST Group in 1997.
*
+ * Copyright (c) 2016.
+ * Chris Johns <chrisj at rtems.org>
+ *
* COPYRIGHT (c) 1989-2008, 2016.
* On-Line Applications Research Corporation (OAR).
*
@@ -107,16 +110,29 @@ static void bsp_start_default( void )
bsp_pci_initialize_helper();
/*
- * Probe for UARTs on PCI. One of these may end up as the console.
+ * Probe for legacy UARTs.
+ */
+ legacy_uart_probe();
+
+ /*
+ * Probe for UARTs on PCI.
*/
pci_uart_probe();
/*
- * Figure out where printk() and console IO is to be directed.
- * Do this after the PCI bus is initialized so we have a chance
- * for those devices to be added to the set in the console driver.
- * In general, Do it as early as possible so printk() has a chance
- * to work early on devices found via PCI probe.
+ * Parse the GDB arguments and flag a serial port as not valid. This stops
+ * the console from claming the port.
+ */
+#if BSP_GDB_STUB
+ pc386_parse_gdb_arguments();
+#endif
+
+ /*
+ * Figure out where printk() and console IO is to be directed. Do this after
+ * the legacy and PCI bus probes so we have a chance for those devices to be
+ * added to the set in the console driver. In general, do it as early as
+ * possible so printk() has a chance to work early on devices found via PCI
+ * probe.
*/
pc386_parse_console_arguments();
@@ -127,7 +143,6 @@ static void bsp_start_default( void )
#if BSP_ENABLE_IDE
bsp_ide_cmdline_init();
#endif
-
} /* bsp_start_default */
/*
diff --git a/c/src/lib/libbsp/i386/pc386/startup/ldsegs.S b/c/src/lib/libbsp/i386/pc386/startup/ldsegs.S
index 82ff982..ea41874 100644
--- a/c/src/lib/libbsp/i386/pc386/startup/ldsegs.S
+++ b/c/src/lib/libbsp/i386/pc386/startup/ldsegs.S
@@ -110,7 +110,6 @@ next_step:
movw ax, fs
movw ax, gs
-#if (BSP_IS_EDISON == 0)
/*---------------------------------------------------------------------+
| Now we have to reprogram the interrupts :-(. We put them right after
| the intel-reserved hardware interrupts, at int 0x20-0x2F. There they
@@ -121,6 +120,7 @@ next_step:
| it isn't fun.
+---------------------------------------------------------------------*/
+#if (BSP_IS_EDISON == 0)
movb $0x11, al /* initialization sequence */
outb al, $0x20 /* send it to 8259A-1 */
call SYM(pc386_delay)
diff --git a/c/src/lib/libbsp/i386/shared/comm/GDB.HOWTO b/c/src/lib/libbsp/i386/shared/comm/GDB.HOWTO
index c57f5a5..d5e0326 100644
--- a/c/src/lib/libbsp/i386/shared/comm/GDB.HOWTO
+++ b/c/src/lib/libbsp/i386/shared/comm/GDB.HOWTO
@@ -1,30 +1,31 @@
-1. Add GDB initilization to your target's code:
+i386/pc386 GDB Stub
-a) include file:
+The i386 GDB stub has been updated to use the libchip drivers for the
+NS16550. Make sure you have detect the device and you have added a console
+entry. On the PC the legacy and PCI boards are supported.
-#include <uart.h>
+This GDB stub glue code is specific to the UART protocol defined in libbchip.
-b) declare this variable:
+The pc386 BSP has boot command line options to manage GDB support.
-extern int BSPConsolePort;
+a) Find the minor number of the console device:
-c) To start-up GDB, run this:
+ #include <console_private.h>
- /* Init GDB glue */
+ rtems_device_minor_number minor = 0;
- if(BSPConsolePort != BSP_UART_COM2)
- {
- /*
- * If com2 is not used as console use it for
- * debugging
- */
- i386_stub_glue_init(BSP_UART_COM2);
- }
- else
- {
- /* Otherwise use com1 */
- i386_stub_glue_init(BSP_UART_COM1);
- }
+ if (console_find_console_entry("/dev/com1",
+ strlen("/dev/com1") - 1, &minor) == NULL)
+ error("driver not found\n");
+
+Note, this call is part of the private console API and may change.
+
+b) To start GDB stub, run this:
+
+ #include <bsp.h>
+
+ /* Init GDB glue */
+ i386_stub_glue_init(minor);
/* Init GDB stub itself */
set_debug_traps();
@@ -39,54 +40,45 @@ c) To start-up GDB, run this:
/* Put breakpoint in */
breakpoint();
-d) This is all you need to do for the target.
-
-2. Edit cmds: specify path to current directory and device used for debugging
- example of cmds is attached below. Make sure your paths are correct.
-3. type 'make'
-4. Boot o-pc386/<test>.exe on target computer, where <test> has the code from step 1. ( I modified and recompiled base_sp as the <test> )
-5. run 'i396-rtems-gdb --nx --command=./cmds o-pc386/<test>.coff
-
-=========================== example cmds ==============================
-/usr1/rtems/work/rtems/cpukit/ada
-/usr1/rtems/work/rtems/cpukit/libblock/src
-/usr1/rtems/work/rtems/cpukit/libcsupport/src
-/usr1/rtems/work/rtems/cpukit/libfs/src/dosfs
-/usr1/rtems/work/rtems/cpukit/libfs/src/imfs
-/usr1/rtems/work/rtems/cpukit/libmisc/capture
-/usr1/rtems/work/rtems/cpukit/libmisc/cpuuse
-/usr1/rtems/work/rtems/cpukit/libmisc/devnull
-/usr1/rtems/work/rtems/cpukit/libmisc/dummy
-/usr1/rtems/work/rtems/cpukit/libmisc/dumpbuf
-/usr1/rtems/work/rtems/cpukit/libmisc/monitor
-/usr1/rtems/work/rtems/cpukit/libmisc/mw-fb
-/usr1/rtems/work/rtems/cpukit/libmisc/rtmonuse
-/usr1/rtems/work/rtems/cpukit/libmisc/serdbg
-/usr1/rtems/work/rtems/cpukit/libmisc/shell
-/usr1/rtems/work/rtems/cpukit/libmisc/stackchk
-/usr1/rtems/work/rtems/cpukit/libmisc/untar
-/usr1/rtems/work/rtems/cpukit/libnetworking/arpa
-/usr1/rtems/work/rtems/cpukit/libnetworking/kern
-/usr1/rtems/work/rtems/cpukit/libnetworking/lib
-/usr1/rtems/work/rtems/cpukit/libnetworking/libc
-/usr1/rtems/work/rtems/cpukit/libnetworking/machine
-/usr1/rtems/work/rtems/cpukit/libnetworking/net
-/usr1/rtems/work/rtems/cpukit/libnetworking/netinet
-/usr1/rtems/work/rtems/cpukit/libnetworking/nfs
-/usr1/rtems/work/rtems/cpukit/libnetworking/rtems
-/usr1/rtems/work/rtems/cpukit/libnetworking/sys
-/usr1/rtems/work/rtems/cpukit/libnetworking/vm
-/usr1/rtems/work/rtems/cpukit/librpc/src/rpc
-/usr1/rtems/work/rtems/cpukit/librpc/src/xdr
-/usr1/rtems/work/rtems/cpukit/posix/src
-/usr1/rtems/work/rtems/cpukit/posix/inline/rtems/posix
-/usr1/rtems/work/rtems/cpukit/rtems/inline/rtems/rtems
-/usr1/rtems/work/rtems/cpukit/rtems/src
-/usr1/rtems/work/rtems/cpukit/sapi/inline/rtems
-/usr1/rtems/work/rtems/cpukit/sapi/src
-/usr1/rtems/work/rtems/cpukit/score/cpu/i386
-/usr1/rtems/work/rtems/cpukit/score/cpu/i386/rtems/score
-/usr1/rtems/work/rtems/cpukit/score/src
-/usr1/rtems/work/rtems/cpukit/score/inline/rtems/score
-set remotebaud 38400
-target remote /dev/ttyS1
+c) To run use GDB:
+
+ $ i386-rtems4.12-gdb hello.exe
+ GNU gdb (GDB) 7.11
+ Copyright (C) 2016 Free Software Foundation, Inc.
+ License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
+ This is free software: you are free to change and redistribute it.
+ There is NO WARRANTY, to the extent permitted by law. Type "show copying"
+ and "show warranty" for details.
+ This GDB was configured as "--host=x86_64-freebsd10.1 --target=i386-rtems4.12".
+ Type "show configuration" for configuration details.
+ For bug reporting instructions, please see:
+ <http://www.gnu.org/software/gdb/bugs/>.
+ Find the GDB manual and other documentation resources online at:
+ <http://www.gnu.org/software/gdb/documentation/>.
+ For help, type "help".
+ Type "apropos word" to search for commands related to "word"...
+ Reading symbols from hello.exe...done.
+ (gdb) target remote /dev/cuaU5
+ Remote debugging using /dev/cuaU5
+ 0x00103fda in breakpoint () at i386-stub.c:1004
+ 1004 BREAKPOINT ();
+ (gdb) b Init
+ Breakpoint 1 at 0x1001e0: file init.c, line 29.
+ (gdb) c
+ Continuing.
+
+ Breakpoint 1, Init (ignored=1269800) at init.c:29
+ 29 {
+ (gdb)
+
+Pressing ^C works and if running the board should halt when GDB connects.
+
+e) Use ser2net to provide reomve access over a network to a board. Install the
+ser2net package and add a configuration for the port GDB connects to. For
+example:
+
+ 0005:raw:0:/dev/cuaU5:115200
+
+Start ser2net running then connect GDB using:
+
+ (gdb) target remote myhost:30005
diff --git a/c/src/lib/libbsp/i386/shared/comm/i386-stub-glue.c b/c/src/lib/libbsp/i386/shared/comm/i386-stub-glue.c
index 121eef1..25a153f 100644
--- a/c/src/lib/libbsp/i386/shared/comm/i386-stub-glue.c
+++ b/c/src/lib/libbsp/i386/shared/comm/i386-stub-glue.c
@@ -1,23 +1,102 @@
/*
+ * Copyright (c) 2016.
+ * Chris Johns <chrisj at rtems.org>
+ *
* This software is Copyright (C) 1998 by T.sqware - all rights limited
* It is provided in to the public domain "as is", can be freely modified
* as far as this copyight notice is kept unchanged, but does not imply
* an endorsement by T.sqware of the product in which it is included.
*/
-#include <rtems/system.h>
-#include <rtems/score/cpu.h>
#include <bsp.h>
#include <bsp/irq.h>
-#include <uart.h>
-#include <assert.h>
+#include <libchip/serial.h>
+
+#include "../../../shared/console_private.h"
int putDebugChar(int ch); /* write a single character */
int getDebugChar(void); /* read and return a single char */
+/* Check is any characters received are a ^C */
+int i386_gdb_uart_ctrl_c_check(void);
+
+/* Raw interrupt handler. */
+void i386_gdb_uart_isr(void);
+
/* assign an exception handler */
void exceptionHandler(int, void (*handler)(void));
+/* User supplied remote debug option. */
+extern int remote_debug;
+
+/* Current uart and port used by the gdb stub */
+static int uart_current;
+static console_tbl* port_current;
+
+/*
+ * Interrupt service routine for all, it does it check whether ^C is received
+ * if yes it will flip TF bit before returning.
+ *
+ * Note: it should be installed as raw interrupt handler.
+ *
+ * Warning: I do not like the use of the global data, I am not
+ * sure if this is SMP safe.
+ */
+int i386_gdb_uart_isr_regsav[4] RTEMS_UNUSED;
+__asm__ (".p2align 4");
+__asm__ (".text");
+__asm__ (".globl i386_gdb_uart_isr");
+__asm__ ("i386_gdb_uart_isr:");
+__asm__ (" pusha"); /* Push all */
+__asm__ (" call i386_gdb_uart_ctrl_c_check"); /* Look for ^C */
+__asm__ (" movl %eax, i386_gdb_uart_isr_regsav"); /* Save eax */
+__asm__ (" popa"); /* Pop all */
+__asm__ (" xchgl %eax, i386_gdb_uart_isr_regsav"); /* Exchange eax */
+__asm__ (" cmpl $0, %eax"); /* 1 == ^C */
+__asm__ (" je i386_gdb_uart_isr_1"); /* branch if 0 */
+__asm__ (" movl %ebx, i386_gdb_uart_isr_regsav + 4"); /* Save ebx */
+__asm__ (" movl %edx, i386_gdb_uart_isr_regsav + 8"); /* Save edx */
+__asm__ (" popl %ebx"); /* Pop eip */
+__asm__ (" popl %edx"); /* Pop cs */
+__asm__ (" popl %eax"); /* Pop flags */
+__asm__ (" orl $0x100, %eax"); /* Modify it */
+__asm__ (" pushl %eax"); /* Push it back */
+__asm__ (" pushl %edx"); /* Push cs */
+__asm__ (" pushl %ebx"); /* Push eip */
+__asm__ (" movl i386_gdb_uart_isr_regsav + 4, %ebx"); /* Restore ebx */
+__asm__ (" movl i386_gdb_uart_isr_regsav + 8, %edx"); /* Restore edx */
+__asm__ ("i386_gdb_uart_isr_1:");
+__asm__ (" movb $0x20, %al");
+__asm__ (" outb %al, $0x20");
+__asm__ (" movl i386_gdb_uart_isr_regsav, %eax"); /* Restore eax */
+__asm__ (" iret"); /* Done */
+
+static int gdb_hello_index;
+static const char const* gdb_hello = "+";
+
+int i386_gdb_uart_ctrl_c_check(void)
+{
+ if (port_current) {
+ int c = 0;
+ while (c >= 0) {
+ c = port_current->pDeviceFns->deviceRead(uart_current);
+ if (c == 3) {
+ gdb_hello_index = 0;
+ return 1;
+ } else if (gdb_hello[gdb_hello_index] == (char) c) {
+ ++gdb_hello_index;
+ if (gdb_hello[gdb_hello_index] == '\0') {
+ gdb_hello_index = 0;
+ return 1;
+ }
+ } else {
+ gdb_hello_index = 0;
+ }
+ }
+ }
+ return 0;
+}
+
static void
nop(const rtems_raw_irq_connect_data* notused)
{
@@ -29,10 +108,12 @@ isOn(const rtems_raw_irq_connect_data* notused)
return 1;
}
-void BSP_loop(int uart);
-
-/* Current uart used by gdb stub */
-static int uart_current = 0;
+int i386_stub_glue_uart(void)
+{
+ if (port_current == NULL)
+ return -1;
+ return uart_current;
+}
/*
* Initialize glue code linking i386-stub with the rest of
@@ -41,12 +122,19 @@ static int uart_current = 0;
void
i386_stub_glue_init(int uart)
{
- assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
+ rtems_device_minor_number minor = (rtems_device_minor_number) uart;
+
+ port_current = console_find_console_entry(NULL, 0, &minor);
+
+ if (port_current == NULL) {
+ printk("GDB: invalid minor number for UART\n");
+ return;
+ }
uart_current = uart;
- /* BSP_uart_init(uart, 38400, CHR_8_BITS, 0, 0, 0);*/
- BSP_uart_init(uart, 115200, CHR_8_BITS, 0, 0, 0);
+ /* Intialise the UART, assuming polled drivers */
+ port_current->pDeviceFns->deviceInitialize(uart);
}
static void BSP_uart_on(const rtems_raw_irq_connect_data* used)
@@ -72,76 +160,65 @@ void i386_stub_glue_init_breakin(void)
{
rtems_raw_irq_connect_data uart_raw_irq_data;
- assert(uart_current == BSP_UART_COM1 || uart_current == BSP_UART_COM2);
+ if (port_current == NULL) {
+ printk("GDB: no port initialised\n");
+ return;
+ }
- if(uart_current == BSP_UART_COM1)
- {
- uart_raw_irq_data.idtIndex = BSP_UART_COM1_IRQ + BSP_IRQ_VECTOR_BASE;
- }
- else
- {
- uart_raw_irq_data.idtIndex = BSP_UART_COM2_IRQ + BSP_IRQ_VECTOR_BASE;
- }
+ if ((port_current->ulIntVector == 0) || (port_current->ulIntVector > 16)) {
+ printk("GDB: no UART interrupt support\n");
+ }
+ else {
+ uart_raw_irq_data.idtIndex = port_current->ulIntVector + BSP_IRQ_VECTOR_BASE;
- if(!i386_get_current_idt_entry(&uart_raw_irq_data))
- {
- printk("cannot get idt entry\n");
+ if (!i386_get_current_idt_entry(&uart_raw_irq_data)) {
+ printk("GBD: cannot get idt entry\n");
rtems_fatal_error_occurred(1);
}
- if(!i386_delete_idt_entry(&uart_raw_irq_data))
- {
- printk("cannot delete idt entry\n");
+ if (!i386_delete_idt_entry(&uart_raw_irq_data)) {
+ printk("GDB: cannot delete idt entry\n");
rtems_fatal_error_occurred(1);
}
- uart_raw_irq_data.on = BSP_uart_on;
- uart_raw_irq_data.off = BSP_uart_off;
- uart_raw_irq_data.isOn= BSP_uart_isOn;
+ uart_raw_irq_data.on = BSP_uart_on;
+ uart_raw_irq_data.off = BSP_uart_off;
+ uart_raw_irq_data.isOn= BSP_uart_isOn;
- /* Install ISR */
- if(uart_current == BSP_UART_COM1)
- {
- uart_raw_irq_data.idtIndex = BSP_UART_COM1_IRQ + BSP_IRQ_VECTOR_BASE;
- uart_raw_irq_data.hdl = BSP_uart_dbgisr_com1;
- }
- else
- {
- uart_raw_irq_data.idtIndex = BSP_UART_COM2_IRQ + BSP_IRQ_VECTOR_BASE;
- uart_raw_irq_data.hdl = BSP_uart_dbgisr_com2;
- }
+ /* Install ISR */
+ uart_raw_irq_data.idtIndex = port_current->ulIntVector + BSP_IRQ_VECTOR_BASE;
+ uart_raw_irq_data.hdl = i386_gdb_uart_isr;
- if (!i386_set_idt_entry (&uart_raw_irq_data))
- {
- printk("raw exception handler connection failed\n");
+ if (!i386_set_idt_entry (&uart_raw_irq_data)) {
+ printk("GDB: raw exception handler connection failed\n");
rtems_fatal_error_occurred(1);
}
- /* Enable interrupts */
- BSP_uart_intr_ctrl(uart_current, BSP_UART_INTR_CTRL_GDB);
-
- return;
+ /* Enable interrupts, this is a bit of a hack because we
+ * have to know the device but there is no other call. */
+ (*port_current->setRegister)(port_current->ulCtrlPort1, 1, 0x01);
+ }
}
int
putDebugChar(int ch)
{
- assert(uart_current == BSP_UART_COM1 || uart_current == BSP_UART_COM2);
-
- BSP_uart_polled_write(uart_current, ch);
-
+ if (port_current != NULL) {
+ port_current->pDeviceFns->deviceWritePolled(uart_current, ch);
+ }
return 1;
}
int getDebugChar(void)
{
- int val;
-
- assert(uart_current == BSP_UART_COM1 || uart_current == BSP_UART_COM2);
+ int c = -1;
- val = BSP_uart_polled_read(uart_current);
+ if (port_current != NULL) {
+ while (c < 0)
+ c = port_current->pDeviceFns->deviceRead(uart_current);
+ }
- return val;
+ return c;
}
void exceptionHandler(int vector, void (*handler)(void))
@@ -152,13 +229,13 @@ void exceptionHandler(int vector, void (*handler)(void))
if(!i386_get_current_idt_entry(&excep_raw_irq_data))
{
- printk("cannot get idt entry\n");
+ printk("GDB: cannot get idt entry\n");
rtems_fatal_error_occurred(1);
}
if(!i386_delete_idt_entry(&excep_raw_irq_data))
{
- printk("cannot delete idt entry\n");
+ printk("GDB: cannot delete idt entry\n");
rtems_fatal_error_occurred(1);
}
@@ -168,7 +245,7 @@ void exceptionHandler(int vector, void (*handler)(void))
excep_raw_irq_data.hdl = handler;
if (!i386_set_idt_entry (&excep_raw_irq_data)) {
- printk("raw exception handler connection failed\n");
+ printk("GDB: raw exception handler connection failed\n");
rtems_fatal_error_occurred(1);
}
return;
diff --git a/c/src/lib/libbsp/i386/shared/comm/i386-stub.c b/c/src/lib/libbsp/i386/shared/comm/i386-stub.c
index bc72396..b3630ee 100644
--- a/c/src/lib/libbsp/i386/shared/comm/i386-stub.c
+++ b/c/src/lib/libbsp/i386/shared/comm/i386-stub.c
@@ -99,6 +99,8 @@
#include <string.h>
#include <stdbool.h>
+#include <bsp.h>
+
/*
* Prototypes we need to avoid warnings but not going into public space.
*/
@@ -150,11 +152,15 @@ enum regnames
/*
* these should not be static cuz they can be used outside this module
*/
-int registers[NUMREGS];
+
+int i386_gdb_registers[NUMREGS];
#define STACKSIZE 10000
-int remcomStack[STACKSIZE / sizeof (int)];
-static int *stackPtr = &remcomStack[STACKSIZE / sizeof (int) - 1];
+int i386_gdb_remcomStack[STACKSIZE / sizeof (int)];
+int *i386_gdb_stackPtr = &i386_gdb_remcomStack[STACKSIZE / sizeof (int) - 1];
+
+
+static int gdb_connected;
/*************************** ASSEMBLY CODE MACROS *************************/
/* */
@@ -168,25 +174,25 @@ extern void
__asm__ (".text");
__asm__ (".globl return_to_prog");
__asm__ ("return_to_prog:");
-__asm__ (" movw registers+44, %ss");
-__asm__ (" movl registers+16, %esp");
-__asm__ (" movl registers+4, %ecx");
-__asm__ (" movl registers+8, %edx");
-__asm__ (" movl registers+12, %ebx");
-__asm__ (" movl registers+20, %ebp");
-__asm__ (" movl registers+24, %esi");
-__asm__ (" movl registers+28, %edi");
-__asm__ (" movw registers+48, %ds");
-__asm__ (" movw registers+52, %es");
-__asm__ (" movw registers+56, %fs");
-__asm__ (" movw registers+60, %gs");
-__asm__ (" movl registers+36, %eax");
+__asm__ (" movw i386_gdb_registers+44, %ss");
+__asm__ (" movl i386_gdb_registers+16, %esp");
+__asm__ (" movl i386_gdb_registers+4, %ecx");
+__asm__ (" movl i386_gdb_registers+8, %edx");
+__asm__ (" movl i386_gdb_registers+12, %ebx");
+__asm__ (" movl i386_gdb_registers+20, %ebp");
+__asm__ (" movl i386_gdb_registers+24, %esi");
+__asm__ (" movl i386_gdb_registers+28, %edi");
+__asm__ (" movw i386_gdb_registers+48, %ds");
+__asm__ (" movw i386_gdb_registers+52, %es");
+__asm__ (" movw i386_gdb_registers+56, %fs");
+__asm__ (" movw i386_gdb_registers+60, %gs");
+__asm__ (" movl i386_gdb_registers+36, %eax");
__asm__ (" pushl %eax"); /* saved eflags */
-__asm__ (" movl registers+40, %eax");
+__asm__ (" movl i386_gdb_registers+40, %eax");
__asm__ (" pushl %eax"); /* saved cs */
-__asm__ (" movl registers+32, %eax");
+__asm__ (" movl i386_gdb_registers+32, %eax");
__asm__ (" pushl %eax"); /* saved eip */
-__asm__ (" movl registers, %eax");
+__asm__ (" movl i386_gdb_registers, %eax");
/* use iret to restore pc and flags together so
that trace flag works right. */
__asm__ (" iret");
@@ -202,37 +208,37 @@ int gdb_i386vector = -1;
/* GDB stores segment registers in 32-bit words (that's just the way
m-i386v.h is written). So zero the appropriate areas in registers. */
#define SAVE_REGISTERS1() \
- __asm__ ("movl %eax, registers"); \
- __asm__ ("movl %ecx, registers+4"); \
- __asm__ ("movl %edx, registers+8"); \
- __asm__ ("movl %ebx, registers+12"); \
- __asm__ ("movl %ebp, registers+20"); \
- __asm__ ("movl %esi, registers+24"); \
- __asm__ ("movl %edi, registers+28"); \
- __asm__ ("movw $0, %ax"); \
- __asm__ ("movw %ds, registers+48"); \
- __asm__ ("movw %ax, registers+50"); \
- __asm__ ("movw %es, registers+52"); \
- __asm__ ("movw %ax, registers+54"); \
- __asm__ ("movw %fs, registers+56"); \
- __asm__ ("movw %ax, registers+58"); \
- __asm__ ("movw %gs, registers+60"); \
- __asm__ ("movw %ax, registers+62");
+ __asm__ ("movl %eax, i386_gdb_registers"); \
+ __asm__ ("movl %ecx, i386_gdb_registers+4"); \
+ __asm__ ("movl %edx, i386_gdb_registers+8"); \
+ __asm__ ("movl %ebx, i386_gdb_registers+12"); \
+ __asm__ ("movl %ebp, i386_gdb_registers+20"); \
+ __asm__ ("movl %esi, i386_gdb_registers+24"); \
+ __asm__ ("movl %edi, i386_gdb_registers+28"); \
+ __asm__ ("movw $0, %ax"); \
+ __asm__ ("movw %ds, i386_gdb_registers+48"); \
+ __asm__ ("movw %ax, i386_gdb_registers+50"); \
+ __asm__ ("movw %es, i386_gdb_registers+52"); \
+ __asm__ ("movw %ax, i386_gdb_registers+54"); \
+ __asm__ ("movw %fs, i386_gdb_registers+56"); \
+ __asm__ ("movw %ax, i386_gdb_registers+58"); \
+ __asm__ ("movw %gs, i386_gdb_registers+60"); \
+ __asm__ ("movw %ax, i386_gdb_registers+62");
#define SAVE_ERRCODE() \
- __asm__ ("popl %ebx"); \
+ __asm__ ("popl %ebx"); \
__asm__ ("movl %ebx, gdb_i386errcode");
#define SAVE_REGISTERS2() \
- __asm__ ("popl %ebx"); /* old eip */ \
- __asm__ ("movl %ebx, registers+32"); \
- __asm__ ("popl %ebx"); /* old cs */ \
- __asm__ ("movl %ebx, registers+40"); \
- __asm__ ("movw %ax, registers+42"); \
- __asm__ ("popl %ebx"); /* old eflags */ \
- __asm__ ("movl %ebx, registers+36"); \
- /* Now that we've done the pops, we can save the stack pointer."); */ \
- __asm__ ("movw %ss, registers+44"); \
- __asm__ ("movw %ax, registers+46"); \
- __asm__ ("movl %esp, registers+16");
+ __asm__ ("popl %ebx"); /* old eip */ \
+ __asm__ ("movl %ebx, i386_gdb_registers+32"); \
+ __asm__ ("popl %ebx"); /* old cs */ \
+ __asm__ ("movl %ebx, i386_gdb_registers+40"); \
+ __asm__ ("movw %ax, i386_gdb_registers+42"); \
+ __asm__ ("popl %ebx"); /* old eflags */ \
+ __asm__ ("movl %ebx, i386_gdb_registers+36"); \
+ /* Now that we've done the pops, we can save the stack pointer."); */ \
+ __asm__ ("movw %ss, i386_gdb_registers+44"); \
+ __asm__ ("movw %ax, i386_gdb_registers+46"); \
+ __asm__ ("movl %esp, i386_gdb_registers+16");
/* See if mem_fault_routine is set, if so just IRET to that address. */
#define CHECK_FAULT() \
@@ -449,7 +455,7 @@ extern void remcomHandler (void);
__asm__ ("_remcomHandler:");
__asm__ (" popl %eax"); /* pop off return address */
__asm__ (" popl %eax"); /* get the exception number */
-__asm__ (" movl stackPtr, %esp"); /* move to remcom stack area */
+__asm__ (" movl i386_gdb_stackPtr, %esp"); /* move to remcom stack area */
__asm__ (" pushl %eax"); /* push exception onto stack */
__asm__ (" call handle_exception"); /* this never returns */
@@ -508,10 +514,15 @@ getpacket (char *buffer)
xmitcsum += hex (getDebugChar () & 0x7f);
if ((remote_debug) && (checksum != xmitcsum))
{
- fprintf (stderr, "bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n",
- checksum, xmitcsum, buffer);
+ printk ("bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n",
+ checksum, xmitcsum, buffer);
}
+ if (remote_debug) {
+ printk("GETP: $%s...%s\n", buffer,
+ checksum == xmitcsum ? "Ack" : "Nack");
+ }
+
if (checksum != xmitcsum)
putDebugChar ('-'); /* failed checksum */
else
@@ -539,13 +550,16 @@ getpacket (char *buffer)
static void
putpacket (char *buffer)
{
- unsigned char checksum;
- int count;
- char ch;
-
/* $<packet info>#<checksum>. */
- do
+ while (true)
{
+ unsigned char checksum;
+ int count;
+ char ch;
+
+ if (remote_debug)
+ printk("PUTP: $%s", buffer);
+
putDebugChar ('$');
checksum = 0;
count = 0;
@@ -562,9 +576,18 @@ putpacket (char *buffer)
putDebugChar (hexchars[checksum >> 4]);
putDebugChar (hexchars[checksum % 16]);
- }
- while ((getDebugChar () & 0x7f) != '+');
+ if (remote_debug)
+ printk("#%c%c...", hexchars[checksum >> 4], hexchars[checksum % 16]);
+ ch = getDebugChar () & 0x7f;
+ if (ch == '+') {
+ if (remote_debug)
+ printk("Ack\n");
+ break;
+ }
+ if (remote_debug)
+ printk("Nack(%c)\n", ch);
+ }
}
char remcomInBuffer[BUFMAX];
@@ -578,7 +601,7 @@ debug_error (
)
{
if (remote_debug)
- fprintf (stderr, format, parm);
+ printk (format, parm);
}
/* Address of a routine to RTE to if we get a memory fault. */
@@ -764,10 +787,10 @@ handle_exception (int exceptionVector)
gdb_i386vector = exceptionVector;
if (remote_debug)
- printf ("vector=%d, sr=0x%x, pc=0x%x\n",
+ printk ("GDB: EXECPTION: vector=%d, sr=0x%x, pc=0x%x\n",
exceptionVector,
- registers[PS],
- registers[PC]);
+ i386_gdb_registers[PS],
+ i386_gdb_registers[PC]);
/* Reply to host that an exception has occurred. Always return the
PC, SP, and FP, since gdb always wants them. */
@@ -779,31 +802,33 @@ handle_exception (int exceptionVector)
*ptr++ = hexchars[ESP];
*ptr++ = ':';
- mem2hex ((char *) ®isters[ESP], ptr, REGBYTES, 0);
+ mem2hex ((char *) &i386_gdb_registers[ESP], ptr, REGBYTES, 0);
ptr += REGBYTES * 2;
*ptr++ = ';';
*ptr++ = hexchars[EBP];
*ptr++ = ':';
- mem2hex ((char *) ®isters[EBP], ptr, REGBYTES, 0);
+ mem2hex ((char *) &i386_gdb_registers[EBP], ptr, REGBYTES, 0);
ptr += REGBYTES * 2;
*ptr++ = ';';
*ptr++ = hexchars[PC];
*ptr++ = ':';
- mem2hex ((char *) ®isters[PC], ptr, REGBYTES, 0);
+ mem2hex ((char *) &i386_gdb_registers[PC], ptr, REGBYTES, 0);
ptr += REGBYTES * 2;
*ptr++ = ';';
*ptr = '\0';
- putpacket (remcomOutBuffer);
+ if (gdb_connected)
+ putpacket (remcomOutBuffer);
while (1 == 1)
{
error = 0;
remcomOutBuffer[0] = 0;
getpacket (remcomInBuffer);
+ gdb_connected = 1;
switch (remcomInBuffer[0])
{
case '?':
@@ -812,14 +837,14 @@ handle_exception (int exceptionVector)
remcomOutBuffer[2] = hexchars[sigval % 16];
remcomOutBuffer[3] = 0;
break;
- case 'd':
+ case 'd': /* remove */
remote_debug = !(remote_debug); /* toggle debug flag */
break;
case 'g': /* return the value of the CPU registers */
- mem2hex ((char *) registers, remcomOutBuffer, NUMREGBYTES, 0);
+ mem2hex ((char *) i386_gdb_registers, remcomOutBuffer, NUMREGBYTES, 0);
break;
case 'G': /* set the value of the CPU registers - return OK */
- hex2mem (&remcomInBuffer[1], (char *) registers, NUMREGBYTES, 0);
+ hex2mem (&remcomInBuffer[1], (char *) i386_gdb_registers, NUMREGBYTES, 0);
strcpy (remcomOutBuffer, "OK");
break;
@@ -828,7 +853,7 @@ handle_exception (int exceptionVector)
if (hexToInt (&ptr, ®)
&& *ptr++ == '=')
{
- hex2mem (ptr, (char *) ®isters[reg], REGBYTES, 0);
+ hex2mem (ptr, (char *) &i386_gdb_registers[reg], REGBYTES, 0);
strcpy (remcomOutBuffer, "OK");
}
else
@@ -902,29 +927,31 @@ handle_exception (int exceptionVector)
/* try to read optional parameter, pc unchanged if no parm */
ptr = &remcomInBuffer[1];
if (hexToInt (&ptr, &addr))
- registers[PC] = addr;
+ i386_gdb_registers[PC] = addr;
/* clear the trace bit */
- registers[PS] &= 0xfffffeff;
+ i386_gdb_registers[PS] &= 0xfffffeff;
/* set the trace bit if we're stepping */
if (remcomInBuffer[0] == 's')
- registers[PS] |= 0x100;
+ i386_gdb_registers[PS] |= 0x100;
_returnFromException (); /* this is a jump */
-
break;
/* Detach. */
case 'D':
putpacket (remcomOutBuffer);
- registers[PS] &= 0xfffffeff;
+ i386_gdb_registers[PS] &= 0xfffffeff;
_returnFromException (); /* this is a jump */
-
break;
/* kill the program */
case 'k': /* do nothing */
+ bsp_reset();
+ continue;
+
+ default:
break;
} /* switch */
@@ -938,7 +965,7 @@ handle_exception (int exceptionVector)
void
set_debug_traps (void)
{
- stackPtr = &remcomStack[STACKSIZE / sizeof (int) - 1];
+ i386_gdb_stackPtr = &i386_gdb_remcomStack[STACKSIZE / sizeof (int) - 1];
exceptionHandler (0, _catchException0);
exceptionHandler (1, _catchException1);
diff --git a/c/src/lib/libbsp/shared/console.c b/c/src/lib/libbsp/shared/console.c
index d226172..b4af1b3 100644
--- a/c/src/lib/libbsp/shared/console.c
+++ b/c/src/lib/libbsp/shared/console.c
@@ -34,6 +34,45 @@ rtems_device_minor_number Console_Port_Minor = 0;
static bool console_initialized = false;
/*
+ * console_find_console_entry
+ *
+ * This method is used to search the console entries for a
+ * specific device entry.
+ */
+console_tbl* console_find_console_entry(
+ const char *match,
+ size_t length,
+ rtems_device_minor_number *match_minor
+)
+{
+ rtems_device_minor_number minor;
+
+ /*
+ * The the match name is NULL get the minor number entry.
+ */
+ if (match == NULL) {
+ if (*match_minor < Console_Port_Count)
+ return Console_Port_Tbl[*match_minor];
+ return NULL;
+ }
+
+ for (minor=0; minor < Console_Port_Count ; minor++) {
+ console_tbl *cptr = Console_Port_Tbl[minor];
+
+ /*
+ * Console table entries include /dev/ prefix, device names passed
+ * in on command line do not.
+ */
+ if ( !strncmp( cptr->sDeviceName, match, length ) ) {
+ *match_minor = minor;
+ return cptr;
+ }
+ }
+
+ return NULL;
+}
+
+/*
* console_initialize_data
*
* This method is used to initialize the table of pointers to the
@@ -278,9 +317,7 @@ rtems_device_driver console_initialize(
* must still initialize pointers for Console_Port_Tbl and
* Console_Port_Data.
*/
- if ( !Console_Port_Tbl ) {
- console_initialize_data();
- }
+ console_initialize_data();
/*
* console_initialize has been invoked so it is now too late to
diff --git a/c/src/lib/libbsp/shared/console_private.h b/c/src/lib/libbsp/shared/console_private.h
index 42a8ee9..3855e83 100644
--- a/c/src/lib/libbsp/shared/console_private.h
+++ b/c/src/lib/libbsp/shared/console_private.h
@@ -41,6 +41,19 @@ int vt_ioctl(
);
/**
+ * @brief console_find_console_entry
+ *
+ * This method is used to search the console entries for a
+ * specific device entry and return it. If match is NULL the
+ * minor number provided is matched.
+ */
+console_tbl* console_find_console_entry(
+ const char *match,
+ size_t length,
+ rtems_device_minor_number *match_minor
+);
+
+/**
* @brief console_initialize_data
*
* This must be called before dynamic registration of devices can occur.
--
2.4.6
More information about the devel
mailing list