mjdietz2 gravatar image

Posted 2016-03-15 11:36:25 +0200

blogs->nordicers

Monitor Mode Debugging - Revolutionize the way you debug BLE applications

Motivation

Monitor Mode Debugging solves the biggest problem when debugging nRF5 devices. It allows BLE applications to be debugged without crashing after setting breakpoints/pausing execution, and is an order of magnitude better than the default 'halt mode' debugging in these situations. The IDE does not notice any difference between halt and monitor mode debug so this will work with whatever IDE you are using (will work in GDB as well). This post will serve as a step by step guide to set up and use Monitor Mode Debugging with each major IDE Nordic supports (Keil, IAR, SEGGER Embedded Studio) and with different BLE examples from Nordic's SDK.

This tutorial should take 20 minutes to work through and by the end of it you will understand what Monitor Mode Debugging is and why you need to be using it. You will also have evaluated it with some BLE examples from our SDK and will have the knowledge to integrate it into your existing project in a few minutes.

  • Keil: BLE Blinky example (experimental_ble_app_blinky).
  • IAR: BLE UART example (ble_app_uart).
  • SEGGER Embedded Studio: BLE Heart Rate example (ble_app_hrs).

Background

In general there are two standard debug modes available for CPUs: Halt Mode (default) and Monitor Mode. In halt mode the CPU is halted and stops program execution when a breakpoint is hit or the debugger issues a halt request - this means peripheral interrupts can only become pending but not taken as this would require execution of their interrupt handlers. As many of you have noticed this causes problems when debugging BLE applications! Certain interrupts need to be serviced to maintain the BLE connection and when the CPU is halted in halt mode debugging this breaks down.

This is where monitor mode debugging saves the day! In monitor mode debugging the CPU is not halted but takes a specific debug exception and jumps into a defined exception handler that executes in a loop. The main effect is the same as halt mode, except now any interrupts with a higher priority than our DebugMonitor_IRQ will continue to be serviced while our CPU is halted. The CPU can also perform some specific operations on debug entry/exit or even periodically during debug mode with almost no delay. We can now effectively debug BLE applications!

Requirements

Monitor Mode debugging will only work on nRF52 series devices because it requires the Debug Monitor exception that is available on Cortex-M4 CPUs.

Very Important: Monitor Mode Debugging relies on the Debug Monitor exception. The SoftDevice your application uses needs to forward this exception to your application! s132_nrf52_2.0.0-7.alpha_softdevice.hex (released mid December 2015) and later do this properly, but prior versions of the s132 SoftDevice did not do this!

Also Very Important: Your application's startup files must define the DebugMon interrupt handler. Old '*_startup_nrf52.s' files are missing the DebugMon interrupt handler. Either download the most recent nRF5x-MDK for your specific IDE here: http://www.nordicsemi.com/eng/Products/Bluetooth-Smart-Bluetooth-low-energy/nRF52832, or add the DebugMon interrupt handler to your application's startup file manually. Attached are the startup files JLink_Monitor_Startup_Files.zip for each IDE that have the DebugMon interrupt handler added to them and are working with Monitor Mode Debugging. Feel free to use them or check your startup files against them.

NOTE: Nordic's startup files define the Debug Monitor handler as DebugMonitor_Handler, while JLink defines it as DebugMon_Handler. You will need to make these consistent by either changing all occurrences of DebugMonitor_Handler to DebugMon_Handler in your startup file or vice versa in the JLINK_MONITOR_ISR_xxx.s file.

Setting up Monitor Mode Debugging

At this point you have downloaded the latest J-Link Software and the J-Link monitor code, checked that your application uses a 'recent enough' SoftDevice, and checked that your application's startup file declares and forwards the DebugMon_Handler.

The following steps are common to all IDEs:

  1. Add the JLINK_MONITOR_ISR_xxx.s file to your project. You will select this file based on the IDE you are using (this file is not to be modified).
  2. Add the JLINK_MONITOR.c file to your project and the path of JLINK_MONITOR.h to your include paths (these files may be modified to define the entry/exit/polling functions declared in them if you want to use these features of Monitor Mode Debugging).
  3. In main.c at the top of your project's main() function add this line of code:

NVIC_SetPriority(DebugMonitor_IRQn, 7ul);

This sets the Debug Monitor exception to the lowest possible priority for nRF52 devices so that any interrupts with a higher priority will be serviced when our CPU is halted.

All we have to do now is enable Monitor Mode Debugging in our J-Link software! This is the only step that varies with your IDE as each IDE has a different way of telling the J-Link software that we will be debugging in monitor mode. The two J-Link commands we must send are:

SetMonModeDebug = 1

SetMonModeVTableAddr = ADDR // ADDR is where your application's vector table is located in FLASH. This corresponds to the start address for your application, probably either 0x1B000 or 0x1C000 depending on your SoftDevice.

Keil

You will need to modify the J-Link settings file 'JLinkSettings.ini' that is created on the start of the first debug session with a specific project. Navigate to your Keil project's directory and edit this file with a text editor adding the following lines to the [CPU] section (see screenshot below).

image description

IAR

