You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2023/07/14 17:57:17 UTC

[nuttx] branch master updated (97309dd22d -> 6c1a7c4265)

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


    from 97309dd22d cmake: fix nrf91 modem static library build
     new b956495c5e libs/libc:Support gdb rsp protocol
     new 6c1a7c4265 support esp32c3-devkit gdbstub use wifi

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../configs/{wifi => gdbstub}/defconfig            |    6 +
 .../esp32_spiflash.h => include/nuttx/gdbstub.h    |   99 +-
 libs/libc/Kconfig                                  |    1 +
 libs/libc/Makefile                                 |    1 +
 libs/libc/gdbstub/Kconfig                          |   20 +
 libs/libc/{lzf => gdbstub}/Make.defs               |   10 +-
 libs/libc/gdbstub/lib_gdbstub.c                    | 1559 ++++++++++++++++++++
 7 files changed, 1635 insertions(+), 61 deletions(-)
 copy boards/risc-v/esp32c3/esp32c3-devkit/configs/{wifi => gdbstub}/defconfig (93%)
 copy arch/xtensa/src/esp32/esp32_spiflash.h => include/nuttx/gdbstub.h (54%)
 create mode 100644 libs/libc/gdbstub/Kconfig
 copy libs/libc/{lzf => gdbstub}/Make.defs (88%)
 create mode 100644 libs/libc/gdbstub/lib_gdbstub.c


[nuttx] 01/02: libs/libc:Support gdb rsp protocol

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit b956495c5eb00396569133dddfdf28a05fe5a1de
Author: anjiahao <an...@xiaomi.com>
AuthorDate: Fri Jul 7 11:08:09 2023 +0800

    libs/libc:Support gdb rsp protocol
    
    you can debug nuttx through any transport layer (serial port, network etc.),
    currently supports the following functions:
    1. Read and write registers
    2. Read and write memory
    3. Switch thread and read stack information
    
    Future support plans:
    1. Support breakpoint, watch point (requires architecture support).
    
    related information:
    https://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html
    
    Signed-off-by: anjiahao <an...@xiaomi.com>
---
 include/nuttx/gdbstub.h         |  113 +++
 libs/libc/Kconfig               |    1 +
 libs/libc/Makefile              |    1 +
 libs/libc/gdbstub/Kconfig       |   20 +
 libs/libc/gdbstub/Make.defs     |   32 +
 libs/libc/gdbstub/lib_gdbstub.c | 1559 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 1726 insertions(+)

diff --git a/include/nuttx/gdbstub.h b/include/nuttx/gdbstub.h
new file mode 100644
index 0000000000..0772e6f049
--- /dev/null
+++ b/include/nuttx/gdbstub.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+ * include/nuttx/gdbstub.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_GDBSTUB_H
+#define __INCLUDE_NUTTX_GDBSTUB_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdlib.h>
+
+/****************************************************************************
+ * Type Definitions
+ ****************************************************************************/
+
+struct gdb_state_s;
+typedef CODE ssize_t (*gdb_send_func_t)(FAR void *priv, FAR void *buf,
+                                        size_t len);
+typedef CODE ssize_t (*gdb_recv_func_t)(FAR void *priv, FAR void *buf,
+                                        size_t len);
+
+typedef CODE int (*gdb_monitor_func_t)(FAR struct gdb_state_s *state,
+                                       FAR const char *cmd);
+
+/****************************************************************************
+ * Name: gdb_state_init
+ *
+ * Description:
+ *   Initialize the GDB state structure.
+ *
+ * Input Parameters:
+ *   send    - The pointer to the send function.
+ *   recv    - The pointer to the receive function.
+ *   monitor - The pointer to the monitor function.
+ *   priv    - The pointer to the private data.
+ *
+ * Returned Value:
+ *   The pointer to the GDB state structure on success.
+ *   NULL on failure.
+ *
+ ****************************************************************************/
+
+FAR struct gdb_state_s *gdb_state_init(gdb_send_func_t send,
+                                       gdb_recv_func_t recv,
+                                       gdb_monitor_func_t monitor,
+                                       FAR void *priv);
+
+/****************************************************************************
+ * Name: gdb_state_uninit
+ *
+ * Description:
+ *   Uninitialize the GDB state structure.
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *
+ ****************************************************************************/
+
+void gdb_state_uninit(FAR struct gdb_state_s *state);
+
+/****************************************************************************
+ * Name: gdb_console_message
+ *
+ * Description:
+ *   Send a message to the GDB console (via O XX... packet).
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *
+ * Returned Value:
+ *    Zero on success.
+ *    Negative value on error.
+ *
+ ****************************************************************************/
+
+int gdb_console_message(FAR struct gdb_state_s *state, FAR const char *msg);
+
+/****************************************************************************
+ * Name: gdb_process
+ *
+ * Description:
+ *   Main debug loop. Handles commands.
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *
+ * Returned Value:
+ *   Zero if successful.
+ *   Negative value on error.
+ *
+ ****************************************************************************/
+
+int gdb_process(FAR struct gdb_state_s *state);
+
+#endif /* __INCLUDE_NUTTX_GDBSTUB_H */
diff --git a/libs/libc/Kconfig b/libs/libc/Kconfig
index 1e26b3ee38..ac59bac040 100644
--- a/libs/libc/Kconfig
+++ b/libs/libc/Kconfig
@@ -14,6 +14,7 @@ source "libs/libc/string/Kconfig"
 source "libs/libc/pthread/Kconfig"
 source "libs/libc/dlfcn/Kconfig"
 source "libs/libc/modlib/Kconfig"
+source "libs/libc/gdbstub/Kconfig"
 source "libs/libc/grp/Kconfig"
 source "libs/libc/pwd/Kconfig"
 source "libs/libc/locale/Kconfig"
diff --git a/libs/libc/Makefile b/libs/libc/Makefile
index 40e87f58fb..b08dabe046 100644
--- a/libs/libc/Makefile
+++ b/libs/libc/Makefile
@@ -30,6 +30,7 @@ include dlfcn/Make.defs
 include errno/Make.defs
 include eventfd/Make.defs
 include fixedmath/Make.defs
+include gdbstub/Make.defs
 include grp/Make.defs
 include hex2bin/Make.defs
 include inttypes/Make.defs
