From 35f8b082a7ad96750b95433a95439b89fae362d3 Mon Sep 17 00:00:00 2001 From: Ludovic Vanasse Date: Sat, 12 Oct 2024 01:34:23 -0400 Subject: [PATCH] Doc: Migrate debugging/flashing NuttX with hw debugger Migrate debugging/flashing NuttX with hw debbuger documentation from Confluence to official documentation Signed-off-by: Ludovic Vanasse --- .../guides/debuggingflash_nuttxonarm.rst | 111 ++++++++++++++++++ Documentation/guides/index.rst | 1 + 2 files changed, 112 insertions(+) create mode 100644 Documentation/guides/debuggingflash_nuttxonarm.rst diff --git a/Documentation/guides/debuggingflash_nuttxonarm.rst b/Documentation/guides/debuggingflash_nuttxonarm.rst new file mode 100644 index 0000000000..bada9f61a6 --- /dev/null +++ b/Documentation/guides/debuggingflash_nuttxonarm.rst @@ -0,0 +1,111 @@ +=================================================================== +Debugging / flashing NuttX on ARM with hardware debugger (JTAG/SWD) +=================================================================== + +.. warning:: + Migrated from: + https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=139629444 + + +NOTE: If you experience the issues described on this page, you can enable the +configuration option below to resolve it. + +.. code-block:: makefile + + CONFIG_STM32_DISABLE_IDLE_SLEEP_DURING_DEBUG=y + +What's the problem? +------------------- + +On some architectures (like ARM Cortex-M3) Idle thread causes the core to stop +using WFI (Wait For Interrupt) assembly instruction. This effectively stops +clocking of the core, which is resumed only by some enabled interrupt. This +causes hardware debuggers to believe that they were disconnected from the +target, as they lose connection with the now stopped core. For example OpenOCD +shows errors like these the moment you start the target: + +.. code-block:: console + + Error: jtag status contains invalid mode value - communication failure + Polling target failed, GDB will be halted. Polling again in 100ms + Error: jtag status contains invalid mode value - communication failure + Polling target failed, GDB will be halted. Polling again in 300ms + Error: jtag status contains invalid mode value - communication failure + Polling target failed, GDB will be halted. Polling again in 700ms + Error: jtag status contains invalid mode value - communication failure + Polling target failed, GDB will be halted. Polling again in 1500ms + Error: jtag status contains invalid mode value - communication failure + Polling target failed, GDB will be halted. Polling again in 3100ms + Error: jtag status contains invalid mode value - communication failure + Polling target failed, GDB will be halted. Polling again in 6300ms + Error: jtag status contains invalid mode value - communication failure + Polling target failed, GDB will be halted. Polling again in 6300ms + + +This makes debugging the code impossible and flashing the chip is much harder - +you have to connect to the chip at the right moment (when it's not disabled +due to WFI) - the chances of doing that are inverse proportional to the load +of your system (if your chip spends 99% of time in Idle mode, you have 1% +chance of connecting and halting it). + +Solution +-------- + +Some ARM cores that support disabling of clocking after WFI instruction have +special configuration options to make debugging possible. One example is STM32 +family - with it's ``DBGMCU->CR`` register it's possible to keep the core +clocked during power-down modes. If your chip supports such configuration you +should put it in some early stage of initialization, like in +``stm32_boardinitialize()`` function. The following code demonstrates the +change for STM32: + +.. code-block:: c + + uint32_t cr = getreg32(STM32_DBGMCU_CR); + cr |= DBGMCU_CR_STANDBY | DBGMCU_CR_STOP | DBGMCU_CR_SLEEP; + putreg32(cr, STM32_DBGMCU_CR); + +If your chip doesn't provide such options there is no other way than not using +WFI instruction in up_idle() function. + +It should be noted that such modification should be done only for development +stage, as keeping the core clocked during power-down modes contradicts the +major purpose of using them - reducing power usage. + +In rare cases that you still have problems with connecting to the target +(especially after power cycle), you should try connecting and halting the chip +under reset (this is supported by new versions of OpenOCD), by holding the +reset button while starting OpenOCD or by configuring OpenOCD to do that for +you. + +Work-around +^^^^^^^^^^^ + +If you keep the RESET button pressed and run OpenOCD command to connected to +it, then it will connect sucessful. After connecting you need to keep the +reset button pressed until you open the telnet connection +(telnet 127.0.0.1 4444) and execute "reset halt": + +.. code-block:: console + + > reset halt + timed out while waiting for target halted + TARGET: stm32f1x.cpu - Not halted + + in procedure 'reset' + target state: halted + target halted due to debug-request, current mode: Thread + xPSR: 0x01000000 pc: 0x080003d0 msp: 0x20001278 + +Then release the RESET boot and it will reset correctly. + +This work-around was tested on viewtool-stm32f107 board and bypassed the above +error reported by OpenOCD. The SWD programmer was a STLink-V2 and this was +the command to connect: + +.. code-block:: console + + openocd -f interface/stlink-v2.cfg -f target/stm32f1x_stlink.cfg + +The OpenOCD version used was: Open On-Chip Debugger 0.8.0-dev-00307-g215c41c +(git commit 215c41c) diff --git a/Documentation/guides/index.rst b/Documentation/guides/index.rst index 7a40208b91..45121672ea 100644 --- a/Documentation/guides/index.rst +++ b/Documentation/guides/index.rst @@ -35,3 +35,4 @@ Guides etcromfs.rst thread_local_storage.rst devicetree.rst + debuggingflash_nuttxonarm.rst