Skip to main content
Andrew Neil
Super User
December 13, 2017
Solved

Detect Debugger Connected To STM32L0 ?

  • December 13, 2017
  • 5 replies
  • 8398 views

Posted on December 13, 2017 at 17:32

In Cortex-M3, M4, etc, we can just check the DEBUGEN bit in DHCSR (the Debug Halting Control and Status Register)

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0337e/CEGCJAHJ.html

But in Cortex-M0, that register is not accessible to the user code.

:(

So - is there any other way on an STM32L0 to detect when the debugger is connected?

 

#stm32l0 #debug

Best answer by Tesla DeLorean
Posted on December 13, 2017 at 19:31

So digging a bit, BKPT instruction causes a Hard Fault when the debugger is not attached, and this is exploitable

Googling pulled this interesting thread, which has usable information

https://community.nxp.com/thread/424925

5 replies

Uwe Bonnes
Chief
December 13, 2017
Posted on December 13, 2017 at 17:37

Most debug session will set at least DBG_CR_SLEEP

Tesla DeLorean
Guru
December 13, 2017
Posted on December 13, 2017 at 17:57

Arguably a CM0+ r0p1

I would look at the DBGMCU clocks and the bits in the DBG registers at 0x40015800..0x4001580F

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Andrew Neil
Super User
December 13, 2017
Posted on December 13, 2017 at 18:21

Turvey.Clive.002 wrote:

I would look at ... the bits in the DBG registers at 0x40015800..0x4001580F

But those are the bits I'd be looking to set depending on whether the debugger was connected or not!

Something along the lines of:

if( debugger_connected() )

{

   HAL_DBGMCU_EnableDBGStopMode( );

Without that, The ST-Link Utility seems to lose connection during STOP even with 'Enble debug in Low power mode' checked.

But Keil seems fine with it

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
Tesla DeLorean
Guru
December 13, 2017
Posted on December 13, 2017 at 19:56

Yeah, a bit more hackary than I'd like.

It did cause me to rewrite my own handler for the CM0(+)

HardFault_Handler\

                PROC

                EXPORT  HardFault_Handler

                EXTERN  hard_fault_handler_c

                MOV     R1, LR

                LDR     R0, =hard_fault_handler_c

                MOV     LR, R0

                MOVS    R0, &sharp4          ; Determine correct stack

                TST     R0, R1

                MRS     R0, MSP         ; Read MSP (Main)

                BEQ     .+6                ; BEQ 2, MRS R0,PSP 4

                MRS     R0, PSP         ; Read PSP (Process)

                MOV     R1, R4          ; Registers R4-R6, as parameters 2-4 of the function called

                MOV     R2, R5

                MOV     R3, R6          ; 

mailto:sourcer32@gmail.com

                BX      LR

                ENDP

//****************************************************************************

void hard_fault_handler_c(unsigned int * hardfault_args, unsigned int r4, unsigned int r5, unsigned int r6)

{

  printf ('\n[Hard Fault]\n'); // After Joseph Yiu

  printf ('r0 = %08X, r1 = %08X, r2 = %08X, r3 = %08X\n',

    hardfault_args[0], hardfault_args[1], hardfault_args[2], hardfault_args[3]);

  printf ('r4 = %08X, r5 = %08X, r6 = %08X, sp = %08X\n',

    r4, r5, r6, (unsigned int)&hardfault_args[8]);

  printf ('r12= %08X, lr = %08X, pc = %08X, psr= %08X\n',

    hardfault_args[4], hardfault_args[5], hardfault_args[6], hardfault_args[7]);

  printf ('bfar=%08X, cfsr=%08X, hfsr=%08X, dfsr=%08X, afsr=%08X\n',

    *((volatile unsigned int *)(0xE000ED38)),

    *((volatile unsigned int *)(0xE000ED28)),

    *((volatile unsigned int *)(0xE000ED2C)),

    *((volatile unsigned int *)(0xE000ED30)),

    *((volatile unsigned int *)(0xE000ED3C)) );

  while(1);

}

//****************************************************************************

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Thomas Roell
Associate III
December 13, 2017
Posted on December 13, 2017 at 22:06

While I would not dare to question Clive One ...

SWDIO has a pullup on the STM32L0 side. The IDLE state of SWDIO is a logic 0. So one could simply read back SDWIO (in a loop with multiple samples). If there is a 0 detected, then a debugger is driving the line.

N.b. that this should detect the presence of a debugger, not necessarily whether it's active. So after detecting presence, one could use the __BKPT() idea to check whether it's active ....

Andrew Neil
Super User
December 5, 2023

Coming back to this, on an STM32F0, the RCC_APB2ENR_DBGMCUEN bit is set only when a debug session is active.

(not set when no debugger is connected, and also not set when a debugger is physically connected, but no debug session is active)

At least that's the case with STM32CubeIDE v1.13.0 and an ST-Link/V2 ...

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
Associate
June 10, 2024

For STM32H743 this worked for me

 

if(READ_BIT(DBGMCU->CR, DBGMCU_CR_DBG_CKD1EN))

{

// This Code here is only entered when Debugging is active

}

Andrew Neil
Super User
June 10, 2024

@ChrisAtWork wrote:

For STM32H743


But that's not a Cortex-M0.

The point is that higher Cortex-Mx give access to DBGMCU status bits - I know that (see OP) - but that's not available on M0.

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.