You will need to use the macro file attached, EnableMonMode.mac. Specify the use of this macro file in 'Options-> Debugger' (see screenshot below).

image description

SEGGER Embedded Studio

You will need to add the following commands to 'Project Properties -> Debugger -> J-Link Options -> Execute J-Link Commands On Connect' (see screenshot below).

image description

Debugging in Monitor Mode!

That's all it takes to set up Monitor Mode Debugging in any project! Now lets experiment with it. Flash the SoftDevice and Application to your nRF52 device and enter debugging. At some point during this process you should see this popup:

image description

It is very important you see this box and select 'Yes' or else Monitor Mode Debugging will not be enabled. If you don't see this box it means the J-Link commands to enable Monitor Mode Debugging aren't being sent/received properly. Also take note of SEGGER's licencing terms to use this feature.

Important: In the upper left corner of this popup verify that your J-Link software version is v5.10t or greater!

Now run your BLE application. It should start advertising as normal. Connect to it with Master Control Panel or the application of your choice. See that the blinky, heart rate or uart example behaves as expected at this point.

Now either halt the CPU or set a breakpoint to halt the CPU. Notice that you don't lose the connection! For the blinky example you should be able to blink the LED from your app or notice when button 1 is pushed. For the heart rate example you will continue receiving heart rate notifications. And for the uart example you can send and receive strings from the terminal. All while the CPU is halted! Now run the CPU again and everything continues to behave as expected - no crashes or lost state! Mess around with this for a bit and see how powerful this debugging features is.

Future

Please comment with any questions/suggestions/concerns below! For more information on Monitor Mode Debugging please see the J-Link User Guide in 'C:\Program Files (x86)\SEGGER\JLink_V510t\Doc\Manuals.' Chapter 8 is dedicated to Monitor Mode Debugging and is a quick read!

9 comments

leonwj gravatar image

Posted March 16, 2016, 12:06 a.m.

Hi Michael,

Thanks for the blog post, still finding things ending up in hard-fault'ville (experimental_ble_app_blinky - IEWARM & Keil uVision) even after trying the workaround(s) that you included for the CONFIG_GPIO_AS_PINRESET define. We'll work through the issue and comment back with any findings. Thus far we've tried the experimental ble blinky app under the following environment combinations with all hard-faulting.

IDE(s):

    IAR EWARM 7.50.2
    Keil  v5.17.0

Softdevice(s):

   s132_nrf52_2.0.0_softdevice.hex [id: 0x0081]         (nRF5-sdk-v110089a)      *VTableAddr = 0x1c000
   s132_nrf52_2.0.0-7.alpha_softdevice.hex [id: 0x0079] (nRF52-sdk-v11002-alpha) *VTableAddr = 0x1b000

JLink(s):

    JLinkARM.dll (JLink_V510r)
    JLinkARM.dll (JLink_V510t)

nRF52 DevKit(s):

    PCA10040 v1.1.0 (Rev. 1 nRF52832)
    PCA10040 v0.9.0 (Eng. B nRF52832)

As an aside, just a quick comment on the specifics of enabling MMD on the different IDEs... It should be noted that its possible to cut out the need for the IDE specific setup of MMD by executing the following commands at the J-Link Control Panel (prior to debug step through):

exec SetMonModeDebug = 1
exec SetMonModeVTableAddr = <Address>   ; <Address> = [0x1c000 | 0x1b000]

mmd-j-link-console.png

Regards

mjdietz2 gravatar image

Posted March 16, 2016, 9:18 a.m.

Hi leon,

Everything above looks correct. I've tested and had success with pretty much the same versions of everything you listed above.

A couple guesses at what could be wrong:

1.) In Nordic's official nRF52 startup files we defined the Debug Monitor Exception Handler as

DebugMonitor_Handler

while in JLINK_MONITOR_ISR_xxx.s it is defined as

DebugMon_Handler

These need to be consistent with each other. (I changed all instances of DebugMonitor_Handler to DebugMon_Handler in Nordic's startup file - there are 3).

2.) Make sure you are seeing the J-Link 'Monitor mode missing licence' popup window as a screen shot in the post shows. You should see this every time you enter debugging and this will verify that monitor mode debug is being properly enabled (note I have had problems - although I haven't looked into them deeply - enabling monitor mode debugging from the JLink commander as you describe above. I've been sending from the IDE as detailed in the post).

3.) I recommend just removing CONFIG_GPIO_AS_PINRESET from your definitions for now and make sure that isn't causing any problems. Then once we get everything working either add it back and follow the workaround or just leave it out while you are developing and add back once us and SEGGER have fixed the problem.

4.) Since you have an IAR licence I recommend doing all this trouble shooting there. I've had a lot more trouble with this in Keil than IAR or Embedded Studio. (I've had trouble loading flashing the application from Keil when monitor mode debug is enabled and have used nrfjprog to flash the application instead and then enter debugging from Keil without loading the application).

Other than that all I can think of is to make sure you remembered:

NVIC_SetPriority(DebugMonitor_IRQn, 7ul);

If you are still hardfaulting after double checking all of this please let me know where its occuring.

-Mike

leonwj gravatar image

Posted March 17, 2016, 8:44 a.m.

