2

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?

Arne
  • 1,111
  • 2
  • 11
  • 22
  • IMO it cannot be done as stopping the core should not change state of the uC. Maybe some probes have a pin which signals it - but I do not know. – 0___________ Oct 05 '17 at 00:13

1 Answers1

2

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.