I am using the STM32F7 series of microcontrollers and it would be most helpful to have some GPIO change value (either toggle, pulse, high-z, ...) whenever the core is halted by the debugger attached to the JTAG interface. Is anyone aware of such a feature?
1 Answers
There are the DBGMCU
registers, which can selectively stop certain peripherals (mostly timers) when the core is stopped.
The idea is to somehow make a timer output a low level signal while it's running, and high level when it isn't. A single timer can't do that, but it's possible with two timers in a master-slave configuration.
Configure TIM3
to output a PWM signal with a very high duty cycle, starting low for two cycles, then going high for the rest of it's 65536 cycles long period. Slave it to TIM2
, which runs with a period of 2 cycles, and resets TIM3
on counter overflow. Thus, TIM3
is forced permamently low as long as TIM2
is running, but it will output a 99.997% high PWM signal when TIM2
is stopped. Then TIM2
is configured to stop when the core is halted by the debugger, but TIM3
keeps running.
RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // enable peripheral clocks, that might be different on your board
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN | RCC_APB1ENR_TIM3EN;
// consult your datasheet for the right AF value
GPIOB->AFR[0] = (GPIOB->AFR[0] & ~GPIO_AFRL_AFRL0) | 2; // set PB0 to Alternate Function 2, TIM3
GPIOB->MODER = (GPIOB->MODER & ~GPIO_MODER_MODER0) | GPIO_MODER_MODER0_1; // set PB0 to Alternate Function
DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM2_STOP; // stop TIM2 when core is stopped
DBGMCU->APB1FZ &= ~DBGMCU_APB1_FZ_DBG_TIM3_STOP; // but don't stop TIM3
TIM2->ARR = 1; // master timer period
TIM2->CR2 = TIM_CR2_MMS_1; // master mode selection MMS=010 Update event
TIM2->CR1 = TIM_CR1_CEN; // enable timer 2
TIM3->ARR = 65535; // PWM period
TIM3->CCR3 = 2; // channel 3 PWM duty cycle
TIM3->CCMR2 = TIM_CCMR2_OC3M; // set channel 3 to PWM mode 2
TIM3->CCER = TIM_CCER_CC3E // enable channel 3 compare output
/* | TIM_CCER_CC3P */; // it's possible to invert output polarity
TIM3->SMCR = TIM_SMCR_TS_0 // trigger selection TS=001 ITR1 = TIM2 is master
| TIM_SMCR_SMS_2; // slave mode SMS=100 reset mode
TIM3->CR1 = TIM_CR1_CEN; // enable timer 3
I don't have an F7, it runs on my STM32L151
board that happens to have a LED on PB0, which is TIM3
channel 3. The LED is lighting up nicely when I hit the suspend button in the debugger, the low pulse is not noticeable to the naked eye at all. Apply an external low pass RC filter to make it disappear when it bothers whatever component it's connected to. It might be possible to output a clean signal using the Retriggerable one pulse mode of the advanced timers TIM1
or TIM8
, but I don't have any experience with these.

- 7,779
- 1
- 23
- 39
-
two timers for this task (including the precious 32 bit tim2), That is the overkill. – 0___________ Oct 05 '17 at 18:09
-
It would of course work with any possible master-slave timer pair. – followed Monica to Codidact Oct 05 '17 at 19:43
-
But I do not understand what for? For stopping another micros in the multiprocessor environment jtag has special mechanisms – 0___________ Oct 05 '17 at 19:59
-
Maybe it's some dumb component that that would get too hot, or move too far, when the controller can't monitor it. – followed Monica to Codidact Oct 06 '17 at 05:23
-
It would be possible to use only one timer that permantly toggles a pin and stops toggling when the core is stopped. If static levels are required, this could be accomplished by adding a simple passive capacitive differentiator and a rectifier. – chrisemb Dec 07 '22 at 10:58