M4 core LP TIM5 interrupts: 50% duty cycle?

I've been using my Giga pretty intensively for a year or so now and have noticed that the performance seemed to be lower than it really should be. Recently, while debugging it I put in a 50kHz wave on an input pin and just had an infinite loop match it on an output pin, all on the M4 core.

What I found was that 50% of the time I was getting <1us delay between the input changing and the output matching it. The other 50% of the time it was completely unresponsive. This is happening on a 1ms on, 1ms off cycle.

This set off huge alarm bells for me as my system needs better responsiveness than that. Digging through I found that the culprit is the interrupt for LP_TIM5, Low Power Timer 5. If I disable this right before running my matching function everything runs perfectly. Putting the disable into my setup() function for the M4, however, prevents the M4 from running at all.

So, anybody have any idea what's going on here? I absolutely cannot tolerate a 1ms dead spot on a 50% duty cycle, but what is this doing and should I be concerned leaving it off most of the time?

Hi @nick0001 , can you share the sketch you're using and details of how you are disabling TIM5. Thanks, Steve

I'm disabling the interrupt as so:
NVIC_DisableIRQ(LPTIM5_IRQn ); /*!< LP TIM5 global interrupt */

As for the code, it's quite long, but the debug routine I was using to demonstrate the issue was this:

if (sub_algo == 0xFF){
uint8_t i=1;
int val;
while(i==1){
val = read_pin(EXT1); // Get the value from input pin
set_pin(MIR1, val); // Mirror that back out to an output pin
}
}

M7 uses TIM5 for the us_ticker but M4 uses TIM2. Only thing I can think of using TIM5 on M4 is PWM_5 - are you using pin D5 for anything?

I would try disabling low-powers tickers and see if the problem persists. Changing line 34 of wiring.cpp to #if DEVICE_LPTICKER_NO will force regular tickers.

Also, what is set_pin using? Arduino API, mbed API or direct reg updates?

curious if you guys came up with a a way to disable the us_ticker code. i don't need it and want/need access to TIM2 and TIM5 for my own purposes. when i simply try to override and configure TIM5 for my self everything works from a counting POV but i can't enable the interrupt with out the whole thing hanging. something is blocking this and this leads to a fail when it finally tries to overflow

here is my code on TIM5 for the M7 core. this code hangs because of a problem enabling the interrupt. if i disable that and have it count to a higher number and display CNT periodically via the main loop then i can see it counting correctly at the correct rate. but i can't enable the interrupt for some reason which i believe is related to the us_ticker code

void setupTIM5() {
  RCC->APB1LENR |= RCC_APB1LENR_TIM5EN;  // Enable TIM5 clock
  TIM5->CR1 = 0;                         // Reset control register
  TIM5->PSC = 4;                         // Prescaler set to 5 (PSC + 1)
  TIM5->ARR = 0xFFFFFFFF;                // Max auto-reload value (free-running)
  TIM5->CNT = 0;  // Reset counter
  TIM5->DIER |= TIM_DIER_UIE;  // Enable update interrupt

  // Configure PA4 as Alternate Function (AF2 for TIM5_ETR)
  GPIOA->MODER &= ~(0b11 << (4 * 2));  // Clear mode bits for PA4
  GPIOA->MODER |= (0b10 << (4 * 2));   // Set to Alternate Function mode
  GPIOA->AFR[0] &= ~(0xF << (4 * 4));  // Clear AF selection for PA4
  GPIOA->AFR[0] |= (0x2 << (4 * 4));   // Set AF2 (TIM5_ETR)

  // Configure TIM5 to use external clock mode 1 on ETR (PA4)
  TIM5->SMCR = (7 << TIM_SMCR_SMS_Pos) |  // External Clock Mode 1
               (7 << TIM_SMCR_TS_Pos) |   // Trigger source = ETR (PA4)
               (1 << 12);                 // Set ETR prescaler to divide by 2

  // Ensure ETR is active high
  TIM5->SMCR &= ~(1 << 15);  // Clear ETP bit to select active high

  TIM5->ARR = 999999;  // Set rollover to 1,000,000 counts
  TIM5->CR1 |= TIM_CR1_ARPE;

  //TIM5->EGR = TIM_EGR_UG;  // Manually trigger an update event
  TIM5->CR1 |= TIM_CR1_CEN;  // Enable the counter
  NVIC_EnableIRQ(TIM5_IRQn);  // Enable TIM5 interrupt in NVIC
}

extern "C" void TIM5_IRQHandler(void) {
  if (TIM5->SR & TIM_SR_UIF) {
    TIM5->SR &= ~TIM_SR_UIF;
    secondsCounter++;
    topSec = 1;
  }
}

Hi @jkobhome , you could try switching the us_tickers from TIM2 / TIM5 to TIM3 / TIM4 by hacking this ArduinoCore-mbed/cores/arduino/mbed/targets/TARGET_STM/TARGET_STM32H7/us_ticker_data.h at main · arduino/ArduinoCore-mbed · GitHub. Not sure if this would need a libmbed.a rebuild but instinct says it will