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/12/11 16:43:34 UTC

(nuttx) 01/04: arch/arm:add up_debugpoint api

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 bb0a706bdcd70f9c5624c35163291a185f5893c7
Author: anjiahao <an...@xiaomi.com>
AuthorDate: Wed Sep 6 20:25:56 2023 +0800

    arch/arm:add up_debugpoint api
    
    on armv8-m/armv7-m,implement breakpoint & watchpoint using FBP & DWT
    
    Signed-off-by: anjiahao <an...@xiaomi.com>
---
 arch/Kconfig                               |   4 +
 arch/arm/Kconfig                           |   2 +
 arch/arm/src/armv7-m/CMakeLists.txt        |   1 +
 arch/arm/src/armv7-m/Make.defs             |   2 +-
 arch/arm/src/armv7-m/arm_dbgmonitor.c      | 673 +++++++++++++++++++++++++++
 arch/arm/src/armv7-m/fpb.h                 |  11 +
 arch/arm/src/armv7-m/nvic.h                |   8 +
 arch/arm/src/armv8-m/CMakeLists.txt        |   1 +
 arch/arm/src/armv8-m/Make.defs             |   2 +-
 arch/arm/src/armv8-m/arm_dbgmonitor.c      | 700 +++++++++++++++++++++++++++++
 arch/arm/src/armv8-m/dwt.h                 |   9 +-
 arch/arm/src/armv8-m/fpb.h                 |  11 +
 arch/arm/src/armv8-m/nvic.h                |   8 +
 arch/arm/src/common/arm_internal.h         |   2 +
 arch/arm/src/cxd56xx/cxd56_irq.c           |  14 +-
 arch/arm/src/efm32/efm32_irq.c             |  14 +-
 arch/arm/src/eoss3/eoss3_irq.c             |  14 +-
 arch/arm/src/gd32f4/gd32f4xx_irq.c         |  14 +-
 arch/arm/src/imxrt/imxrt_irq.c             |  14 +-
 arch/arm/src/kinetis/kinetis_irq.c         |  14 +-
 arch/arm/src/lc823450/lc823450_irq.c       |  14 +-
 arch/arm/src/lpc17xx_40xx/lpc17_40_irq.c   |  14 +-
 arch/arm/src/lpc43xx/lpc43_irq.c           |  14 +-
 arch/arm/src/lpc54xx/lpc54_irq.c           |  14 +-
 arch/arm/src/max326xx/common/max326_irq.c  |  14 +-
 arch/arm/src/nrf52/nrf52_irq.c             |  14 +-
 arch/arm/src/nrf53/nrf53_irq.c             |  14 +-
 arch/arm/src/s32k1xx/s32k14x/s32k14x_irq.c |  14 +-
 arch/arm/src/s32k3xx/s32k3xx_irq.c         |  14 +-
 arch/arm/src/sam34/sam_irq.c               |  14 +-
 arch/arm/src/samd5e5/sam_irq.c             |  14 +-
 arch/arm/src/samv7/sam_irq.c               |  14 +-
 arch/arm/src/stm32/stm32_irq.c             |  14 +-
 arch/arm/src/stm32f7/stm32_irq.c           |  14 +-
 arch/arm/src/stm32h7/stm32_irq.c           |  14 +-
 arch/arm/src/stm32l4/stm32l4_irq.c         |  14 +-
 arch/arm/src/stm32l5/stm32l5_irq.c         |  14 +-
 arch/arm/src/stm32u5/stm32_irq.c           |  14 +-
 arch/arm/src/stm32wb/stm32wb_irq.c         |  14 +-
 arch/arm/src/stm32wl5/stm32wl5_irq.c       |  14 +-
 arch/arm/src/tiva/common/tiva_irq.c        |  14 +-
 arch/arm/src/xmc4/xmc4_irq.c               |  14 +-
 include/nuttx/arch.h                       |  63 +++
 43 files changed, 1578 insertions(+), 311 deletions(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index deccaf4007..da974c6071 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -506,6 +506,10 @@ config ARCH_HAVE_BACKTRACE
 	bool
 	default n
 
+config ARCH_HAVE_DEBUG
+	bool "Architecture have debug support"
+	default n
+
 config ARCH_HAVE_PERF_EVENTS
 	bool
 	default n
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 750caf44a4..dea4e3904d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -790,6 +790,7 @@ config ARCH_ARMV7M
 	bool
 	default n
 	select ARCH_HAVE_CPUINFO
+	select ARCH_HAVE_DEBUG
 	select ARCH_HAVE_PERF_EVENTS
 
 config ARCH_CORTEXM3
@@ -929,6 +930,7 @@ config ARCH_ARMV8M
 	bool
 	default n
 	select ARCH_HAVE_CPUINFO
+	select ARCH_HAVE_DEBUG
 	select ARCH_HAVE_PERF_EVENTS
 
 config ARCH_CORTEXM23
diff --git a/arch/arm/src/armv7-m/CMakeLists.txt b/arch/arm/src/armv7-m/CMakeLists.txt
index 95ed96d88e..49be110409 100644
--- a/arch/arm/src/armv7-m/CMakeLists.txt
+++ b/arch/arm/src/armv7-m/CMakeLists.txt
@@ -24,6 +24,7 @@ set(SRCS
     arm_exception.S
     arm_saveusercontext.S
     arm_busfault.c
+    arm_dbgmonitor.c
     arm_cache.c
     arm_cpuinfo.c
     arm_doirq.c
diff --git a/arch/arm/src/armv7-m/Make.defs b/arch/arm/src/armv7-m/Make.defs
index 2cdb688b89..c8fb3766e3 100644
--- a/arch/arm/src/armv7-m/Make.defs
+++ b/arch/arm/src/armv7-m/Make.defs
@@ -29,7 +29,7 @@ CMN_CSRCS += arm_hardfault.c arm_initialstate.c arm_itm.c
 CMN_CSRCS += arm_memfault.c arm_perf.c
 CMN_CSRCS += arm_schedulesigaction.c arm_sigdeliver.c
 CMN_CSRCS += arm_svcall.c arm_systemreset.c arm_tcbinfo.c
-CMN_CSRCS += arm_trigger_irq.c arm_usagefault.c arm_vectors.c
+CMN_CSRCS += arm_trigger_irq.c arm_usagefault.c arm_vectors.c arm_dbgmonitor.c
 
 ifeq ($(CONFIG_ARMV7M_SYSTICK),y)
   CMN_CSRCS += arm_systick.c
diff --git a/arch/arm/src/armv7-m/arm_dbgmonitor.c b/arch/arm/src/armv7-m/arm_dbgmonitor.c
new file mode 100644
index 0000000000..dad81182db
--- /dev/null
+++ b/arch/arm/src/armv7-m/arm_dbgmonitor.c
@@ -0,0 +1,673 @@
+/****************************************************************************
+ * arch/arm/src/armv7-m/arm_dbgmonitor.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 <nuttx/config.h>
+#include <nuttx/arch.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <arch/irq.h>
+
+#include "nvic.h"
+#include "fpb.h"
+#include "dwt.h"
+#include "arm_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* 4 watchpoint, 4 breakpoint, 1 single step */
+
+#define ARM_DEBUG_MAX (4 + 4 + 1)
+
+#define ARM_FPB_NUM() \
+        (((getreg32(FPB_CTRL) & FPB_CTRL_NUM_CODE2_MASK) >> \
+          FPB_CTRL_NUM_CODE2_SHIFT << FPB_CTRL_NUM_CODE1_SHIFT) | \
+         ((getreg32(FPB_CTRL) & FPB_CTRL_NUM_CODE1_MASK) >> \
+          FPB_CTRL_NUM_CODE1_SHIFT))
+
+#define ARM_FPB_REVISION() \
+        ((getreg32(FPB_CTRL) & FPB_CTRL_REV_MASK) >> FPB_CTRL_REV_SHIFT)
+
+#define ARM_DWT_NUM() \
+        ((getreg32(DWT_CTRL) & DWT_CTRL_NUMCOMP_MASK) >> \
+         DWT_CTRL_NUMCOMP_SHIFT)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct arm_debug_s
+{
+  int type;
+  void *addr;
+  size_t size;
+  debug_callback_t callback;
+  void *arg;
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct arm_debug_s g_arm_debug[ARM_DEBUG_MAX];
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: arm_fpb_init
+ ****************************************************************************/
+
+static void arm_fpb_init(void)
+{
+  uint32_t num = ARM_FPB_NUM();
+  uint32_t i;
+
+  for (i = 0; i < num; i++)
+    {
+      putreg32(0, FPB_COMP0 + i * 4);
+    }
+
+  modifyreg32(FPB_CTRL, 0, FPB_CTRL_ENABLE_MASK | FPB_CTRL_KEY_MASK);
+}
+
+/****************************************************************************
+ * Name: arm_dwt_init
+ ****************************************************************************/
+
+static void arm_dwt_init(void)
+{
+  uint32_t num = ARM_DWT_NUM();
+  uint32_t i;
+
+  for (i = 0; i < num; i++)
+    {
+      putreg32(0, DWT_COMP0 + 16 * i);
+      putreg32(0, DWT_MASK0 + 16 * i);
+      putreg32(0, DWT_FUNCTION0 + 16 * i);
+    }
+}
+
+/****************************************************************************
+ * Name: up_watchpoint_add
+ *
+ * Description:
+ *   Add a watchpoint on the address.
+ *
+ * Input Parameters:
+ *  type - The type of the watchpoint
+ *  addr - The address to be watched
+ *  size - The size of the address to be watched
+ *
+ * Returned Value:
+ *  Zero on success; a negated errno value on failure
+ *
+ * Notes:
+ *  The size of the watchpoint is determined by the hardware.
+ *  armv7-m supports only support 4 bytes.
+ *
+ ****************************************************************************/
+
+static int arm_watchpoint_add(int type, uint32_t addr, size_t size)
+{
+  uint32_t num = ARM_DWT_NUM();
+  uint32_t i;
+
+  for (i = 0; i < num; i++)
+    {
+      uint32_t fun;
+
+      if (getreg32(DWT_COMP0 + 16 * i) == 0)
+        {
+          switch (type)
+            {
+              case DEBUGPOINT_WATCHPOINT_RO:
+                fun = DWT_FUNCTION_WATCHPOINT_RO;
+                break;
+              case DEBUGPOINT_WATCHPOINT_WO:
+                fun = DWT_FUNCTION_WATCHPOINT_WO;
+                break;
+              case DEBUGPOINT_WATCHPOINT_RW:
+                fun = DWT_FUNCTION_WATCHPOINT_RW;
+                break;
+              default:
+                return -EINVAL;
+            }
+
+          putreg32(fun, DWT_FUNCTION0 + 16 * i);
+          putreg32(addr, DWT_COMP0 + 16 * i);
+          putreg32(0, DWT_MASK0 + 16 * i);
+          return 0;
+        }
+    }
+
+  return -ENOSPC;
+}
+
+/****************************************************************************
+ * Name: arm_watchpoint_remove
+ *
+ * Description:
+ *   Remove a watchpoint on the address.
+ *
+ * Input Parameters:
+ *   type - The type of the watchpoint.
+ *   addr - The address to be watched.
+ *   size - The size of the address to be watched.
+ *
+ * Returned Value:
+ *  Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int arm_watchpoint_remove(int type, uint32_t addr, size_t size)
+{
+  uint32_t num = ARM_DWT_NUM();
+  uint32_t i;
+
+  for (i = 0; i < num; i++)
+    {
+      uint32_t fun_type = (getreg32(DWT_FUNCTION0 + 16 * i) &
+                          DWT_FUNCTION_FUNCTION_MASK) >>
+                          DWT_FUNCTION_FUNCTION_SHIFT;
+
+      switch (fun_type)
+        {
+          case DWT_FUNCTION_WATCHPOINT_RO:
+            if (type == DEBUGPOINT_WATCHPOINT_RO)
+              {
+                break;
+              }
+
+            continue;
+          case DWT_FUNCTION_WATCHPOINT_WO:
+            if (type == DEBUGPOINT_WATCHPOINT_WO)
+              {
+                break;
+              }
+
+            continue;
+          case DWT_FUNCTION_WATCHPOINT_RW:
+            if (type == DEBUGPOINT_WATCHPOINT_RW)
+              {
+                break;
+              }
+
+            continue;
+
+          default:
+            continue;
+        }
+
+      if (getreg32(DWT_COMP0 + 16 * i) != addr)
+        {
+          continue;
+        }
+
+      putreg32(0, DWT_COMP0 + 16 * i);
+      putreg32(0, DWT_FUNCTION0 + 16 * i);
+      putreg32(0, DWT_MASK0 + 16 * i);
+      return 0;
+    }
+
+  return -EINVAL;
+}
+
+/****************************************************************************
+ * Name: arm_watchpoint_match
+ *
+ * Description:
+ *   This function will be called when watchpoint match.
+ *
+ ****************************************************************************/
+
+static void arm_watchpoint_match(void)
+{
+  uint32_t num = ARM_DWT_NUM();
+  uint32_t addr = 0;
+  uint32_t i;
+  int type = 0;
+
+  for (i = 0; i < num; i++)
+    {
+      uint32_t fun = getreg32(DWT_FUNCTION0 + 16 * i);
+      if ((fun & DWT_FUNCTION_MATCHED_MASK) != 0)
+        {
+          uint32_t fun_type = (fun & DWT_FUNCTION_FUNCTION_MASK) >>
+                              DWT_FUNCTION_FUNCTION_SHIFT;
+
+          addr = getreg32(DWT_COMP0 + 16 * i);
+          switch (fun_type)
+            {
+              case DWT_FUNCTION_WATCHPOINT_RO:
+                type = DEBUGPOINT_WATCHPOINT_RO;
+                break;
+              case DWT_FUNCTION_WATCHPOINT_WO:
+                type = DEBUGPOINT_WATCHPOINT_WO;
+                break;
+              case DWT_FUNCTION_WATCHPOINT_RW:
+                type = DEBUGPOINT_WATCHPOINT_RW;
+                break;
+
+              default:
+                continue;
+            }
+        }
+    }
+
+  for (i = 0; i < ARM_DEBUG_MAX; i++)
+    {
+      if (g_arm_debug[i].addr == (void *)addr &&
+          g_arm_debug[i].type == type && g_arm_debug[i].callback)
+        {
+          g_arm_debug[i].callback(g_arm_debug[i].type,
+                                  g_arm_debug[i].addr,
+                                  g_arm_debug[i].size,
+                                  g_arm_debug[i].arg);
+          break;
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: arm_breakpoint_add
+ *
+ * Description:
+ *   Add a breakpoint on addr.
+ *
+ * Input Parameters:
+ *  addr - The address to break.
+ *
+ * Returned Value:
+ *  Zero on success; a negated errno value on failure
+ *
+ * Notes:
+ *  1. If breakpoint is already set, it will do nothing.
+ *  2. If all comparators are in use, it will return -1.
+ *  3. When the breakpoint trigger, if enable monitor exception already ,
+ *     will cause a debug monitor exception, otherwise will cause
+ *     a hard fault.
+ *
+ ****************************************************************************/
+
+static int arm_breakpoint_add(uintptr_t addr)
+{
+  uint32_t revision = ARM_FPB_REVISION();
+  uint32_t num = ARM_FPB_NUM();
+  uint32_t fpb_comp;
+  uint32_t replace;
+  uint32_t comp;
+  uint32_t i;
+
+  if (revision == 0)
+    {
+      replace = (addr & 0x2) == 0 ? 1 : 2;
+      fpb_comp = (addr & ~0x3) | FPB_COMP0_ENABLE_MASK |
+                 (replace << FPB_COMP0_REPLACE_SHIFT);
+    }
+  else
+    {
+      fpb_comp = addr | FPB_COMP0_ENABLE_MASK;
+    }
+
+  for (i = 0; i < num; i++)
+    {
+      comp = getreg32(FPB_COMP0 + i * 4);
+
+      if (comp == fpb_comp) /* Already set */
+        {
+          return 0;
+        }
+      else if (comp & FPB_COMP0_ENABLE_MASK) /* Comparators is in use */
+        {
+          continue;
+        }
+      else /* Find a free comparators */
+        {
+          putreg32(fpb_comp, FPB_COMP0 + i * 4);
+          return 0;
+        }
+    }
+
+  return -ENOSPC;
+}
+
+/****************************************************************************
+ * Name: arm_breakpoint_remove
+ *
+ * Description:
+ *   Remove a breakpoint on addr.
+ *
+ * Input Parameters:
+ *  addr - The address to remove.
+ *
+ * Returned Value:
+ *  Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int arm_breakpoint_remove(uintptr_t addr)
+{
+  uint32_t revision = ARM_FPB_REVISION();
+  uint32_t num = ARM_FPB_NUM();
+  uint32_t fpb_comp;
+  uint32_t replace;
+  uint32_t i;
+
+  if (revision == 0)
+    {
+      replace = (addr & 0x2) == 0 ? 1 : 2;
+      fpb_comp = (addr & ~0x3) | FPB_COMP0_ENABLE_MASK |
+                 (replace << FPB_COMP0_REPLACE_SHIFT);
+    }
+  else
+    {
+      fpb_comp = addr | FPB_COMP0_ENABLE_MASK;
+    }
+
+  for (i = 0; i < num; i++)
+    {
+      if (fpb_comp == getreg32(FPB_COMP0 + i * 4))
+        {
+          putreg32(0, FPB_COMP0 + i * 4);
+          return 0;
+        }
+    }
+
+  return -EINVAL;
+}
+
+/****************************************************************************
+ * Name: arm_breakpoint_match
+ *
+ * Description:
+ *   This function will be called when breakpoint match.
+ *
+ ****************************************************************************/
+
+static void arm_breakpoint_match(uint32_t pc)
+{
+  uint32_t i;
+
+  for (i = 0; i < ARM_DEBUG_MAX; i++)
+    {
+      if (g_arm_debug[i].type == DEBUGPOINT_BREAKPOINT &&
+          g_arm_debug[i].addr == (void *)pc &&
+          g_arm_debug[i].callback != NULL)
+        {
+          g_arm_debug[i].callback(g_arm_debug[i].type,
+                                  g_arm_debug[i].addr,
+                                  g_arm_debug[i].size,
+                                  g_arm_debug[i].arg);
+          break;
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: arm_steppoint
+ *
+ * Description:
+ *   Enable/disable single step.
+ *
+ * Input Parameters:
+ *  enable - True: enable single step; False: disable single step.
+ *
+ * Returned Value:
+ *  Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int arm_steppoint(bool enable)
+{
+  if (enable)
+    {
+      modifyreg32(NVIC_DEMCR, 0, NVIC_DEMCR_MONSTEP);
+    }
+  else
+    {
+      modifyreg32(NVIC_DEMCR, NVIC_DEMCR_MONSTEP, 0);
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: arm_steppoint_match
+ *
+ * Description:
+ *   This function will be called when single step match.
+ *
+ ****************************************************************************/
+
+static void arm_steppoint_match(void)
+{
+  uint32_t i;
+
+  for (i = 0; i < ARM_DEBUG_MAX; i++)
+    {
+      if (g_arm_debug[i].type == DEBUGPOINT_STEPPOINT &&
+          g_arm_debug[i].callback != NULL)
+        {
+          g_arm_debug[i].callback(g_arm_debug[i].type,
+                                  g_arm_debug[i].addr,
+                                  g_arm_debug[i].size,
+                                  g_arm_debug[i].arg);
+          break;
+        }
+    }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_debugpoint_add
+ *
+ * Description:
+ *   Add a debugpoint.
+ *
+ * Input Parameters:
+ *   type     - The debugpoint type. optional value:
+ *              DEBUGPOINT_WATCHPOINT_RO - Read only watchpoint.
+ *              DEBUGPOINT_WATCHPOINT_WO - Write only watchpoint.
+ *              DEBUGPOINT_WATCHPOINT_RW - Read and write watchpoint.
+ *              DEBUGPOINT_BREAKPOINT    - Breakpoint.
+ *              DEBUGPOINT_STEPPOINT     - Single step.
+ *   addr     - The address to be debugged.
+ *   size     - The watchpoint size. only for watchpoint.
+ *   callback - The callback function when debugpoint triggered.
+ *              if NULL, the debugpoint will be removed.
+ *   arg      - The argument of callback function.
+ *
+ * Returned Value:
+ *  Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+int up_debugpoint_add(int type, void *addr, size_t size,
+                      debug_callback_t callback, void *arg)
+{
+  int ret = -EINVAL;
+  uint32_t i;
+
+  if (type == DEBUGPOINT_BREAKPOINT)
+    {
+      ret = arm_breakpoint_add((uintptr_t)addr);
+
+      /* Thumb mode breakpoint address must be word-aligned */
+
+      addr = (void *)((uintptr_t)addr & ~0x1);
+    }
+  else if (type == DEBUGPOINT_WATCHPOINT_RO ||
+           type == DEBUGPOINT_WATCHPOINT_WO ||
+           type == DEBUGPOINT_WATCHPOINT_RW)
+    {
+      ret = arm_watchpoint_add(type, (uintptr_t)addr, size);
+    }
+  else if (type == DEBUGPOINT_STEPPOINT)
+    {
+      ret = arm_steppoint(true);
+    }
+
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  for (i = 0; i < ARM_DEBUG_MAX; i++)
+    {
+      if (g_arm_debug[i].type == DEBUGPOINT_NONE)
+        {
+          g_arm_debug[i].type = type;
+          g_arm_debug[i].addr = addr;
+          g_arm_debug[i].size = size;
+          g_arm_debug[i].callback = callback;
+          g_arm_debug[i].arg = arg;
+          break;
+        }
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: up_debugpoint_remove
+ *
+ * Description:
+ *   Remove a debugpoint.
+ *
+ * Input Parameters:
+ *   type     - The debugpoint type. optional value:
+ *              DEBUGPOINT_WATCHPOINT_RO - Read only watchpoint.
+ *              DEBUGPOINT_WATCHPOINT_WO - Write only watchpoint.
+ *              DEBUGPOINT_WATCHPOINT_RW - Read and write watchpoint.
+ *              DEBUGPOINT_BREAKPOINT    - Breakpoint.
+ *              DEBUGPOINT_STEPPOINT     - Single step.
+ *   addr     - The address to be debugged.
+ *   size     - The watchpoint size. only for watchpoint.
+ *
+ * Returned Value:
+ *  Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+int up_debugpoint_remove(int type, void *addr, size_t size)
+{
+  int ret = -EINVAL;
+  uint32_t i;
+
+  if (type == DEBUGPOINT_BREAKPOINT)
+    {
+      ret = arm_breakpoint_remove((uintptr_t)addr);
+
+      /* Thumb mode breakpoint address must be word-aligned */
+
+      addr = (void *)((uintptr_t)addr & ~0x1);
+    }
+  else if (type == DEBUGPOINT_WATCHPOINT_RO ||
+           type == DEBUGPOINT_WATCHPOINT_WO ||
+           type == DEBUGPOINT_WATCHPOINT_RW)
+    {
+      ret = arm_watchpoint_remove(type, (uintptr_t)addr, size);
+    }
+  else if (type == DEBUGPOINT_STEPPOINT)
+    {
+      ret = arm_steppoint(false);
+    }
+
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  for (i = 0; i < ARM_DEBUG_MAX; i++)
+    {
+      if (g_arm_debug[i].type == type &&
+          g_arm_debug[i].size == size &&
+          g_arm_debug[i].addr == addr)
+        {
+          g_arm_debug[i].type = DEBUGPOINT_NONE;
+          break;
+        }
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: arm_enable_dbgmonitor
+ *
+ * Description:
+ *   This function enables the debug monitor exception.
+ *
+ ****************************************************************************/
+
+int arm_enable_dbgmonitor(void)
+{
+  arm_fpb_init();
+  arm_dwt_init();
+  modifyreg32(NVIC_DEMCR, 0, NVIC_DEMCR_MONEN | NVIC_DEMCR_TRCENA);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: arm_dbgmonitor
+ *
+ * Description:
+ *   This is Debug Monitor exception handler.  This function is entered when
+ *   the processor enters debug mode.  The debug monitor handler will handle
+ *   debug events, and resume execution.
+ *
+ ****************************************************************************/
+
+int arm_dbgmonitor(int irq, void *context, void *arg)
+{
+  uint32_t dfsr = getreg32(NVIC_DFAULTS);
+  uint32_t *regs = (uint32_t *)context;
+
+  if ((dfsr & NVIC_DFAULTS_HALTED) != 0)
+    {
+      arm_steppoint_match();
+    }
+
+  if ((dfsr & NVIC_DFAULTS_BKPT) != 0)
+    {
+      arm_breakpoint_match(regs[REG_PC]);
+    }
+
+  if ((dfsr & NVIC_DFAULTS_DWTTRAP) != 0)
+    {
+      arm_watchpoint_match();
+    }
+
+  return OK;
+}
diff --git a/arch/arm/src/armv7-m/fpb.h b/arch/arm/src/armv7-m/fpb.h
index 320fc04de2..38c1022a40 100644
--- a/arch/arm/src/armv7-m/fpb.h
+++ b/arch/arm/src/armv7-m/fpb.h
@@ -61,6 +61,17 @@
 
 /* FPB_CTRL */
 
+/* REV
+ *
+ * Flash Patch and Breakpoint Unit revision number.
+ * 0000: Flash patch Breakpoint Unit revision 1
+ * 0001: Flash patch Breakpoint Unit revision 2. Supports breakpoints on
+ * any location in the 4GB address range.
+ */
+
+#define FPB_CTRL_REV_SHIFT        28
+#define FPB_CTRL_REV_MASK         0xF0000000
+
 /* NUM_CODE2
  *
  * Number of full banks of code comparators, sixteen comparators per bank.
diff --git a/arch/arm/src/armv7-m/nvic.h b/arch/arm/src/armv7-m/nvic.h
index b98be5b511..fff728acbe 100644
--- a/arch/arm/src/armv7-m/nvic.h
+++ b/arch/arm/src/armv7-m/nvic.h
@@ -635,6 +635,14 @@
 #define NVIC_HFAULTS_FORCED             (1 << 30) /* Bit 30: FORCED Mask */
 #define NVIC_HFAULTS_DEBUGEVT           (1 << 31) /* Bit 31: DEBUGEVT Mask */
 
+/* Debug Fault Status Register */
+
+#define NVIC_DFAULTS_HALTED             (1 << 0)  /* Bit 0:  Halted Mask */
+#define NVIC_DFAULTS_BKPT               (1 << 1)  /* Bit 1:  BKPT or FPB Mask */
+#define NVIC_DFAULTS_DWTTRAP            (1 << 2)  /* Bit 2:  DWT Mask */
+#define NVIC_DFAULTS_VCATCH             (1 << 3)  /* Bit 3:  Vector catch Mask */
+#define NVIC_DFAULTS_EXTERNAL           (1 << 4)  /* Bit 4:  External debug request Mask */
+
 /* Cache Level ID register (Cortex-M7) */
 
 #define NVIC_CLIDR_L1CT_SHIFT           (0)      /* Bits 0-2: Level 1 cache type */
diff --git a/arch/arm/src/armv8-m/CMakeLists.txt b/arch/arm/src/armv8-m/CMakeLists.txt
index db57c8b24c..eed1feb3d8 100644
--- a/arch/arm/src/armv8-m/CMakeLists.txt
+++ b/arch/arm/src/armv8-m/CMakeLists.txt
@@ -22,6 +22,7 @@ set(SRCS
     arm_exception.S
     arm_saveusercontext.S
     arm_busfault.c
+    arm_dbgmonitor.c
     arm_cache.c
     arm_cpuinfo.c
     arm_doirq.c
diff --git a/arch/arm/src/armv8-m/Make.defs b/arch/arm/src/armv8-m/Make.defs
index d74ab316be..8c80208381 100644
--- a/arch/arm/src/armv8-m/Make.defs
+++ b/arch/arm/src/armv8-m/Make.defs
@@ -30,7 +30,7 @@ CMN_CSRCS += arm_memfault.c arm_perf.c arm_sau.c
 CMN_CSRCS += arm_schedulesigaction.c arm_securefault.c arm_secure_irq.c
 CMN_CSRCS += arm_sigdeliver.c arm_svcall.c
 CMN_CSRCS += arm_systemreset.c arm_tcbinfo.c
-CMN_CSRCS += arm_trigger_irq.c arm_usagefault.c arm_vectors.c
+CMN_CSRCS += arm_trigger_irq.c arm_usagefault.c arm_vectors.c arm_dbgmonitor.c
 
 ifeq ($(CONFIG_ARMV8M_SYSTICK),y)
   CMN_CSRCS += arm_systick.c
diff --git a/arch/arm/src/armv8-m/arm_dbgmonitor.c b/arch/arm/src/armv8-m/arm_dbgmonitor.c
new file mode 100644
index 0000000000..c887bd71bd
--- /dev/null
+++ b/arch/arm/src/armv8-m/arm_dbgmonitor.c
@@ -0,0 +1,700 @@
+/****************************************************************************
+ * arch/arm/src/armv8-m/arm_dbgmonitor.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 <nuttx/config.h>
+#include <nuttx/arch.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <arch/irq.h>
+
+#include "nvic.h"
+#include "fpb.h"
+#include "dwt.h"
+#include "arm_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* 4 watchpoint, 4 breakpoint, 1 single step */
+
+#define ARM_DEBUG_MAX (4 + 4 + 1)
+
+#define ARM_FPB_NUM() \
+        (((getreg32(FPB_CTRL) & FPB_CTRL_NUM_CODE2_MASK) >> \
+          FPB_CTRL_NUM_CODE2_SHIFT << FPB_CTRL_NUM_CODE1_SHIFT) | \
+         ((getreg32(FPB_CTRL) & FPB_CTRL_NUM_CODE1_MASK) >> \
+          FPB_CTRL_NUM_CODE1_SHIFT))
+
+#define ARM_FPB_REVISION() \
+        ((getreg32(FPB_CTRL) & FPB_CTRL_REV_MASK) >> FPB_CTRL_REV_SHIFT)
+
+#define ARM_DWT_NUM() \
+        ((getreg32(DWT_CTRL) & DWT_CTRL_NUMCOMP_MASK) >> \
+         DWT_CTRL_NUMCOMP_SHIFT)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct arm_debug_s
+{
+  int type;
+  void *addr;
+  size_t size;
+  debug_callback_t callback;
+  void *arg;
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct arm_debug_s g_arm_debug[ARM_DEBUG_MAX];
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: arm_fpb_init
+ ****************************************************************************/
+
+static void arm_fpb_init(void)
+{
+  uint32_t num = ARM_FPB_NUM();
+  uint32_t i;
+
+  for (i = 0; i < num; i++)
+    {
+      putreg32(0, FPB_COMP0 + i * 4);
+    }
+
+  modifyreg32(FPB_CTRL, 0, FPB_CTRL_ENABLE_MASK | FPB_CTRL_KEY_MASK);
+}
+
+/****************************************************************************
+ * Name: arm_dwt_init
+ ****************************************************************************/
+
+static void arm_dwt_init(void)
+{
+  uint32_t num = ARM_DWT_NUM();
+  uint32_t i;
+
+  for (i = 0; i < num; i++)
+    {
+      putreg32(0, DWT_COMP0 + 16 * i);
+      putreg32(0, DWT_MASK0 + 16 * i);
+      putreg32(0, DWT_FUNCTION0 + 16 * i);
+    }
+}
+
+/****************************************************************************
+ * Name: arm_watchpoint_add
+ *
+ * Description:
+ *   Add a watchpoint on the address.
+ *
+ * Input Parameters:
+ *  type - The type of the watchpoint
+ *  addr - The address to be watched
+ *  size - The size of the address to be watched
+ *
+ * Returned Value:
+ *  Zero on success; a negated errno value on failure
+ *
+ * Notes:
+ *  The size of the watchpoint is determined by the hardware.
+ *
+ ****************************************************************************/
+
+static int arm_watchpoint_add(int type, uintptr_t addr, size_t size)
+{
+  uint32_t num = ARM_DWT_NUM();
+  uint32_t i;
+
+  for (i = 0; i < num; i++)
+    {
+      if (getreg32(DWT_COMP0 + 16 * i) == 0)
+        {
+          uint32_t fun;
+
+          switch (type)
+            {
+              case DEBUGPOINT_WATCHPOINT_RO:
+                fun = DWT_FUNCTION_WATCHPOINT_RO;
+                break;
+              case DEBUGPOINT_WATCHPOINT_WO:
+                fun = DWT_FUNCTION_WATCHPOINT_WO;
+                break;
+              case DEBUGPOINT_WATCHPOINT_RW:
+                fun = DWT_FUNCTION_WATCHPOINT_RW;
+                break;
+              default:
+                return -EINVAL;
+            }
+
+        if (size > 4)
+            {
+              if (i + 1 >= num || i % 2 != 0 ||
+                  getreg32(DWT_COMP0 + 16 * (i + 1)) != 0)
+                {
+                  continue;
+                }
+
+              putreg32(addr + size, DWT_COMP0 + 16 * (i + 1));
+              putreg32(DWT_FUNCTION_WATCHPOINT_CO,
+                       DWT_FUNCTION0 + 16 * (i + 1));
+            }
+
+          putreg32(addr, DWT_COMP0 + 16 * i);
+          putreg32(fun, DWT_FUNCTION0 + 16 * i);
+          putreg32(0, DWT_MASK0 + 16 * i);
+
+          return 0;
+        }
+    }
+
+  return -ENOSPC;
+}
+
+/****************************************************************************
+ * Name: arm_watchpoint_remove
+ *
+ * Description:
+ *   Remove a watchpoint on the address.
+ *
+ * Input Parameters:
+ *   type - The type of the watchpoint.
+ *   addr - The address to be watched.
+ *   size - The size of the address to be watched.
+ *
+ * Returned Value:
+ *  Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int arm_watchpoint_remove(int type, uintptr_t addr, size_t size)
+{
+  uint32_t num = ARM_DWT_NUM();
+  uint32_t i;
+
+  for (i = 0; i < num; i++)
+    {
+      uint32_t fun_type = (getreg32(DWT_FUNCTION0 + 16 * i) &
+                          DWT_FUNCTION_FUNCTION_MASK) >>
+                          DWT_FUNCTION_FUNCTION_SHIFT;
+
+      switch (fun_type)
+        {
+          case DWT_FUNCTION_WATCHPOINT_RO:
+            if (type == DEBUGPOINT_WATCHPOINT_RO)
+              {
+                break;
+              }
+
+            continue;
+          case DWT_FUNCTION_WATCHPOINT_WO:
+            if (type == DEBUGPOINT_WATCHPOINT_WO)
+              {
+                break;
+              }
+
+            continue;
+          case DWT_FUNCTION_WATCHPOINT_RW:
+            if (type == DEBUGPOINT_WATCHPOINT_RW)
+              {
+                break;
+              }
+
+            continue;
+
+          default:
+            continue;
+        }
+
+      if (addr != getreg32(DWT_COMP0 + 16 * i))
+        {
+          continue;
+        }
+
+      if (size > 4)
+        {
+          if (i + 1 >= num || i % 2 != 0 ||
+              getreg32(DWT_COMP0 + 16 * (i + 1)) == 0)
+            {
+              continue;
+            }
+
+          putreg32(0, DWT_COMP0 + 16 * (i + 1));
+          putreg32(0, DWT_FUNCTION0 + 16 * (i + 1));
+          putreg32(0, DWT_MASK0 + 16 * (i + 1));
+        }
+
+      putreg32(0, DWT_COMP0 + 16 * i);
+      putreg32(0, DWT_FUNCTION0 + 16 * i);
+      putreg32(0, DWT_MASK0 + 16 * i);
+      return 0;
+    }
+
+  return -EINVAL;
+}
+
+/****************************************************************************
+ * Name: arm_watchpoint_match
+ *
+ * Description:
+ *   This function will be called when watchpoint match.
+ *
+ ****************************************************************************/
+
+static void arm_watchpoint_match(void)
+{
+  uint32_t num = ARM_DWT_NUM();
+  uint32_t addr = 0;
+  uint32_t i;
+  int type = 0;
+
+  for (i = 0; i < num; i++)
+    {
+      uint32_t fun = getreg32(DWT_FUNCTION0 + 16 * i);
+
+      if (fun & DWT_FUNCTION_MATCHED_MASK)
+        {
+          uint32_t fun_type = (fun & DWT_FUNCTION_FUNCTION_MASK) >>
+                              DWT_FUNCTION_FUNCTION_SHIFT;
+
+          addr = getreg32(DWT_COMP0 + 16 * i);
+          switch (fun_type)
+            {
+              case DWT_FUNCTION_WATCHPOINT_RO:
+                type = DEBUGPOINT_WATCHPOINT_RO;
+                break;
+              case DWT_FUNCTION_WATCHPOINT_WO:
+                type = DEBUGPOINT_WATCHPOINT_WO;
+                break;
+              case DWT_FUNCTION_WATCHPOINT_RW:
+                type = DEBUGPOINT_WATCHPOINT_RW;
+                break;
+
+              default:
+                continue;
+            }
+
+          break;
+        }
+    }
+
+  for (i = 0; i < ARM_DEBUG_MAX; i++)
+    {
+      if (g_arm_debug[i].addr == (void *)addr &&
+          g_arm_debug[i].type == type && g_arm_debug[i].callback)
+        {
+          g_arm_debug[i].callback(g_arm_debug[i].type,
+                                  g_arm_debug[i].addr,
+                                  g_arm_debug[i].size,
+                                  g_arm_debug[i].arg);
+          break;
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: arm_breakpoint_add
+ *
+ * Description:
+ *   Add a breakpoint on addr.
+ *
+ * Input Parameters:
+ *  addr - The address to break.
+ *
+ * Returned Value:
+ *  Zero on success; a negated errno value on failure
+ *
+ * Notes:
+ *  1. If breakpoint is already set, it will do nothing.
+ *  2. If all comparators are in use, it will return -ENOSPC.
+ *  3. When the breakpoint trigger, if enable monitor exception already ,
+ *     will cause a debug monitor exception, otherwise will cause
+ *     a hard fault.
+ *
+ ****************************************************************************/
+
+static int arm_breakpoint_add(uintptr_t addr)
+{
+  uint32_t revision = ARM_FPB_REVISION();
+  uint32_t num = ARM_FPB_NUM();
+  uint32_t fpb_comp;
+  uint32_t i;
+
+  if (revision == 0)
+    {
+      uint32_t replace = (addr & 0x2) == 0 ? 1 : 2;
+      fpb_comp = (addr & ~0x3) | FPB_COMP0_ENABLE_MASK |
+                 (replace << FPB_COMP0_REPLACE_SHIFT);
+    }
+  else
+    {
+      fpb_comp = addr | FPB_COMP0_ENABLE_MASK;
+    }
+
+  for (i = 0; i < num; i++)
+    {
+      uint32_t comp = getreg32(FPB_COMP0 + i * 4);
+
+      if (comp == fpb_comp) /* Already set */
+        {
+          return 0;
+        }
+      else if (comp & FPB_COMP0_ENABLE_MASK) /* Comparators is in use */
+        {
+          continue;
+        }
+      else /* Find a free comparators */
+        {
+          putreg32(fpb_comp, FPB_COMP0 + i * 4);
+          return 0;
+        }
+    }
+
+  return -ENOSPC;
+}
+
+/****************************************************************************
+ * Name: arm_breakpoint_remove
+ *
+ * Description:
+ *   Remove a breakpoint on addr.
+ *
+ * Input Parameters:
+ *  addr - The address to remove.
+ *
+ * Returned Value:
+ *  Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int arm_breakpoint_remove(uintptr_t addr)
+{
+  uint32_t revision = ARM_FPB_REVISION();
+  uint32_t num = ARM_FPB_NUM();
+  uint32_t fpb_comp;
+  uint32_t i;
+
+  if (revision == 0)
+    {
+      uint32_t replace = (addr & 0x2) == 0 ? 1 : 2;
+      fpb_comp = (addr & ~0x3) | FPB_COMP0_ENABLE_MASK |
+                (replace << FPB_COMP0_REPLACE_SHIFT);
+    }
+  else
+    {
+      fpb_comp = addr | FPB_COMP0_ENABLE_MASK;
+    }
+
+  for (i = 0; i < num; i++)
+    {
+      if (fpb_comp == getreg32(FPB_COMP0 + i * 4))
+        {
+          putreg32(0, FPB_COMP0 + i * 4);
+          return 0;
+        }
+    }
+
+  return -EINVAL;
+}
+
+/****************************************************************************
+ * Name: arm_breakpoint_match
+ *
+ * Description:
+ *   This function will be called when breakpoint match.
+ *
+ ****************************************************************************/
+
+static void arm_breakpoint_match(uintptr_t pc)
+{
+  int i;
+
+  for (i = 0; i < ARM_DEBUG_MAX; i++)
+    {
+      if (g_arm_debug[i].type == DEBUGPOINT_BREAKPOINT &&
+          g_arm_debug[i].addr == (void *)pc &&
+          g_arm_debug[i].callback != NULL)
+        {
+          g_arm_debug[i].callback(g_arm_debug[i].type,
+                                  g_arm_debug[i].addr,
+                                  g_arm_debug[i].size,
+                                  g_arm_debug[i].arg);
+          break;
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: arm_steppoint
+ *
+ * Description:
+ *   Enable/disable single step.
+ *
+ * Input Parameters:
+ *  enable - True: enable single step; False: disable single step.
+ *
+ * Returned Value:
+ *  Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int arm_steppoint(bool enable)
+{
+  if (enable)
+    {
+      modifyreg32(NVIC_DEMCR, 0, NVIC_DEMCR_MONSTEP);
+    }
+  else
+    {
+      modifyreg32(NVIC_DEMCR, NVIC_DEMCR_MONSTEP, 0);
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: arm_steppoint_match
+ *
+ * Description:
+ *   This function will be called when single step match.
+ *
+ ****************************************************************************/
+
+static void arm_steppoint_match(void)
+{
+  int i;
+
+  for (i = 0; i < ARM_DEBUG_MAX; i++)
+    {
+      if (g_arm_debug[i].type == DEBUGPOINT_STEPPOINT &&
+          g_arm_debug[i].callback != NULL)
+        {
+          g_arm_debug[i].callback(g_arm_debug[i].type,
+                                  g_arm_debug[i].addr,
+                                  g_arm_debug[i].size,
+                                  g_arm_debug[i].arg);
+          break;
+        }
+    }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_debugpoint_add
+ *
+ * Description:
+ *   Add a debugpoint.
+ *
+ * Input Parameters:
+ *   type     - The debugpoint type. optional value:
+ *              DEBUGPOINT_WATCHPOINT_RO - Read only watchpoint.
+ *              DEBUGPOINT_WATCHPOINT_WO - Write only watchpoint.
+ *              DEBUGPOINT_WATCHPOINT_RW - Read and write watchpoint.
+ *              DEBUGPOINT_BREAKPOINT    - Breakpoint.
+ *              DEBUGPOINT_STEPPOINT     - Single step.
+ *   addr     - The address to be debugged.
+ *   size     - The watchpoint size. only for watchpoint.
+ *   callback - The callback function when debugpoint triggered.
+ *              if NULL, the debugpoint will be removed.
+ *   arg      - The argument of callback function.
+ *
+ * Returned Value:
+ *  Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+int up_debugpoint_add(int type, void *addr, size_t size,
+                      debug_callback_t callback, void *arg)
+{
+  int ret = -EINVAL;
+  int i;
+
+  if (type == DEBUGPOINT_BREAKPOINT)
+    {
+      ret = arm_breakpoint_add((uintptr_t)addr);
+
+      /* Thumb mode breakpoint address must be word-aligned */
+
+      addr = (void *)((uintptr_t)addr & ~0x1);
+    }
+  else if (type == DEBUGPOINT_WATCHPOINT_RO ||
+           type == DEBUGPOINT_WATCHPOINT_WO ||
+           type == DEBUGPOINT_WATCHPOINT_RW)
+    {
+      ret = arm_watchpoint_add(type, (uintptr_t)addr, size);
+    }
+  else if (type == DEBUGPOINT_STEPPOINT)
+    {
+      ret = arm_steppoint(true);
+    }
+
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  for (i = 0; i < ARM_DEBUG_MAX; i++)
+    {
+      if (g_arm_debug[i].type == DEBUGPOINT_NONE)
+        {
+          g_arm_debug[i].type = type;
+          g_arm_debug[i].addr = addr;
+          g_arm_debug[i].size = size;
+          g_arm_debug[i].callback = callback;
+          g_arm_debug[i].arg = arg;
+          break;
+        }
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: up_debugpoint_remove
+ *
+ * Description:
+ *   Remove a debugpoint.
+ *
+ * Input Parameters:
+ *   type     - The debugpoint type. optional value:
+ *              DEBUGPOINT_WATCHPOINT_RO - Read only watchpoint.
+ *              DEBUGPOINT_WATCHPOINT_WO - Write only watchpoint.
+ *              DEBUGPOINT_WATCHPOINT_RW - Read and write watchpoint.
+ *              DEBUGPOINT_BREAKPOINT    - Breakpoint.
+ *              DEBUGPOINT_STEPPOINT     - Single step.
+ *   addr     - The address to be debugged.
+ *   size     - The watchpoint size. only for watchpoint.
+ *
+ * Returned Value:
+ *  Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+int up_debugpoint_remove(int type, void *addr, size_t size)
+{
+  int ret = -EINVAL;
+  int i;
+
+  if (type == DEBUGPOINT_BREAKPOINT)
+    {
+      ret = arm_breakpoint_remove((uintptr_t)addr);
+
+      /* Thumb mode breakpoint address must be word-aligned */
+
+      addr = (void *)((uintptr_t)addr & ~0x1);
+    }
+  else if (type == DEBUGPOINT_WATCHPOINT_RO ||
+           type == DEBUGPOINT_WATCHPOINT_WO ||
+           type == DEBUGPOINT_WATCHPOINT_RW)
+    {
+      ret = arm_watchpoint_remove(type, (uintptr_t)addr, size);
+    }
+  else if (type == DEBUGPOINT_STEPPOINT)
+    {
+      ret = arm_steppoint(false);
+    }
+
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  for (i = 0; i < ARM_DEBUG_MAX; i++)
+    {
+      if (g_arm_debug[i].type == type &&
+          g_arm_debug[i].size == size &&
+          g_arm_debug[i].addr == addr)
+        {
+          g_arm_debug[i].type = DEBUGPOINT_NONE;
+          break;
+        }
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: arm_enable_dbgmonitor
+ *
+ * Description:
+ *   This function enables the debug monitor exception.
+ *
+ ****************************************************************************/
+
+int arm_enable_dbgmonitor(void)
+{
+  arm_fpb_init();
+  arm_dwt_init();
+  modifyreg32(NVIC_DEMCR, 0, NVIC_DEMCR_MONEN | NVIC_DEMCR_TRCENA);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: arm_dbgmonitor
+ *
+ * Description:
+ *   This is Debug Monitor exception handler.  This function is entered when
+ *   the processor enters debug mode.  The debug monitor handler will handle
+ *   debug events, and resume execution.
+ *
+ ****************************************************************************/
+
+int arm_dbgmonitor(int irq, void *context, void *arg)
+{
+  uint32_t dfsr = getreg32(NVIC_DFAULTS);
+  uint32_t *regs = (uint32_t *)context;
+
+  if ((dfsr & NVIC_DFAULTS_HALTED) != 0)
+    {
+      arm_steppoint_match();
+    }
+
+  if ((dfsr & NVIC_DFAULTS_BKPT) != 0)
+    {
+      arm_breakpoint_match(regs[REG_PC]);
+    }
+
+  if ((dfsr & NVIC_DFAULTS_DWTTRAP) != 0)
+    {
+      arm_watchpoint_match();
+    }
+
+  return OK;
+}
diff --git a/arch/arm/src/armv8-m/dwt.h b/arch/arm/src/armv8-m/dwt.h
index 584e543a6c..314f5b30de 100644
--- a/arch/arm/src/armv8-m/dwt.h
+++ b/arch/arm/src/armv8-m/dwt.h
@@ -222,6 +222,13 @@
 #define DWT_FUNCTION_EMITRANGE_SHIFT  5
 #define DWT_FUNCTION_EMITRANGE_MASK   (0x1ul << DWT_FUNCTION_EMITRANGE_SHIFT)
 #define DWT_FUNCTION_FUNCTION_SHIFT   0
-#define DWT_FUNCTION_FUNCTION_MASK    (0xful << DWT_FUNCTION_FUNCTION_SHIFT)
+#define DWT_FUNCTION_FUNCTION_MASK    (0x1ful << DWT_FUNCTION_FUNCTION_SHIFT)
+
+/* Two comparator are consecutive flags */
+
+#define DWT_FUNCTION_WATCHPOINT_CO    (0x17ul << DWT_FUNCTION_FUNCTION_SHIFT)
+#define DWT_FUNCTION_WATCHPOINT_RO    (0x16ul << DWT_FUNCTION_FUNCTION_SHIFT)
+#define DWT_FUNCTION_WATCHPOINT_WO    (0x15ul << DWT_FUNCTION_FUNCTION_SHIFT)
+#define DWT_FUNCTION_WATCHPOINT_RW    (0x14ul << DWT_FUNCTION_FUNCTION_SHIFT)
 
 #endif /* __ARCH_ARM_SRC_ARMV8_M_DWT_H */
diff --git a/arch/arm/src/armv8-m/fpb.h b/arch/arm/src/armv8-m/fpb.h
index de14a4c77b..ce51a6f1b8 100644
--- a/arch/arm/src/armv8-m/fpb.h
+++ b/arch/arm/src/armv8-m/fpb.h
@@ -61,6 +61,17 @@
 
 /* FPB_CTRL */
 
+/* REV
+ *
+ * Flash Patch and Breakpoint Unit revision number.
+ * 0000: Flash patch Breakpoint Unit revision 1
+ * 0001: Flash patch Breakpoint Unit revision 2. Supports breakpoints on
+ * any location in the 4GB address range.
+ */
+
+#define FPB_CTRL_REV_SHIFT        28
+#define FPB_CTRL_REV_MASK         0xF0000000
+
 /* NUM_CODE2
  *
  * Number of full banks of code comparators, sixteen comparators per bank.
diff --git a/arch/arm/src/armv8-m/nvic.h b/arch/arm/src/armv8-m/nvic.h
index 07459ba904..cf98d26c44 100644
--- a/arch/arm/src/armv8-m/nvic.h
+++ b/arch/arm/src/armv8-m/nvic.h
@@ -725,6 +725,14 @@
 #define NVIC_HFAULTS_FORCED             (1 << 30) /* Bit 30: FORCED Mask */
 #define NVIC_HFAULTS_DEBUGEVT           (1 << 31) /* Bit 31: DEBUGEVT Mask */
 
+/* Debug Fault Status Register */
+
+#define NVIC_DFAULTS_HALTED             (1 << 0)  /* Bit 0:  Halted Mask */
+#define NVIC_DFAULTS_BKPT               (1 << 1)  /* Bit 1:  BKPT or FPB Mask */
+#define NVIC_DFAULTS_DWTTRAP            (1 << 2)  /* Bit 2:  DWT Mask */
+#define NVIC_DFAULTS_VCATCH             (1 << 3)  /* Bit 3:  Vector catch Mask */
+#define NVIC_DFAULTS_EXTERNAL           (1 << 4)  /* Bit 4:  External debug request Mask */
+
 /* Cache Level ID register */
 
 #define NVIC_CLIDR_L1CT_SHIFT           (0)      /* Bits 0-2: Level 1 cache type */
diff --git a/arch/arm/src/common/arm_internal.h b/arch/arm/src/common/arm_internal.h
index 271aa05e28..f8971cf41c 100644
--- a/arch/arm/src/common/arm_internal.h
+++ b/arch/arm/src/common/arm_internal.h
@@ -384,6 +384,8 @@ EXTERN const void * const _vectors[];
 
 int  arm_svcall(int irq, void *context, void *arg);
 int  arm_hardfault(int irq, void *context, void *arg);
+int  arm_enable_dbgmonitor(void);
+int  arm_dbgmonitor(int irq, void *context, void *arg);
 
 #  if defined(CONFIG_ARCH_ARMV7M) || defined(CONFIG_ARCH_ARMV8M)
 
diff --git a/arch/arm/src/cxd56xx/cxd56_irq.c b/arch/arm/src/cxd56xx/cxd56_irq.c
index 98770ed6e7..5885ed53fe 100644
--- a/arch/arm/src/cxd56xx/cxd56_irq.c
+++ b/arch/arm/src/cxd56xx/cxd56_irq.c
@@ -151,8 +151,7 @@ static void cxd56_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: cxd56_nmi, cxd56_pendsv,
- *       cxd56_dbgmonitor, cxd56_pendsv, cxd56_reserved
+ * Name: cxd56_nmi, cxd56_pendsv, cxd56_pendsv, cxd56_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -178,14 +177,6 @@ static int cxd56_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int cxd56_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int cxd56_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -363,7 +354,8 @@ void up_irqinitialize(void)
   irq_attach(CXD56_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(CXD56_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(CXD56_IRQ_PENDSV, cxd56_pendsv, NULL);
-  irq_attach(CXD56_IRQ_DBGMONITOR, cxd56_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(CXD56_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(CXD56_IRQ_RESERVED, cxd56_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/efm32/efm32_irq.c b/arch/arm/src/efm32/efm32_irq.c
index 53f422b6d7..b24d3408ad 100644
--- a/arch/arm/src/efm32/efm32_irq.c
+++ b/arch/arm/src/efm32/efm32_irq.c
@@ -132,8 +132,7 @@ static void efm32_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: efm32_nmi, efm32_pendsv,
- *       efm32_dbgmonitor, efm32_pendsv, efm32_reserved
+ * Name: efm32_nmi, efm32_pendsv, efm32_pendsv, efm32_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -159,14 +158,6 @@ static int efm32_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int efm32_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int efm32_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -360,7 +351,8 @@ void up_irqinitialize(void)
   irq_attach(EFM32_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(EFM32_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(EFM32_IRQ_PENDSV, efm32_pendsv, NULL);
-  irq_attach(EFM32_IRQ_DBGMONITOR, efm32_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(EFM32_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(EFM32_IRQ_RESERVED, efm32_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/eoss3/eoss3_irq.c b/arch/arm/src/eoss3/eoss3_irq.c
index 2fa1b963cb..a23ac273f8 100644
--- a/arch/arm/src/eoss3/eoss3_irq.c
+++ b/arch/arm/src/eoss3/eoss3_irq.c
@@ -113,8 +113,7 @@ static void eoss3_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: eoss3_nmi, eoss3_pendsv,
- *       eoss3_dbgmonitor, eoss3_pendsv, eoss3_reserved
+ * Name: eoss3_nmi, eoss3_pendsv, eoss3_pendsv, eoss3_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -140,14 +139,6 @@ static int eoss3_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int eoss3_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int eoss3_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -341,7 +332,8 @@ void up_irqinitialize(void)
   irq_attach(EOSS3_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(EOSS3_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(EOSS3_IRQ_PENDSV, eoss3_pendsv, NULL);
-  irq_attach(EOSS3_IRQ_DBGMONITOR, eoss3_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(EOSS3_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(EOSS3_IRQ_RESERVED, eoss3_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/gd32f4/gd32f4xx_irq.c b/arch/arm/src/gd32f4/gd32f4xx_irq.c
index f8db23cdff..0e3dc2570a 100644
--- a/arch/arm/src/gd32f4/gd32f4xx_irq.c
+++ b/arch/arm/src/gd32f4/gd32f4xx_irq.c
@@ -138,8 +138,7 @@ static void gd32_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: gd32_nmi, gd32_pendsv,
- *       gd32_dbgmonitor, gd32_pendsv, gd32_reserved
+ * Name: gd32_nmi, gd32_pendsv, gd32_pendsv, gd32_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -165,14 +164,6 @@ static int gd32_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int gd32_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int gd32_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -370,7 +361,8 @@ void up_irqinitialize(void)
   irq_attach(GD32_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(GD32_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(GD32_IRQ_PENDSV, gd32_pendsv, NULL);
-  irq_attach(GD32_IRQ_DBGMONITOR, gd32_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(GD32_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(GD32_IRQ_RESERVED, gd32_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/imxrt/imxrt_irq.c b/arch/arm/src/imxrt/imxrt_irq.c
index 68485d8f77..285343a669 100644
--- a/arch/arm/src/imxrt/imxrt_irq.c
+++ b/arch/arm/src/imxrt/imxrt_irq.c
@@ -214,8 +214,7 @@ static void imxrt_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: imxrt_nmi, imxrt_pendsv,
- *       imxrt_dbgmonitor, imxrt_pendsv, imxrt_reserved
+ * Name: imxrt_nmi, imxrt_pendsv, imxrt_pendsv, imxrt_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -241,14 +240,6 @@ static int imxrt_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int imxrt_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int imxrt_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -505,7 +496,8 @@ void up_irqinitialize(void)
   irq_attach(IMXRT_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(IMXRT_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(IMXRT_IRQ_PENDSV, imxrt_pendsv, NULL);
-  irq_attach(IMXRT_IRQ_DBGMONITOR, imxrt_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(IMXRT_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(IMXRT_IRQ_RESERVED, imxrt_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/kinetis/kinetis_irq.c b/arch/arm/src/kinetis/kinetis_irq.c
index fc90c7d717..41e856c7a7 100644
--- a/arch/arm/src/kinetis/kinetis_irq.c
+++ b/arch/arm/src/kinetis/kinetis_irq.c
@@ -144,8 +144,7 @@ static void kinetis_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: kinetis_nmi, kinetis_pendsv,
- *       kinetis_dbgmonitor, kinetis_pendsv, kinetis_reserved
+ * Name: kinetis_nmi, kinetis_pendsv, kinetis_pendsv, kinetis_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -171,14 +170,6 @@ static int kinetis_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int kinetis_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int kinetis_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -391,7 +382,8 @@ void up_irqinitialize(void)
   irq_attach(KINETIS_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(KINETIS_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(KINETIS_IRQ_PENDSV, kinetis_pendsv, NULL);
-  irq_attach(KINETIS_IRQ_DBGMONITOR, kinetis_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(KINETIS_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(KINETIS_IRQ_RESERVED, kinetis_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/lc823450/lc823450_irq.c b/arch/arm/src/lc823450/lc823450_irq.c
index 4a33df3262..c64e1a3a31 100644
--- a/arch/arm/src/lc823450/lc823450_irq.c
+++ b/arch/arm/src/lc823450/lc823450_irq.c
@@ -172,8 +172,7 @@ static void lc823450_dumpnvic(const char *msg, int irq)
 
 /****************************************************************************
  * Name: lc823450_nmi,
- *       lc823450_pendsv, lc823450_dbgmonitor, lc823450_pendsv,
- *       lc823450_reserved
+ *       lc823450_pendsv, lc823450_pendsv, lc823450_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -199,14 +198,6 @@ static int lc823450_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int lc823450_dbgmonitor(int irq, void *context, void *arg)
-{
-  enter_critical_section();
-  irqinfo("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int lc823450_reserved(int irq, void *context, void *arg)
 {
   enter_critical_section();
@@ -517,7 +508,8 @@ void up_irqinitialize(void)
   irq_attach(LC823450_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(LC823450_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(LC823450_IRQ_PENDSV, lc823450_pendsv, NULL);
-  irq_attach(LC823450_IRQ_DBGMONITOR, lc823450_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(LC823450_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(LC823450_IRQ_RESERVED, lc823450_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/lpc17xx_40xx/lpc17_40_irq.c b/arch/arm/src/lpc17xx_40xx/lpc17_40_irq.c
index 02194b62c4..d0f1316568 100644
--- a/arch/arm/src/lpc17xx_40xx/lpc17_40_irq.c
+++ b/arch/arm/src/lpc17xx_40xx/lpc17_40_irq.c
@@ -117,8 +117,7 @@ static void lpc17_40_dumpnvic(const char *msg, int irq)
 
 /****************************************************************************
  * Name: lpc17_40_nmi, lpc17_40_busfault, lpc17_40_usagefault,
- *       lpc17_40_pendsv, lpc17_40_dbgmonitor, lpc17_40_pendsv,
- *       lpc17_40_reserved
+ *       lpc17_40_pendsv, lpc17_40_pendsv, lpc17_40_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -144,14 +143,6 @@ static int lpc17_40_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int lpc17_40_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int lpc17_40_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -361,7 +352,8 @@ void up_irqinitialize(void)
   irq_attach(LPC17_40_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(LPC17_40_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(LPC17_40_IRQ_PENDSV, lpc17_40_pendsv, NULL);
-  irq_attach(LPC17_40_IRQ_DBGMONITOR, lpc17_40_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(LPC17_40_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(LPC17_40_IRQ_RESERVED, lpc17_40_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/lpc43xx/lpc43_irq.c b/arch/arm/src/lpc43xx/lpc43_irq.c
index 642832637a..e244a17a7e 100644
--- a/arch/arm/src/lpc43xx/lpc43_irq.c
+++ b/arch/arm/src/lpc43xx/lpc43_irq.c
@@ -122,8 +122,7 @@ static void lpc43_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: lpc43_nmi, lpc43_pendsv,
- *       lpc43_dbgmonitor, lpc43_pendsv, lpc43_reserved
+ * Name: lpc43_nmi, lpc43_pendsv, lpc43_pendsv, lpc43_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -149,14 +148,6 @@ static int lpc43_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int lpc43_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int lpc43_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -354,7 +345,8 @@ void up_irqinitialize(void)
   irq_attach(LPC43_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(LPC43_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(LPC43_IRQ_PENDSV, lpc43_pendsv, NULL);
-  irq_attach(LPC43_IRQ_DBGMONITOR, lpc43_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(LPC43_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(LPC43_IRQ_RESERVED, lpc43_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/lpc54xx/lpc54_irq.c b/arch/arm/src/lpc54xx/lpc54_irq.c
index caba3997f8..e58d5ae711 100644
--- a/arch/arm/src/lpc54xx/lpc54_irq.c
+++ b/arch/arm/src/lpc54xx/lpc54_irq.c
@@ -121,8 +121,7 @@ static void lpc54_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: lpc54_nmi, lpc54_pendsv,
- *       lpc54_dbgmonitor, lpc54_pendsv, lpc54_reserved
+ * Name: lpc54_nmi, lpc54_pendsv, lpc54_pendsv, lpc54_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -148,14 +147,6 @@ static int lpc54_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int lpc54_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int lpc54_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -354,7 +345,8 @@ void up_irqinitialize(void)
   irq_attach(LPC54_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(LPC54_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(LPC54_IRQ_PENDSV, lpc54_pendsv, NULL);
-  irq_attach(LPC54_IRQ_DBGMONITOR, lpc54_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(LPC54_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(LPC54_IRQ_RESERVED, lpc54_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/max326xx/common/max326_irq.c b/arch/arm/src/max326xx/common/max326_irq.c
index 454fa1917e..bbb5548ddf 100644
--- a/arch/arm/src/max326xx/common/max326_irq.c
+++ b/arch/arm/src/max326xx/common/max326_irq.c
@@ -122,8 +122,7 @@ static void max326_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: max326_nmi, max326_pendsv,
- *       max326_dbgmonitor, max326_pendsv, max326_reserved
+ * Name: max326_nmi, max326_pendsv, max326_pendsv, max326_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -149,14 +148,6 @@ static int max326_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int max326_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int max326_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -354,7 +345,8 @@ void up_irqinitialize(void)
   irq_attach(MAX326_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(MAX326_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(MAX326_IRQ_PENDSV, max326_pendsv, NULL);
-  irq_attach(MAX326_IRQ_DBGMONITOR, max326_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(MAX326_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(MAX326_IRQ_RESERVED, max326_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/nrf52/nrf52_irq.c b/arch/arm/src/nrf52/nrf52_irq.c
index 0b0939db45..7c400bbf9c 100644
--- a/arch/arm/src/nrf52/nrf52_irq.c
+++ b/arch/arm/src/nrf52/nrf52_irq.c
@@ -123,8 +123,7 @@ static void nrf52_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: nrf52_nmi, nrf52_pendsv,
- *       nrf52_dbgmonitor, nrf52_pendsv, nrf52_reserved
+ * Name: nrf52_nmi, nrf52_pendsv, nrf52_pendsv, nrf52_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -150,14 +149,6 @@ static int nrf52_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int nrf52_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int nrf52_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -358,7 +349,8 @@ void up_irqinitialize(void)
   irq_attach(NRF52_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(NRF52_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(NRF52_IRQ_PENDSV, nrf52_pendsv, NULL);
-  irq_attach(NRF52_IRQ_DBGMONITOR, nrf52_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(NRF52_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(NRF52_IRQ_RESERVED, nrf52_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/nrf53/nrf53_irq.c b/arch/arm/src/nrf53/nrf53_irq.c
index b2f1966cb6..9174ecd22f 100644
--- a/arch/arm/src/nrf53/nrf53_irq.c
+++ b/arch/arm/src/nrf53/nrf53_irq.c
@@ -123,8 +123,7 @@ static void nrf53_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: nrf53_nmi, nrf53_pendsv,
- *       nrf53_dbgmonitor, nrf53_pendsv, nrf53_reserved
+ * Name: nrf53_nmi, nrf53_pendsv, nrf53_pendsv, nrf53_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -150,14 +149,6 @@ static int nrf53_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int nrf53_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int nrf53_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -358,7 +349,8 @@ void up_irqinitialize(void)
   irq_attach(NRF53_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(NRF53_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(NRF53_IRQ_PENDSV, nrf53_pendsv, NULL);
-  irq_attach(NRF53_IRQ_DBGMONITOR, nrf53_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(NRF53_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(NRF53_IRQ_RESERVED, nrf53_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/s32k1xx/s32k14x/s32k14x_irq.c b/arch/arm/src/s32k1xx/s32k14x/s32k14x_irq.c
index a6d6f23870..c299a7c634 100644
--- a/arch/arm/src/s32k1xx/s32k14x/s32k14x_irq.c
+++ b/arch/arm/src/s32k1xx/s32k14x/s32k14x_irq.c
@@ -156,8 +156,7 @@ static void s32k14x_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: s32k14x_nmi, s32k14x_pendsv,
- *       s32k14x_dbgmonitor, s32k14x_pendsv, s32k14x_reserved
+ * Name: s32k14x_nmi, s32k14x_pendsv, s32k14x_pendsv, s32k14x_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -183,14 +182,6 @@ static int s32k14x_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int s32k14x_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int s32k14x_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -389,7 +380,8 @@ void up_irqinitialize(void)
   irq_attach(S32K1XX_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(S32K1XX_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(S32K1XX_IRQ_PENDSV, s32k14x_pendsv, NULL);
-  irq_attach(S32K1XX_IRQ_DBGMONITOR, s32k14x_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(S32K1XX_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(S32K1XX_IRQ_RESERVED, s32k14x_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/s32k3xx/s32k3xx_irq.c b/arch/arm/src/s32k3xx/s32k3xx_irq.c
index 62b0f8028f..81110aab83 100644
--- a/arch/arm/src/s32k3xx/s32k3xx_irq.c
+++ b/arch/arm/src/s32k3xx/s32k3xx_irq.c
@@ -163,8 +163,7 @@ static void s32k3xx_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: s32k3xx_nmi, s32k3xx_pendsv,
- *       s32k3xx_dbgmonitor, s32k3xx_pendsv, s32k3xx_reserved
+ * Name: s32k3xx_nmi, s32k3xx_pendsv, s32k3xx_pendsv, s32k3xx_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -190,14 +189,6 @@ static int s32k3xx_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int s32k3xx_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int s32k3xx_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -396,7 +387,8 @@ void up_irqinitialize(void)
   irq_attach(S32K3XX_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(S32K3XX_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(S32K3XX_IRQ_PENDSV, s32k3xx_pendsv, NULL);
-  irq_attach(S32K3XX_IRQ_DBGMONITOR, s32k3xx_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(S32K3XX_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(S32K3XX_IRQ_RESERVED, s32k3xx_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/sam34/sam_irq.c b/arch/arm/src/sam34/sam_irq.c
index 770e9c2f85..35c08f7836 100644
--- a/arch/arm/src/sam34/sam_irq.c
+++ b/arch/arm/src/sam34/sam_irq.c
@@ -142,8 +142,7 @@ static void sam_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: sam_nmi, sam_pendsv, sam_dbgmonitor,
- *       sam_pendsv, sam_reserved
+ * Name: sam_nmi, sam_pendsv, sam_pendsv, sam_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -169,14 +168,6 @@ static int sam_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int sam_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int sam_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -415,7 +406,8 @@ void up_irqinitialize(void)
   irq_attach(SAM_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(SAM_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(SAM_IRQ_PENDSV, sam_pendsv, NULL);
-  irq_attach(SAM_IRQ_DBGMONITOR, sam_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(SAM_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(SAM_IRQ_RESERVED, sam_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/samd5e5/sam_irq.c b/arch/arm/src/samd5e5/sam_irq.c
index 58b89ea462..eb0d954a03 100644
--- a/arch/arm/src/samd5e5/sam_irq.c
+++ b/arch/arm/src/samd5e5/sam_irq.c
@@ -180,8 +180,7 @@ static void sam_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: sam_nmi, sam_pendsv, sam_dbgmonitor,
- *       sam_pendsv, sam_reserved
+ * Name: sam_nmi, sam_pendsv, sam_pendsv, sam_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -207,14 +206,6 @@ static int sam_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int sam_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int sam_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -502,7 +493,8 @@ void up_irqinitialize(void)
   irq_attach(SAM_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(SAM_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(SAM_IRQ_PENDSV, sam_pendsv, NULL);
-  irq_attach(SAM_IRQ_DBGMONITOR, sam_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(SAM_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(SAM_IRQ_RESERVED, sam_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/samv7/sam_irq.c b/arch/arm/src/samv7/sam_irq.c
index 0ee4aff8b5..87a1571ba7 100644
--- a/arch/arm/src/samv7/sam_irq.c
+++ b/arch/arm/src/samv7/sam_irq.c
@@ -144,8 +144,7 @@ static void sam_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: sam_nmi, sam_pendsv, sam_dbgmonitor,
- *       sam_pendsv, sam_reserved
+ * Name: sam_nmi, sam_pendsv, sam_pendsv, sam_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -171,14 +170,6 @@ static int sam_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int sam_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int sam_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -424,7 +415,8 @@ void up_irqinitialize(void)
   irq_attach(SAM_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(SAM_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(SAM_IRQ_PENDSV, sam_pendsv, NULL);
-  irq_attach(SAM_IRQ_DBGMONITOR, sam_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(SAM_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(SAM_IRQ_RESERVED, sam_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/stm32/stm32_irq.c b/arch/arm/src/stm32/stm32_irq.c
index 03432dd7e0..99374e5db7 100644
--- a/arch/arm/src/stm32/stm32_irq.c
+++ b/arch/arm/src/stm32/stm32_irq.c
@@ -128,8 +128,7 @@ static void stm32_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: stm32_nmi, stm32_pendsv,
- *       stm32_dbgmonitor, stm32_pendsv, stm32_reserved
+ * Name: stm32_nmi, stm32_pendsv, stm32_pendsv, stm32_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -155,14 +154,6 @@ static int stm32_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int stm32_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int stm32_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -362,7 +353,8 @@ void up_irqinitialize(void)
   irq_attach(STM32_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(STM32_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(STM32_IRQ_PENDSV, stm32_pendsv, NULL);
-  irq_attach(STM32_IRQ_DBGMONITOR, stm32_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(STM32_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(STM32_IRQ_RESERVED, stm32_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/stm32f7/stm32_irq.c b/arch/arm/src/stm32f7/stm32_irq.c
index 8111e5c679..6131e37ec0 100644
--- a/arch/arm/src/stm32f7/stm32_irq.c
+++ b/arch/arm/src/stm32f7/stm32_irq.c
@@ -164,8 +164,7 @@ static void stm32_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: stm32_nmi, stm32_pendsv,
- *       stm32_dbgmonitor, stm32_pendsv, stm32_reserved
+ * Name: stm32_nmi, stm32_pendsv,stm32_pendsv, stm32_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -191,14 +190,6 @@ static int stm32_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int stm32_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int stm32_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -459,7 +450,8 @@ void up_irqinitialize(void)
   irq_attach(STM32_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(STM32_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(STM32_IRQ_PENDSV, stm32_pendsv, NULL);
-  irq_attach(STM32_IRQ_DBGMONITOR, stm32_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(STM32_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(STM32_IRQ_RESERVED, stm32_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/stm32h7/stm32_irq.c b/arch/arm/src/stm32h7/stm32_irq.c
index 3dd99295a6..ff78a45874 100644
--- a/arch/arm/src/stm32h7/stm32_irq.c
+++ b/arch/arm/src/stm32h7/stm32_irq.c
@@ -159,8 +159,7 @@ static void stm32_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: stm32_nmi, stm32_pendsv,
- *       stm32_dbgmonitor, stm32_pendsv, stm32_reserved
+ * Name: stm32_nmi, stm32_pendsv, stm32_pendsv, stm32_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -186,14 +185,6 @@ static int stm32_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int stm32_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int stm32_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -481,7 +472,8 @@ void up_irqinitialize(void)
   irq_attach(STM32_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(STM32_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(STM32_IRQ_PENDSV, stm32_pendsv, NULL);
-  irq_attach(STM32_IRQ_DBGMONITOR, stm32_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(STM32_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(STM32_IRQ_RESERVED, stm32_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/stm32l4/stm32l4_irq.c b/arch/arm/src/stm32l4/stm32l4_irq.c
index 7a40ba8ed8..e8c0031550 100644
--- a/arch/arm/src/stm32l4/stm32l4_irq.c
+++ b/arch/arm/src/stm32l4/stm32l4_irq.c
@@ -125,8 +125,7 @@ static void stm32l4_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: stm32l4_nmi, stm32l4_pendsv,
- *       stm32l4_dbgmonitor, stm32l4_pendsv, stm32l4_reserved
+ * Name: stm32l4_nmi, stm32l4_pendsv, stm32l4_pendsv, stm32l4_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -152,14 +151,6 @@ static int stm32l4_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int stm32l4_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int stm32l4_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -349,7 +340,8 @@ void up_irqinitialize(void)
   irq_attach(STM32L4_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(STM32L4_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(STM32L4_IRQ_PENDSV, stm32l4_pendsv, NULL);
-  irq_attach(STM32L4_IRQ_DBGMONITOR, stm32l4_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(STM32L4_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(STM32L4_IRQ_RESERVED, stm32l4_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/stm32l5/stm32l5_irq.c b/arch/arm/src/stm32l5/stm32l5_irq.c
index b93dd26c2f..03f178e678 100644
--- a/arch/arm/src/stm32l5/stm32l5_irq.c
+++ b/arch/arm/src/stm32l5/stm32l5_irq.c
@@ -110,8 +110,7 @@ static void stm32l5_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: stm32l5_nmi, stm32l5_pendsv,
- *       stm32l5_dbgmonitor, stm32l5_pendsv, stm32l5_reserved
+ * Name: stm32l5_nmi, stm32l5_pendsv, stm32l5_pendsv, stm32l5_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -137,14 +136,6 @@ static int stm32l5_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int stm32l5_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int stm32l5_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -336,7 +327,8 @@ void up_irqinitialize(void)
   irq_attach(STM32L5_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(STM32L5_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(STM32L5_IRQ_PENDSV, stm32l5_pendsv, NULL);
-  irq_attach(STM32L5_IRQ_DBGMONITOR, stm32l5_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(STM32L5_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(STM32L5_IRQ_RESERVED, stm32l5_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/stm32u5/stm32_irq.c b/arch/arm/src/stm32u5/stm32_irq.c
index 239d414bec..2931c14d51 100644
--- a/arch/arm/src/stm32u5/stm32_irq.c
+++ b/arch/arm/src/stm32u5/stm32_irq.c
@@ -110,8 +110,7 @@ static void stm32_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: stm32_nmi, stm32_pendsv,
- *       stm32_dbgmonitor, stm32_pendsv, stm32_reserved
+ * Name: stm32_nmi, stm32_pendsv, stm32_pendsv, stm32_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -137,14 +136,6 @@ static int stm32_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int stm32_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int stm32_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -336,7 +327,8 @@ void up_irqinitialize(void)
   irq_attach(STM32_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(STM32_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(STM32_IRQ_PENDSV, stm32_pendsv, NULL);
-  irq_attach(STM32_IRQ_DBGMONITOR, stm32_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(STM32_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(STM32_IRQ_RESERVED, stm32_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/stm32wb/stm32wb_irq.c b/arch/arm/src/stm32wb/stm32wb_irq.c
index f4ffe0e68d..1756a57544 100644
--- a/arch/arm/src/stm32wb/stm32wb_irq.c
+++ b/arch/arm/src/stm32wb/stm32wb_irq.c
@@ -126,8 +126,7 @@ static void stm32wb_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: stm32wb_nmi, stm32wb_pendsv,
- *       stm32wb_dbgmonitor, stm32wb_pendsv, stm32wb_reserved
+ * Name: stm32wb_nmi, stm32wb_pendsv,stm32wb_pendsv, stm32wb_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -153,14 +152,6 @@ static int stm32wb_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int stm32wb_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int stm32wb_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -354,7 +345,8 @@ void up_irqinitialize(void)
   irq_attach(STM32WB_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(STM32WB_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(STM32WB_IRQ_PENDSV, stm32wb_pendsv, NULL);
-  irq_attach(STM32WB_IRQ_DBGMONITOR, stm32wb_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(STM32WB_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(STM32WB_IRQ_RESERVED, stm32wb_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/stm32wl5/stm32wl5_irq.c b/arch/arm/src/stm32wl5/stm32wl5_irq.c
index c4107c491a..47740528fe 100644
--- a/arch/arm/src/stm32wl5/stm32wl5_irq.c
+++ b/arch/arm/src/stm32wl5/stm32wl5_irq.c
@@ -126,8 +126,7 @@ static void stm32wl5_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: stm32wl5_nmi, stm32wl5_pendsv,
- *       stm32wl5_dbgmonitor, stm32wl5_pendsv, stm32wl5_reserved
+ * Name: stm32wl5_nmi, stm32wl5_pendsv, stm32wl5_pendsv, stm32wl5_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -153,14 +152,6 @@ static int stm32wl5_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int stm32wl5_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int stm32wl5_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -350,7 +341,8 @@ void up_irqinitialize(void)
   irq_attach(STM32WL5_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(STM32WL5_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(STM32WL5_IRQ_PENDSV, stm32wl5_pendsv, NULL);
-  irq_attach(STM32WL5_IRQ_DBGMONITOR, stm32wl5_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(STM32WL5_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(STM32WL5_IRQ_RESERVED, stm32wl5_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/tiva/common/tiva_irq.c b/arch/arm/src/tiva/common/tiva_irq.c
index 6445a40078..e049a1b2a1 100644
--- a/arch/arm/src/tiva/common/tiva_irq.c
+++ b/arch/arm/src/tiva/common/tiva_irq.c
@@ -193,8 +193,7 @@ static void tiva_dumpnvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: tiva_nmi, tiva_pendsv,
- *       tiva_dbgmonitor, tiva_pendsv, tiva_reserved
+ * Name: tiva_nmi, tiva_pendsv, tiva_pendsv, tiva_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -220,14 +219,6 @@ static int tiva_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int tiva_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int tiva_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -479,7 +470,8 @@ void up_irqinitialize(void)
   irq_attach(TIVA_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(TIVA_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(TIVA_IRQ_PENDSV, tiva_pendsv, NULL);
-  irq_attach(TIVA_IRQ_DBGMONITOR, tiva_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(TIVA_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(TIVA_IRQ_RESERVED, tiva_reserved, NULL);
 #endif
 
diff --git a/arch/arm/src/xmc4/xmc4_irq.c b/arch/arm/src/xmc4/xmc4_irq.c
index 907ad0dbef..f58754b023 100644
--- a/arch/arm/src/xmc4/xmc4_irq.c
+++ b/arch/arm/src/xmc4/xmc4_irq.c
@@ -143,8 +143,7 @@ static void xmc4_dump_nvic(const char *msg, int irq)
 #endif
 
 /****************************************************************************
- * Name: xmc4_nmi, xmc4_pendsv,
- *       xmc4_dbgmonitor, xmc4_pendsv, xmc4_reserved
+ * Name: xmc4_nmi, xmc4_pendsv, xmc4_pendsv, xmc4_reserved
  *
  * Description:
  *   Handlers for various exceptions.  None are handled and all are fatal
@@ -170,14 +169,6 @@ static int xmc4_pendsv(int irq, void *context, void *arg)
   return 0;
 }
 
-static int xmc4_dbgmonitor(int irq, void *context, void *arg)
-{
-  up_irq_save();
-  _err("PANIC!!! Debug Monitor received\n");
-  PANIC();
-  return 0;
-}
-
 static int xmc4_reserved(int irq, void *context, void *arg)
 {
   up_irq_save();
@@ -393,7 +384,8 @@ void up_irqinitialize(void)
   irq_attach(XMC4_IRQ_BUSFAULT, arm_busfault, NULL);
   irq_attach(XMC4_IRQ_USAGEFAULT, arm_usagefault, NULL);
   irq_attach(XMC4_IRQ_PENDSV, xmc4_pendsv, NULL);
-  irq_attach(XMC4_IRQ_DBGMONITOR, xmc4_dbgmonitor, NULL);
+  arm_enable_dbgmonitor();
+  irq_attach(XMC4_IRQ_DBGMONITOR, arm_dbgmonitor, NULL);
   irq_attach(XMC4_IRQ_RESERVED, xmc4_reserved, NULL);
 #endif
 
diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h
index 2d65bdc86b..2aee23fc8c 100644
--- a/include/nuttx/arch.h
+++ b/include/nuttx/arch.h
@@ -90,6 +90,13 @@
  * Pre-processor definitions
  ****************************************************************************/
 
+#define DEBUGPOINT_NONE          0x00
+#define DEBUGPOINT_WATCHPOINT_RO 0x01
+#define DEBUGPOINT_WATCHPOINT_WO 0x02
+#define DEBUGPOINT_WATCHPOINT_RW 0x03
+#define DEBUGPOINT_BREAKPOINT    0x04
+#define DEBUGPOINT_STEPPOINT     0x05
+
 /****************************************************************************
  * Public Types
  ****************************************************************************/
@@ -97,6 +104,8 @@
 typedef CODE void (*sig_deliver_t)(FAR struct tcb_s *tcb);
 typedef CODE void (*phy_enable_t)(bool enable);
 typedef CODE void (*initializer_t)(void);
+typedef CODE void (*debug_callback_t)(int type, FAR void *addr, size_t size,
+                                      FAR void *arg);
 
 /****************************************************************************
  * Public Data
@@ -2829,6 +2838,60 @@ bool up_fpucmp(FAR const void *saveregs1, FAR const void *saveregs2);
 #define up_fpucmp(r1, r2) (true)
 #endif
 
+#ifdef CONFIG_ARCH_HAVE_DEBUG
+
+/****************************************************************************
+ * Name: up_debugpoint
+ *
+ * Description:
+ *   Add a debugpoint.
+ *
+ * Input Parameters:
+ *   type     - The debugpoint type. optional value:
+ *              DEBUGPOINT_WATCHPOINT_RO - Read only watchpoint.
+ *              DEBUGPOINT_WATCHPOINT_WO - Write only watchpoint.
+ *              DEBUGPOINT_WATCHPOINT_RW - Read and write watchpoint.
+ *              DEBUGPOINT_BREAKPOINT    - Breakpoint.
+ *              DEBUGPOINT_STEPPOINT     - Single step.
+ *   addr     - The address to be debugged.
+ *   size     - The watchpoint size. only for watchpoint.
+ *   callback - The callback function when debugpoint triggered.
+ *              if NULL, the debugpoint will be removed.
+ *   arg      - The argument of callback function.
+ *
+ * Returned Value:
+ *  Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+int up_debugpoint_add(int type, FAR void *addr, size_t size,
+                      debug_callback_t callback, FAR void *arg);
+
+/****************************************************************************
+ * Name: up_debugpoint_remove
+ *
+ * Description:
+ *   Remove a debugpoint.
+ *
+ * Input Parameters:
+ *   type     - The debugpoint type. optional value:
+ *              DEBUGPOINT_WATCHPOINT_RO - Read only watchpoint.
+ *              DEBUGPOINT_WATCHPOINT_WO - Write only watchpoint.
+ *              DEBUGPOINT_WATCHPOINT_RW - Read and write watchpoint.
+ *              DEBUGPOINT_BREAKPOINT    - Breakpoint.
+ *              DEBUGPOINT_STEPPOINT     - Single step.
+ *   addr     - The address to be debugged.
+ *   size     - The watchpoint size. only for watchpoint.
+ *
+ * Returned Value:
+ *  Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+int up_debugpoint_remove(int type, FAR void *addr, size_t size);
+
+#endif
+
 #undef EXTERN
 #if defined(__cplusplus)
 }