Hi Mike,

Thanks for your feedback...

We had both 1) and 2) in place already so eliminated those as possible issues; and we also had the call to NVIC_SetPriority(DebugMonitor_IRQn, 7ul); and the CONFIG_GPIO_AS_PINRESET define so chose to leave those in.

To troubleshoot further we implemented a generic HardFault_Handler to give us access to the SCB values via RTT and managed to glean the following:

 0>  sd_ble_enable: RAM START at 0x20001FE8
 0>  
 0>  [Generic ARM Cortex M4 - HardFault_Handler Address(es)]
 0>  R0 = 0x20003354
 0>  R1 = 0x20003290
 0>  R2 = 0x00000001
 0>  R3 = 0x40020518
 0>  R12 = 0x00000000
 0>  LR [R14] = 0x1E5C3  <Subroutine Call Return Address>
 0>  PC [R15] = 0x1E572  <Program Counter>
 0>  PSR = 0x01000026
 0>  BFAR = N/A
 0>  CFSR = 0x00000000
 0>  HFSR = 0x80000000
 0>  DFSR = 0x00000002
 0>  MMFAR = 0x200026AC
 0>  AFSR = 0

Looking further into the HFSR value of 0x80000000 and based upon the description in Cortex-M3 Technical Reference Manual_r1p1 - Page #180 it seemed to suggest that our DebugMonitor interrupt was not able to fire (hard-faulting) due to being lower than the current priority of our code.

arm-cortex-m3-hfsr.png

With this in hand, we amended the DebugMonitor IRQ to be one priority higher i.e. NVIC_SetPriority(DebugMonitor_IRQn, 6ul); and finally managed to get a fully functional MMD setup (under IAR EWARM at least) with the experimental_ble_app_blinky example working as expected and with CONFIG_GPIO_AS_PINRESET defined (however it looks like the workaround to initially set the UICR after erase all is still required).

Given that we can define out MMD in any release code, I'm not aware of any drawbacks in running DebugMonitor at that higher priority (could you please let me have your thoughts on this?)

Regards

jacob gravatar image

Posted Nov. 3, 2016, 3:59 p.m.

Hello, Where can I find the monitor source files for GCC?

Thanks, Jacob

leonwj gravatar image

Posted Nov. 3, 2016, 8:59 p.m.

Hi Jacob,

The guys at Segger have previously indicated that the monitor mode code/files available for SEGGER Embedded Studio should also work with Eclipse-CDT + GCC without any changes.

Regards,

leonwj

gcrisler gravatar image

Posted Nov. 8, 2016, 3:31 p.m.

In SES 3.10f does the monitor mode box still pop up. I don't get any pop up box, however the output box has the this information in it. I seems like my board is reseting, I lose the connection when I hit break points. Any thoughts?

Preparing target for download

J-Link V6.10i -- Monitor Mode missing license The connected J-Link (S/N 682012230) does not have a valid license for the use of monitor mode debugging. J-Link PLUS, ULTRA+ and PRO models come with a built-in license for monitor mode debugging.

Stopped by vector catch Stopped by vector catch Preparing target for user application Executing script TargetInterface.resetAndStop(1000)

muhammadakram.karimi gravatar image

Posted Feb. 14, 2017, 12:02 p.m.

Hello, I followed the steps, Added and Updated the JLINK_MONITOR_ISR_ARM.s file to include DebugMonitor_Handler Added JLINK_MONITOR.c and its respective header (with the path in options)

Added "NVIC_SetPriority(DebugMonitor_IRQn, 7ul);" before main() but I am unable to compile the code:

can you please suggest what can be the possible reason. Here is the error log

..\..\..\main.c(1414): error:  #40: expected an identifier

NVIC_SetPriority(DebugMonitor_IRQn, 7ul); ......\main.c(1414): error: #260-D: explicit type is missing ("int" assumed) NVIC_SetPriority(DebugMonitor_IRQn, 7ul); ......\main.c(1414): error: #92: identifier-list parameters may only be used in a function definition NVIC_SetPriority(DebugMonitor_IRQn, 7ul); ......\main.c(1414): error: #147: declaration is incompatible with "void NVIC_SetPriority(IRQn_Type, uint32_t)" (declared at line 1698 of "C:\Keil_v5\ARM\PACK\ARM\CMSIS\4.5.0\CMSIS\Include\core_cm4.h") NVIC_SetPriority(DebugMonitor_IRQn, 7ul);

muhammadakram.karimi gravatar image

Posted Feb. 14, 2017, 12:06 p.m.

One more thing to add to my previous error; It's also not able to find the assembler file and throws the following error:

JLINK_MONITOR_ISR_ARM.s: error: A1023E: File "..\..\..\..\..\..\..\JLink_Monitor_Code\JLink_Monitor_Code\JLINK_MONITOR_ISR_ARM.s" could not be opened: No such file or directory
muhammadakram.karimi gravatar image

Posted Feb. 14, 2017, 12:09 p.m.

Actually I successfully added the assembler file *.s using --reduce_paths in ASM tab but the above mentioned 4 errors are still there during compilation. Please help...

Sign in to comment.

Related posts by tag