diff --git a/libs/libc/gdbstub/Kconfig b/libs/libc/gdbstub/Kconfig
new file mode 100644
index 0000000000..faa91cdb90
--- /dev/null
+++ b/libs/libc/gdbstub/Kconfig
@@ -0,0 +1,20 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+config LIB_GDBSTUB
+	tristate "GDBSTUB"
+	depends on DEBUG_TCBINFO
+	---help---
+		Enable support for gdbstub.
+
+if LIB_GDBSTUB
+
+config LIB_GDBSTUB_DEBUG
+	bool "Gdbstub Debug Info"
+	default n
+	---help---
+		Add debug info to gdbstub
+
+endif
diff --git a/libs/libc/gdbstub/Make.defs b/libs/libc/gdbstub/Make.defs
new file mode 100644
index 0000000000..77c2180c80
--- /dev/null
+++ b/libs/libc/gdbstub/Make.defs
@@ -0,0 +1,32 @@
+############################################################################
+# libs/libc/gdbstub/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+ifeq ($(CONFIG_LIB_GDBSTUB),y)
+
+# Add the internal C files to the build
+
+CSRCS += lib_gdbstub.c
+
+# Add the userfs directory to the build
+
+DEPPATH += --dep-path gdbstub
+VPATH += :gdbstub
+
+endif
diff --git a/libs/libc/gdbstub/lib_gdbstub.c b/libs/libc/gdbstub/lib_gdbstub.c
new file mode 100644
index 0000000000..67b4dbb5ad
--- /dev/null
+++ b/libs/libc/gdbstub/lib_gdbstub.c
@@ -0,0 +1,1559 @@
+/****************************************************************************
+ * libs/libc/gdbstub/lib_gdbstub.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <ctype.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <nuttx/sched.h>
+#include <nuttx/gdbstub.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifdef CONFIG_LIB_GDBSTUB_DEBUG
+#  define GDB_DEBUG(...) syslog(LOG_DEBUG, ##__VA_ARGS__)
+#  define GDB_ASSERT() __assert(__FILE__, __LINE__, 0)
+#else
+#  define GDB_DEBUG(...)
+#  define GDB_ASSERT() do {} while (0)
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct gdb_state_s
+{
+  gdb_send_func_t send;                   /* Send buffer to gdb */
+  gdb_recv_func_t recv;                   /* Recv buffer from gdb */
+  FAR void *priv;                         /* Private data for transport */
+  gdb_monitor_func_t monitor;             /* Monitor will be called when gdb
+                                           * receive a monitor command
+                                           */
+  pid_t pid;                              /* Gdb current thread */
+  FAR char *pkt_next;                     /* Pointer to next byte in packet */
+  char pkt_buf[1024];                     /* Packet buffer */
+  size_t pkt_len;                         /* Packet send and receive length */
+  uint8_t running_regs[XCPTCONTEXT_SIZE]; /* Registers of running thread */
+  size_t size;                            /* Size of registers */
+  uintptr_t registers[0];                 /* Registers of other threads */
+};
+
+typedef CODE ssize_t (*gdb_format_func_t)(FAR void *buf, size_t buf_len,
+                                          FAR const void *data,
+                                          size_t data_len);
+
+/* Calculate remaining space in packet from ptr_next position. */
+
+#define gdb_remaining_len(state) ((state)->pkt_len - \
+                                  ((state)->pkt_next - (state)->pkt_buf))
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions Prototypes
+ ****************************************************************************/
+
+/* System functions, supported by all stubs */
+
+static int gdb_getchar(FAR struct gdb_state_s *state);
+static int gdb_putchar(FAR struct gdb_state_s *state, int ch);
+
+/* Packet functions */
+
+static int gdb_send_packet(FAR struct gdb_state_s *state);
+static int gdb_recv_packet(FAR struct gdb_state_s *state);
+static int gdb_checksum(FAR const char *buf, size_t len);
+static int gdb_recv_ack(FAR struct gdb_state_s *state);
+
+/* Data format */
+
+static ssize_t gdb_bin2hex(FAR void *buf, size_t buf_len,
+                           FAR const void *data, size_t data_len);
+static ssize_t gdb_hex2bin(FAR void *buf, size_t buf_len,
+                           FAR const void *data, size_t data_len);
+static ssize_t gdb_bin2bin(FAR void *buf, size_t buf_len,
+                           FAR const void *data, size_t data_len);
+
+/* Packet creation helpers */
+
+static int gdb_send_ok_packet(FAR struct gdb_state_s *state);
+static int gdb_send_signal_packet(FAR struct gdb_state_s *state,
+                                  unsigned char signal);
+static int gdb_send_error_packet(FAR struct gdb_state_s *state,
+                                 unsigned char error);
+
+/* Command functions */
+
+static ssize_t gdb_get_memory(FAR struct gdb_state_s *state,
+                              FAR void *buf, size_t buf_len,
+                              uintptr_t addr, size_t len,
+                              gdb_format_func_t format);
+static ssize_t gdb_put_memory(FAR struct gdb_state_s *state,
+                              FAR const void *buf, size_t buf_len,
+                              uintptr_t addr, size_t len,
+                              gdb_format_func_t format);
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Packet buffer Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: gdb_expect_seperator
+ *
+ * Description:
+ *   Check if the next byte in the packet is a seperator.
+ *
+ * Input Parameters:
+ *   state - The pointer to the GDB state structure.
+ *   c     - The expected seperator.
+ *
+ * Returned Value:
+ *   0 on success, -EINVAL on error.
+ *
+ ****************************************************************************/
+
+static int gdb_expect_seperator(FAR struct gdb_state_s *state, char c)
+{
+  if (!state->pkt_next || *state->pkt_next != c)
+    {
+      return -EINVAL;
+    }
+  else
+    {
+      state->pkt_next++;
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: gdb_expect_integer
+ *
+ * Description:
+ *   Parse an integer argument from the packet.
+ *
+ * Input Parameters:
+ *   state - The pointer to the GDB state structure.
+ *   arg   - The parsed integer argument.
+ *
+ * Returned Value:
+ *   0 on success
+ *
+ ****************************************************************************/
+
+static int gdb_expect_integer(FAR struct gdb_state_s *state,
+                              FAR uintptr_t *arg)
+{
+  size_t len = gdb_remaining_len(state);
+  char tmp = state->pkt_next[len];
+
+  state->pkt_next[len] = '\0';
+  *arg = strtoul(state->pkt_next, &state->pkt_next, 16);
+  state->pkt_next[len] = tmp;
+  return 0;
+}
+
+/****************************************************************************
+ * Name: gdb_expect_addr_lenth
+ *
+ * Description:
+ *   Parse an address and length argument from the packet.
+ *
+ * Input Parameters:
+ *   state - The pointer to the GDB state structure.
+ *   addr  - The parsed address.
+ *   length - The parsed length.
+ *
+ * Returned Value:
+ *   0 on success, -EINVAL on error.
+ *
+ ****************************************************************************/
+
+static int gdb_expect_addr_lenth(FAR struct gdb_state_s *state,
+                                 FAR uintptr_t *addr, FAR size_t *length)
+{
+  int ret;
+
+  ret = gdb_expect_integer(state, addr);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  ret = gdb_expect_seperator(state, ',');
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  return gdb_expect_integer(state, length);
+}
+
+/****************************************************************************
+ * Packet Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: gdb_putchar
+ *
+ * Description:
+ *   Put a character to the GDB server.
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *   ch      - The character to be sent.
+ *
+ * Returned Value:
+ *   The character sent to the GDB server.
+ *
+ ****************************************************************************/
+
+static int gdb_putchar(FAR struct gdb_state_s *state, int ch)
+{
+  unsigned char tmp = ch & 0xff;
+  ssize_t ret;
+
+  ret = state->send(state->priv, &tmp, 1);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  return tmp;
+}
+
+/****************************************************************************
+ * Name: gdb_getchar
+ *
+ * Description:
+ *  Get a character from the GDB server.
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *
+ * Returned Value:
+ *   The character read from the GDB server.
+ *
+ ****************************************************************************/
+
+static int gdb_getchar(FAR struct gdb_state_s *state)
+{
+  unsigned char tmp;
+  ssize_t ret;
+
+  ret = state->recv(state->priv, &tmp, 1);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  return tmp;
+}
+
+/****************************************************************************
+ * Name: gdb_send_packet
+ *
+ * Description:
+ *   Transmits a packet of data.
+ *   Packets are of the form: $<packet-data>#<checksum>
+ *
+ * Input Parameters:
+ *   state - The pointer to the GDB state structure.
+ *
+ * Returned Value:
+ *   0       if the packet was transmitted and acknowledged.
+ *   1       if the packet was transmitted but not acknowledged.
+ *   Negative value on error.
+ *
+ ****************************************************************************/
+
+static int gdb_send_packet(FAR struct gdb_state_s *state)
+{
+  unsigned char buf[3];
+  unsigned char csum;
+  int ret;
+
+  ret = gdb_putchar(state, '$'); /* Send packet start */
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+#ifdef CONFIG_LIB_GDBSTUB_DEBUG
+    {
+      size_t p;
+      GDB_DEBUG("-> ");
+      for (p = 0; p < state->pkt_len; p++)
+        {
+          if (isprint(state->pkt_buf[p]))
+            {
+              GDB_DEBUG("%c", state->pkt_buf[p]);
+            }
+          else
+            {
+              GDB_DEBUG("\\x%02x", state->pkt_buf[p] & 0xff);
+            }
+        }
+
+      GDB_DEBUG("\n");
+    }
+#endif
+
+  /* Send packet data */
+
+  ret = state->send(state->priv, state->pkt_buf, state->pkt_len);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* Send the checksum */
+
+  buf[0] = '#';
+  csum = gdb_checksum(state->pkt_buf, state->pkt_len);
+  ret = gdb_bin2hex(buf + 1, sizeof(buf) - 1, &csum, 1);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  ret = state->send(state->priv, buf, sizeof(buf));
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  return gdb_recv_ack(state);
+}
+
+/****************************************************************************
+ * Name: gdb_recv_packet
+ *
+ * Description:
+ *   Receives a packet of data, assuming a 7-bit clean connection.
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *
+ * Returned Value:
+ *   0          if the packet was received.
+ *   -EIO       if the packet was not received.
+ *   -EOVERFLOW if the packet was too long.
+ *   Negative value on error.
+ *
+ ****************************************************************************/
+
+static int gdb_recv_packet(FAR struct gdb_state_s *state)
+{
+  unsigned char buf[2];
+  unsigned char csum;
+  int ret;
+
+  /* Wait for packet start */
+
+  do
+    {
+      while (1)
+        {
+          ret = gdb_getchar(state);
+          if (ret < 0)
+            {
+              return ret;
+            }
+          else if (ret == '$')
+            {
+              /* Detected start of packet. */
+
+              break;
+            }
+        }
+
+      /* Read until checksum */
+
+      state->pkt_len = 0;
+      while (1)
+        {
+          ret = gdb_getchar(state);
+          if (ret < 0) /* Error receiving character */
+            {
+              return ret;
+            }
+          else if (ret == '#') /* End of packet */
+            {
+              break;
+            }
+          else /* Check for space */
+            {
+              if (state->pkt_len >= sizeof(state->pkt_buf))
+                {
+                  GDB_DEBUG("packet buffer overflow\n");
+                  return -EOVERFLOW;
+                }
+
+              /* Store character and update checksum */
+
+              state->pkt_buf[state->pkt_len++] = (char)ret;
+            }
+        }
+    }
+  while (state->pkt_len == 0); /* Ignore empty packets */
+
+#ifdef CONFIG_LIB_GDBSTUB_DEBUG
+    {
+      size_t p;
+      GDB_DEBUG("<- ");
+      for (p = 0; p < state->pkt_len; p++)
+        {
+          if (isprint(state->pkt_buf[p]))
+            {
+              GDB_DEBUG("%c", state->pkt_buf[p]);
+            }
+          else
+            {
+              GDB_DEBUG("\\x%02x", state->pkt_buf[p] & 0xff);
+            }
+        }
+
+      GDB_DEBUG("\n");
+    }
+#endif
+
+  ret = state->recv(state->priv, buf, 2); /* Receive the checksum */
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  ret = gdb_hex2bin(&csum, 1, buf, 2);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  if (csum != gdb_checksum(state->pkt_buf, state->pkt_len)) /* Verify */
+    {
+      GDB_DEBUG("received packet with bad checksum\n");
+      gdb_putchar(state, '-'); /* Send packet nack */
+      return -EIO;
+    }
+
+  gdb_putchar(state, '+'); /* Send packet ack */
+  state->pkt_next = state->pkt_buf;
+  return 0;
+}
+
+/****************************************************************************
+ * Name: gdb_checksum
+ *
+ * Description:
+ *   Calculate 8-bit checksum of a buffer.
+ *
+ * Input Parameters:
+ *   buf - The buffer to checksum.
+ *
+ * Returned Value:
+ *   8-bit checksum
+ *
+ ****************************************************************************/
+
+static int gdb_checksum(FAR const char *buf, size_t len)
+{
+  unsigned char csum = 0;
+
+  while (len--)
+    {
+      csum += *buf++;
+    }
+
+  return csum;
+}
+
+/****************************************************************************
+ * Name: gdb_recv_ack
+ *
+ * Description:
+ *   Receive a packet acknowledgment.
+ *
+ * Input Parameters:
+ *   state - The pointer to the GDB state structure.
+ *
+ * Returned Value:
+ *   0       if an ACK (+) was received
+ *   1       if a NACK (-) was received
+ *   -EINVAL if a bad response was received
+ *
+ ****************************************************************************/
+
+static int gdb_recv_ack(FAR struct gdb_state_s *state)
+{
+  int response;
+
+  switch (response = gdb_getchar(state)) /* Wait for packet ack */
+    {
+      case '+': /* Packet acknowledged */
+        return 0;
+      case '-': /* Packet negative acknowledged */
+        return 1;
+      default: /* Bad response! */
+        GDB_DEBUG("received bad packet response: 0x%2x\n", response);
+        return -EINVAL;
+    }
+}
+
+/****************************************************************************
+ * Data Encoding/Decoding
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: gdb_bin2hex
+ *
+ * Description:
+ *   Encode data to its hex-value representation in a buffer.
+ *
+ * Input Parameters:
+ *   buf      - The buffer to encode to.
+ *   buf_len  - The length of the buffer.
+ *   data     - The data to encode.
+ *   data_len - The length of the data to encode.
+ *
+ * Returned Value:
+ *    The number of bytes written to buf on success.
+ *    -EOVERFLOW if the buffer is too small.
+ *
+ ****************************************************************************/
+
+static ssize_t gdb_bin2hex(FAR void *buf, size_t buf_len,
+                           FAR const void *data, size_t data_len)
+{
+  FAR const char *in = data;
+  FAR char *out = buf;
+  size_t pos;
+
+  if (buf_len < data_len * 2)
+    {
+      return -EOVERFLOW; /* Buffer too small */
+    }
+
+  for (pos = 0; pos < data_len; pos++)
+    {
+      itoa(in[pos] >> 4 & 0xf, out++, 16);
+      itoa(in[pos] & 0xf, out++, 16);
+    }
+
+  return data_len * 2;
+}
+
+/****************************************************************************
+ * Name: gdb_hex2bin
+ *
+ * Description:
+ *   Decode data from its hex-value representation to a buffer.
+ *
+ * Input Parameters:
+ *   buf      - The buffer containing the encoded data.
+ *   buf_len  - The length of the buffer.
+ *   data     - The buffer to store the decoded data.
+ *   data_len - The length of the data to decode.
+ *
+ * Returned Value:
+ *   The number of bytes written to data on success.
+ *   -EOVERFLOW if the buffer is too small.
+ *   Negative value on error.
+ *
+ ****************************************************************************/
+
+static int gdb_hex2bin(FAR void *buf, size_t buf_len,
+                       FAR const void *data, size_t data_len)
+{
+  FAR const char *in = data;
+  FAR char *out = buf;
+  size_t pos;
+
+  if (buf_len * 2 < data_len)
+    {
+      return -EOVERFLOW; /* Buffer too small */
+    }
+
+  for (pos = 0; pos < data_len; pos += 2)
+    {
+      char ch[3] =
+        {
+          in[pos], in[pos + 1], 0
+        };
+
+      out[pos / 2] = strtoul(ch, NULL, 16); /* Decode high nibble */
+      if (out[pos / 2] == 0 && errno)
+        {
+          GDB_ASSERT();
+          return -errno; /* Buffer contained junk. */
+        }
+    }
+
+  return data_len / 2;
+}
+
+/****************************************************************************
+ * Name: gdb_bin2bin
+ *
+ * Description:
+ *   Decode data from its bin-value representation to a buffer.
+ *
+ * Input Parameters:
+ *   buf      - The buffer containing the encoded data.
+ *   buf_len  - The length of the buffer.
+ *   data     - The buffer to store the decoded data.
+ *   data_len - The length of the data to decode.
+ *
+ * Returned Value:
+ *     The number of bytes written to data on success.
+ *    -EOVERFLOW if the output buffer is too small.
+ *    -EINVAL if the input buffer is invalid.
+ *
+ ****************************************************************************/
+
+static ssize_t gdb_bin2bin(FAR void *buf, size_t buf_len,
+                           FAR const void *data, size_t data_len)
+{
+  FAR const char *in = data;
+  FAR char *out = buf;
+  size_t out_pos = 0;
+  size_t in_pos;
+
+  for (in_pos = 0; in_pos < data_len; in_pos++)
+    {
+      if (out_pos >= buf_len)
+        {
+          GDB_ASSERT();
+          return -EOVERFLOW; /* Output buffer overflow */
+        }
+
+      if (in[in_pos] == '}') /* The next byte is escaped! */
+        {
+          if (in_pos + 1 >= data_len)
+            {
+              /* There's an escape character, but no escaped character
+               * following the escape character.
+               */
+
+              GDB_ASSERT();
+              return -EINVAL;
+            }
+
+          in_pos++;
+          out[out_pos++] = in[in_pos] ^ 0x20;
+        }
+      else
+        {
+          out[out_pos++] = in[in_pos];
+        }
+    }
+
+  return out_pos;
+}
+
+/****************************************************************************
+ * Command Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: gdb_get_memory
+ *
+ * Description:
+ *  Get data from memory.
+ *
+ * Input Parameters:
+ *   state   - The state structure.
+ *   buf     - The buffer to store the encoded data.
+ *   buf_len - The length of the buffer.
+ *   addr    - The address to read from.
+ *   len     - The length of the data to read.
+ *   format  - The formatting function to use.
+ *
+ * Returned Value:
+ *   The number of bytes written to buf on success.
+ *   Negative value on error.
+ *
+ ****************************************************************************/
+
+static ssize_t gdb_get_memory(FAR struct gdb_state_s *state,
+                              FAR void *buf, size_t buf_len,
+                              uintptr_t addr, size_t len,
+                              gdb_format_func_t format)
+{
+  return format(buf, buf_len, (FAR const void *)addr, len);
+}
+
+/****************************************************************************
+ * Name: gdb_put_memory
+ *
+ * Description:
+ *   Put data from buf into memory.
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *   buf     - The buffer containing the encoded data.
+ *   buf_len - The length of the buffer.
+ *   addr    - The address to write to.
+ *   len     - The length of the data to write.
+ *   format  - The formatting function to use.
+ *
+ * Returned Value:
+ *   The number of bytes written to addr on success.
+ *   Negative value on error.
+ *
+ ****************************************************************************/
+
+static ssize_t gdb_put_memory(FAR struct gdb_state_s *state,
+                              FAR const void *buf, size_t buf_len,
+                              uintptr_t addr, size_t len,
+                              gdb_format_func_t format)
+{
+  return format((FAR void *)addr, len, buf, buf_len);
+}
+
+/****************************************************************************
+ * Packet Creation Helpers
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: gdb_send_ok_packet
+ *
+ * Description:
+ *   Send OK packet.
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *
+ * Returned Value:
+ *    Zero on success.
+ *    Negative value on error.
+ *
+ ****************************************************************************/
+
+static int gdb_send_ok_packet(FAR struct gdb_state_s *state)
+{
+  state->pkt_buf[0] = 'O';
+  state->pkt_buf[1] = 'K';
+  state->pkt_len = 2;
+
+  return gdb_send_packet(state);
+}
+
+/****************************************************************************
+ * Name: gdb_send_signal_packet
+ *
+ * Description:
+ *   Send a signal packet (S AA).
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *   signal  - The signal to send.
+ *
+ * Returned Value:
+ *   Zero on success.
+ *   Negative value on error.
+ *
+ ****************************************************************************/
+
+static int gdb_send_signal_packet(FAR struct gdb_state_s *state,
+                                  unsigned char signal)
+{
+  int ret;
+
+  state->pkt_buf[0] = 'S';
+  ret = gdb_bin2hex(&state->pkt_buf[1], sizeof(state->pkt_buf) - 1,
+                    &signal, 1);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  state->pkt_len = 1 + ret;
+  return gdb_send_packet(state);
+}
+
+/****************************************************************************
+ * Name: gdb_send_error_packet
+ *
+ * Description:
+ *   Send a error packet (E AA).
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *   error   - The error to send.
+ *
+ * Returned Value:
+ *   Zero on success.
+ *   Negative value on error.
+ *
+ ****************************************************************************/
+
+static int gdb_send_error_packet(FAR struct gdb_state_s *state,
+                                 unsigned char error)
+{
+  int ret;
+
+  state->pkt_buf[0] = 'E';
+  ret = gdb_bin2hex(&state->pkt_buf[1], sizeof(state->pkt_buf) - 1,
+                    &error, 1);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  state->pkt_len = 1 + ret;
+  return gdb_send_packet(state);
+}
+
+/****************************************************************************
+ * Communication Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: gdb_get_registers
+ *
+ * Description:
+ *   Get the registers of the specified task.
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ ****************************************************************************/
+
+static void gdb_get_registers(FAR struct gdb_state_s *state)
+{
+  FAR struct tcb_s *tcb = nxsched_get_tcb(state->pid);
+  FAR uint8_t *reg;
+  int i;
+
+  reg = (FAR uint8_t *)tcb->xcp.regs;
+  if (state->pid == getpid())
+    {
+      if (up_interrupt_context())
+        {
+          reg = (FAR uint8_t *)CURRENT_REGS;
+        }
+      else
+        {
+          up_saveusercontext(state->running_regs);
+          reg = state->running_regs;
+        }
+    }
+
+  for (i = 0; i < state->size / sizeof(uintptr_t); i++)
+    {
+      if (g_tcbinfo.reg_off.p[i] == UINT16_MAX)
+        {
+          state->registers[i] = 0;
+        }
+      else
+        {
+          state->registers[i] =
+            *(FAR uintptr_t *)(reg + g_tcbinfo.reg_off.p[i]);
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: gdb_read_registers
+ *
+ * Description:
+ *   Read Registers Command Format: g.
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *
+ * Returned Value:
+ *   Zero on success.
+ *   Negative value on error.
+ *
+ * Note: Comand Format: g.
+ *       Response Format: xxxxxxxxyyyyyyyyy...
+ ****************************************************************************/
+
+static int gdb_read_registers(FAR struct gdb_state_s *state)
+{
+  int ret;
+
+  gdb_get_registers(state);
+  ret = gdb_bin2hex(state->pkt_buf, sizeof(state->pkt_buf),
+                    state->registers, state->size);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  state->pkt_len = ret;
+  gdb_send_packet(state);
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: gdb_write_registers
+ *
+ * Description:
+ *   Write Registers Command Format: G XX...
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *
+ * Returned Value:
+ *   Zero on success.
+ *   Negative value on error.
+ *
+ *   Note: This function is not really change the register values.
+ *         Comand Format: Gxxxxxxxxyyyyyyyyy
+ *         Response Format: OK
+ ****************************************************************************/
+
+static int gdb_write_registers(FAR struct gdb_state_s *state)
+{
+  int ret;
+
+  ret = gdb_hex2bin(state->registers, sizeof(state->registers),
+                    state->pkt_buf + 1, state->pkt_len - 1);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  gdb_send_ok_packet(state);
+  return 0;
+}
+
+/****************************************************************************
+ * Name: gdb_write_register
+ *
+ * Description:
+ *   Write a Register Command Format: P n.
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *
+ * Returned Value:
+ *   Zero on success.
+ *   Negative value on error.
+ *
+ * Note: Comand Format: Pn.
+ *       Response Format: OK
+ ****************************************************************************/
+
+static int gdb_read_register(FAR struct gdb_state_s *state)
+{
+  uintptr_t addr;
+  int ret;
+
+  state->pkt_next++;
+  ret = gdb_expect_integer(state, &addr);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  gdb_get_registers(state);
+  if (addr >= state->size)
+    {
+      return 0;
+    }
+
+  ret = gdb_bin2hex(state->pkt_buf, sizeof(state->pkt_buf),
+                    &state->registers[addr], sizeof(state->registers[addr]));
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  state->pkt_len = ret;
+  gdb_send_packet(state);
+  return 0;
+}
+
+/****************************************************************************
+ * Name: gdb_read_memory
+ *
+ * Description:
+ *   Read Memory Command Format: m addr,length
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *
+ * Returned Value:
+ *   The number of bytes read if successful.
+ *   Negative value on error.
+ *
+ * Note: Comand Format: mAAAAAAAAA,LLLLLLLL
+ *       Response Format: XXXXXXXXYYYYYYYYY...
+ ****************************************************************************/
+
+static int gdb_read_memory(FAR struct gdb_state_s *state)
+{
+  uintptr_t addr;
+  size_t length;
+  int ret;
+
+  state->pkt_next++;
+  ret = gdb_expect_addr_lenth(state, &addr, &length);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  ret = gdb_get_memory(state, state->pkt_buf, sizeof(state->pkt_buf),
+                       addr, length, gdb_bin2hex);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  state->pkt_len = ret;
+  gdb_send_packet(state);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: gdb_write_memory
+ *
+ * Description:
+ *   Write Memory Command Format: M addr,length:XX..
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *
+ * Returned Value:
+ *   The number of bytes written if successful.
+ *   Negative value on error.
+ *
+ * Note : Comand Format: MAAAAAAAAA,LLLLLLLL:XXXXXXXXX...
+ *        Response Format: OK
+ ****************************************************************************/
+
+static int gdb_write_memory(FAR struct gdb_state_s *state)
+{
+  uintptr_t addr;
+  size_t length;
+  int ret;
+
+  state->pkt_next++;
+  ret = gdb_expect_addr_lenth(state, &addr, &length);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  ret = gdb_put_memory(state, state->pkt_next, gdb_remaining_len(state),
+                       addr, length, gdb_hex2bin);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  gdb_send_ok_packet(state);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: gdb_write_bin_memory
+ *
+ * Description:
+ *   Write Memory (Binary) Command Format: X addr,length:XX..
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *
+ * Returned Value:
+ *   The number of bytes written if successful.
+ *   Negative value on error.
+ *
+ * Note : Comand Format: XAAAAAAAAA,LLLLLLLL:XXXXXXXXX...
+ *        Response Format: OK
+ ****************************************************************************/
+
+static int gdb_write_bin_memory(FAR struct gdb_state_s *state)
+{
+  uintptr_t addr;
+  size_t length;
+  int ret;
+
+  state->pkt_next++;
+  ret = gdb_expect_addr_lenth(state, &addr, &length);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  ret = gdb_expect_seperator(state, ':');
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  ret = gdb_put_memory(state, state->pkt_next, gdb_remaining_len(state),
+                       addr, length, gdb_bin2bin);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  gdb_send_ok_packet(state);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: gdb_get_thread
+ *
+ * Description:
+ *   Get the all thread id.
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *
+ ****************************************************************************/
+
+static void gdb_get_thread(FAR struct tcb_s *tcb, FAR void *arg)
+{
+  FAR struct gdb_state_s *state = arg;
+  int pid = tcb->pid;
+  size_t len;
+
+  len = sprintf(&state->pkt_buf[state->pkt_len], "%x,", pid);
+  state->pkt_len += len;
+}
+
+/****************************************************************************
+ * Name: gdb_query
+ *
+ * Description:
+ *  The query packet is used by GDB to request information from the stub.
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *
+ * Returned Value:
+ *   0  if successful.
+ *   Negative value on error.
+ *
+ * Note : Comand Format: qSTRING
+ *        STRING:is the query string.
+ ****************************************************************************/
+
+static int gdb_query(FAR struct gdb_state_s *state)
+{
+  static const char thread_extra_info[] = "ThreadExtraInfo";
+  static const char fthread_info[] = "fThreadInfo";
+  static const char sthread_info[] = "sThreadInfo";
+  static const char r_cmd[] = "Rcmd";
+
+  if (memcmp(&state->pkt_buf[1], fthread_info,
+              sizeof(fthread_info) - 1) == 0)
+    {
+      state->pkt_buf[0] = 'm';
+      state->pkt_len = 1;
+      nxsched_foreach(gdb_get_thread, state);
+      state->pkt_len--;
+      state->pkt_buf[state->pkt_len] = 0;
+      gdb_send_packet(state);
+    }
+  else if (memcmp(&state->pkt_buf[1], sthread_info,
+                   sizeof(sthread_info) - 1) == 0)
+    {
+      state->pkt_buf[0] = 'l';
+      state->pkt_len = 1;
+      gdb_send_packet(state);
+    }
+  else if (memcmp(&state->pkt_buf[1], thread_extra_info,
+                   sizeof(thread_extra_info) - 1) == 0)
+    {
+      FAR struct tcb_s *tcb;
+      char thread_state[32];
+      char thread_info[128];
+      uintptr_t pid;
+      int ret;
+
+      state->pkt_next += sizeof(thread_extra_info) + 1;
+      ret = gdb_expect_integer(state, &pid);
+      if (ret < 0)
+        {
+          return ret;
+        }
+
+      tcb = nxsched_get_tcb(pid);
+      if (tcb == NULL)
+        {
+          return -EINVAL;
+        }
+
+      nxsched_get_stateinfo(tcb, thread_state, sizeof(thread_state));
+#if CONFIG_TASK_NAME_SIZE > 0
+      snprintf(thread_info, sizeof(thread_info),
+               "Name: %s, State: %s, Priority: %d, Stack: %d",
+                tcb->name, thread_state, tcb->sched_priority,
+                tcb->adj_stack_size);
+#else
+      snprintf(thread_info, sizeof(thread_info),
+               "State: %s, Priority: %d, Stack: %d",
+               thread_state, tcb->sched_priority,
+               tcb->adj_stack_size);
+#endif
+
+      ret = gdb_bin2hex(state->pkt_buf, sizeof(state->pkt_buf),
+                        thread_info, strlen(thread_info));
+
+      state->pkt_len = ret;
+      gdb_send_packet(state);
+    }
+  else if (state->monitor != NULL &&
+           memcmp(&state->pkt_buf[1], r_cmd, sizeof(r_cmd) - 1) == 0)
+    {
+      ssize_t len = state->pkt_len - sizeof(r_cmd) - 1; /* skip the 'Rcmd,' */
+      char cmd[128];
+      int ret;
+
+      len = gdb_hex2bin(cmd, len / 2,
+                        &state->pkt_buf[sizeof(r_cmd) + 1], len);
+      if (len < 0)
+        {
+          return len;
+        }
+
+      cmd[len] = '\0';
+      ret = state->monitor(state, cmd);
+      if (ret < 0)
+        {
+          return ret;
+        }
+      else
+        {
+          gdb_send_ok_packet(state);
+        }
+    }
+  else
+    {
+      return -EPROTONOSUPPORT;
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: gdb_is_thread_active
+ *
+ * Description:
+ *  The is thread active packet is used by GDB to request information from
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *
+ * Returned Value:
+ *   0  if successful.
+ *   Negative value on error.
+ *
+ * Note : Comand Format: T<id>
+ *        id:is the thread id.
+ *        Rsponse Format: OK
+ ****************************************************************************/
+
+static int gdb_is_thread_active(FAR struct gdb_state_s *state)
+{
+  FAR struct tcb_s *tcb;
+  uintptr_t pid;
+  int ret;
+
+  state->pkt_next++;
+  ret = gdb_expect_integer(state, &pid);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  tcb = nxsched_get_tcb(pid);
+  if (tcb == NULL)
+    {
+      return -EINVAL;
+    }
+
+  state->pid = pid;
+  gdb_send_ok_packet(state);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: gdb_thread_context
+ *
+ * Description:
+ *  The thread context packet is used by GDB to request information from
+ *  the stub.
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *
+ * Returned Value:
+ *   0  if successful.
+ *   Negative value on error.
+ *
+ * Note : Comand Format: Hc<id>
+ *        Rsponse Format: OK
+ ****************************************************************************/
+
+static int gdb_thread_context(FAR struct gdb_state_s *state)
+{
+  FAR struct tcb_s *tcb;
+  uintptr_t pid;
+  int ret;
+
+  state->pkt_next += 2;
+  ret = gdb_expect_integer(state, &pid);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  tcb = nxsched_get_tcb(pid);
+  if (tcb == NULL)
+    {
+      return -EINVAL;
+    }
+
+  state->pid = pid;
+  gdb_send_ok_packet(state);
+  return 0;
+}
+
+/****************************************************************************
+ * Name: gdb_send_stop
+ *
+ * Description:
+ *  The stop packet is used by GDB to request information from the stub.
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *
+ * Returned Value:
+ *   0  if successful.
+ *   Negative value on error.
+ *
+ ****************************************************************************/
+
+static int gdb_send_stop(FAR struct gdb_state_s *state)
+{
+  return gdb_send_signal_packet(state, 0x00);
+}
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+extern const struct tcbinfo_s g_tcbinfo;
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: gdb_state_init
+ *
+ * Description:
+ *   Initialize the GDB state structure.
+ *
+ * Input Parameters:
+ *   send    - The pointer to the send function.
+ *   recv    - The pointer to the receive function.
+ *   monitor - The pointer to the monitor_cmd function.
+ *   priv    - The pointer to the private data.
+ *
+ * Returned Value:
+ *   The pointer to the GDB state structure on success.
+ *   NULL on failure.
+ *
+ ****************************************************************************/
+
+FAR struct gdb_state_s *gdb_state_init(gdb_send_func_t send,
+                                       gdb_recv_func_t recv,
+                                       gdb_monitor_func_t monitor,
+                                       FAR void *priv)
+{
+  size_t size = g_tcbinfo.basic_num * sizeof(uintptr_t);
+  FAR struct gdb_state_s *state = lib_zalloc(sizeof(*state) + size);
+
+  if (state == NULL)
+    {
+      return NULL;
+    }
+
+  state->size = size;
+  state->send = send;
+  state->recv = recv;
+  state->priv = priv;
+  state->monitor = monitor;
+
+  return state;
+}
+
+/****************************************************************************
+ * Name: gdb_state_uninit
+ *
+ * Description:
+ *   Uninitialize the GDB state structure.
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *
+ ****************************************************************************/
+
+void gdb_state_uninit(FAR struct gdb_state_s *state)
+{
+  if (state != NULL)
+    {
+      lib_free(state);
+    }
+}
+
+/****************************************************************************
+ * Name: gdb_console_message
+ *
+ * Description:
+ *   Send a message to the GDB console (via O XX... packet).
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *
+ * Returned Value:
+ *    Zero on success.
+ *    Negative value on error.
+ *
+ ****************************************************************************/
+
+int gdb_console_message(FAR struct gdb_state_s *state, FAR const char *msg)
+{
+  ssize_t ret;
+
+  if (state == NULL || msg == NULL)
+    {
+      return -EINVAL;
+    }
+
+  state->pkt_buf[0] = 'O';
+  ret = gdb_bin2hex(&state->pkt_buf[1], sizeof(state->pkt_buf) - 1,
+                    msg, strlen(msg));
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  state->pkt_len = 1 + ret;
+  return gdb_send_packet(state);
+}
+
+/****************************************************************************
+ * Name: gdb_process
+ *
+ * Description:
+ *   Main debug loop. Handles commands.
+ *
+ * Input Parameters:
+ *   state   - The pointer to the GDB state structure.
+ *
+ * Returned Value:
+ *   Zero if successful.
+ *   Negative value on error.
+ *
+ ****************************************************************************/
+
+int gdb_process(FAR struct gdb_state_s *state)
+{
+  int ret;
+
+  while ((ret = gdb_recv_packet(state)) >= 0)
+    {
+      /* Handle one letter commands */
+
+      switch (state->pkt_buf[0])
+        {
+          case '?': /* gdbserial status */
+            ret = gdb_send_stop(state);
+            break;
+          case 'g': /* Read registers */
+            ret = gdb_read_registers(state);
+            break;
+          case 'G': /* Write registers */
+            ret = gdb_write_registers(state);
+            break;
+          case 'p': /* Read one register */
+            ret = gdb_read_register(state);
+            break;
+          case 'm': /* Read memory */
+            ret = gdb_read_memory(state);
+            break;
+          case 'M': /* Write memory */
+            ret = gdb_write_memory(state);
+            break;
+          case 'X': /* Write binary memory */
+            ret = gdb_write_bin_memory(state);
+            break;
+          case 'q': /* Query command */
+            ret = gdb_query(state);
+            break;
+          case 'T': /* Query thread */
+            ret = gdb_is_thread_active(state);
+            break;
+          case 'H': /* Thread related */
+            ret = gdb_thread_context(state);
+            break;
+          case 'k': /* Kill request */
+            ret = -ECONNRESET;
+            break;
+          default:
+            ret = -EPROTONOSUPPORT;
+      }
+
+      if (ret == -EPROTONOSUPPORT)
+        {
+          state->pkt_len = 0;
+          gdb_send_packet(state);
+        }
+      else if (ret == -ECONNRESET)
+        {
+          break;
+        }
+      else if (ret < 0)
+        {
+          gdb_send_error_packet(state, 0x00);
+        }
+    }
+
+  return ret;
+}


[nuttx] 02/02: support esp32c3-devkit gdbstub use wifi

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 6c1a7c426565b2569dca65a6577dc8cefded3ea8
Author: anjiahao <an...@xiaomi.com>
AuthorDate: Thu Jul 13 12:22:06 2023 +0800

    support esp32c3-devkit gdbstub use wifi
    
    Signed-off-by: anjiahao <an...@xiaomi.com>
---
 .../esp32c3-devkit/configs/gdbstub/defconfig       | 82 ++++++++++++++++++++++
 1 file changed, 82 insertions(+)

diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/configs/gdbstub/defconfig b/boards/risc-v/esp32c3/esp32c3-devkit/configs/gdbstub/defconfig
new file mode 100644
index 0000000000..fadbbc1ea0
--- /dev/null
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/configs/gdbstub/defconfig
@@ -0,0 +1,82 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+# CONFIG_NSH_ARGCAT is not set
+# CONFIG_NSH_CMDOPT_HEXDUMP is not set
+CONFIG_ALLOW_BSD_COMPONENTS=y
+CONFIG_ARCH="risc-v"
+CONFIG_ARCH_BOARD="esp32c3-devkit"
+CONFIG_ARCH_BOARD_COMMON=y
+CONFIG_ARCH_BOARD_ESP32C3_DEVKIT=y
+CONFIG_ARCH_CHIP="esp32c3"
+CONFIG_ARCH_CHIP_ESP32C3=y
+CONFIG_ARCH_CHIP_ESP32C3WROOM02=y
+CONFIG_ARCH_FLOAT_H=y
+CONFIG_ARCH_INTERRUPTSTACK=1536
+CONFIG_ARCH_RISCV=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_BOARD_LOOPSPERMSEC=16717
+CONFIG_BUILTIN=y
+CONFIG_DEBUG_FULLOPT=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DEBUG_TCBINFO=y
+CONFIG_DRIVERS_IEEE80211=y
+CONFIG_DRIVERS_WIRELESS=y
+CONFIG_ESP32C3_SPIFLASH=y
+CONFIG_ESP32C3_SPIFLASH_SPIFFS=y
+CONFIG_ESP32C3_WIFI=y
+CONFIG_FS_PROCFS=y
+CONFIG_HAVE_CXX=y
+CONFIG_HAVE_CXXINITIALIZE=y
+CONFIG_IDLETHREAD_STACKSIZE=3072
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INTELHEX_BINARY=y
+CONFIG_IOB_NBUFFERS=124
+CONFIG_IOB_THROTTLE=24
+CONFIG_LIBC_MAX_EXITFUNS=1
+CONFIG_LIB_GDBSTUB=y
+CONFIG_NAME_MAX=48
+CONFIG_NETDB_DNSCLIENT=y
+CONFIG_NETDEV_LATEINIT=y
+CONFIG_NETDEV_PHY_IOCTL=y
+CONFIG_NETDEV_WIRELESS_IOCTL=y
+CONFIG_NETUTILS_CJSON=y
+CONFIG_NETUTILS_IPERF=y
+CONFIG_NET_BROADCAST=y
+CONFIG_NET_ETH_PKTSIZE=1514
+CONFIG_NET_ICMP=y
+CONFIG_NET_ICMP_SOCKET=y
+CONFIG_NET_TCP=y
+CONFIG_NET_TCP_DELAYED_ACK=y
+CONFIG_NET_TCP_WRITE_BUFFERS=y
+CONFIG_NET_UDP=y
+CONFIG_NET_UDP_WRITE_BUFFERS=y
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_LINELEN=64
+CONFIG_NSH_READLINE=y
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_PTHREAD_MUTEX_TYPES=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_LPWORK=y
+CONFIG_SCHED_WAITPID=y
+CONFIG_SIG_DEFAULT=y
+CONFIG_START_DAY=6
+CONFIG_START_MONTH=12
+CONFIG_START_YEAR=2011
+CONFIG_SYSTEM_DHCPC_RENEW=y
+CONFIG_SYSTEM_GDBSTUB=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_SYSTEM_PING=y
+CONFIG_TLS_TASK_NELEM=4
+CONFIG_UART0_SERIAL_CONSOLE=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_WAPI=y
+CONFIG_WIRELESS_WAPI_CMDTOOL=y
+CONFIG_WIRELESS_WAPI_INITCONF=y
+CONFIG_WIRELESS_WAPI_STACKSIZE=4096