cancel
Showing results for 
Search instead for 
Did you mean: 

MCU runs different in free running than in manual stepping in debug mode

Benjamin Brammer
Senior II

Hey guys,

I have expereinced a very strange behaviour of my STM32F429ZIT6 custom board:

When I execute the following code the processor behaves differently in free running then in manual stepped mode or my oscilloscope seems to be completely broken - which I doubt.

			_5_PLUS_COIL_HIGH;
			delay_TIM10(50);
			STANDARD_COIL_LOW;
			_5_MINUS_COIL_LOW;

the macros behinde _5_PLUS_COIL_HIGH , STANDARD_COIL_LOW and _5_MINUS_COIL_LOW are simply GPIO output state settings:

#define STANDARD_COIL_HIGH										STANDARD_COIL_GPIO_Port->BSRR = STANDARD_COIL_Pin
#define STANDARD_COIL_LOW										STANDARD_COIL_GPIO_Port->BSRR = (STANDARD_COIL_Pin	<< 16U)
#define _5_PLUS_COIL_HIGH										_5_PLUS_COIL_GPIO_Port->BSRR = _5_PLUS_COIL_Pin
#define _5_PLUS_COIL_LOW										_5_PLUS_COIL_GPIO_Port->BSRR = (_5_PLUS_COIL_Pin << 16U)

and the function delay_TIM10(50) is a msec delay function:

#pragma GCC push_options
#pragma GCC optimize ("O3")
 
void delay_TIM7(uint32_t ucnt)		// IMPORTANT!! always check with clock speed for correct delays in STM32CubeMX
{
	uint32_t start = TIM7->CNT;
	while(tim7_tick() - start < ucnt);
}
 
 
void delay_TIM10(uint32_t mcnt)		// IMPORTANT!! always check with clock speed for correct delays in STM32CubeMX
{
	uint32_t start = TIM10->CNT;
	while(tim10_tick() - start < mcnt);
}
 
#pragma GCC pop_options
 
#define tim7_tick()												(TIM7->CNT)
#define tim10_tick()											(TIM10->CNT)

I halt the program per breakpoint at _5_PLUS_COIL_HIGH and trigger my oscilloscope on that pin to check for a rising edge, as the pin is LOW prior. Normally I would just hit run and the socilloscope would get triggered. But for a reason I don't know, the oscilloscope gets not triggered. When I maually step from the breakpoint the oscilloscope gets triggered.

Has anybody a clue why this is the case?

My processor runs only at 68MHz.

best regards

Benjamin

1 ACCEPTED SOLUTION

Accepted Solutions

I finally found the problem:

I used open-drain outputs. Now I switched them to push-pull and everything works fine (the delays and the GPIO switching). I must admit that I not really understand why this was the reason.. I am having a logic buffer connected to these GPIOs, but as far as I thought the buffer just needs a clear HIGH or LOW state as it is a high impedance input. I will look deeper int this.

Anyhow thanks for all the help and effort from different people!

P.S. Off course this could not work, as a logic "1" on an open-drain output is a high impedance state, so floating.

View solution in original post

21 REPLIES 21

Aren't those 16-bit TIM?​

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Benjamin Brammer
Senior II

yes, they are, why?

Apt to make your delay routines malfunction as coded.​

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Could you please point this out to me as I don't understand why. I use these delay functions on different places in my code and so far they have worked right. But this still doesn't explain why stepped debugging behaves differently than free running, does it?

Piranha
Chief II

The delay functions will fail on timer overflow. Correct code for 16-bit timers is:

void delay_TIM10(uint16_t mcnt)
{
	uint16_t start = tim10_tick();
	while((uint16_t)(tim10_tick() - start) < mcnt);
}

Type cast is necessary because of integer promotion.

https://en.cppreference.com/w/c/language/conversion

What are the tick frequencies and are these delay functions executed somehow in parallel? Debugging changes timing and that can expose/hide problems with delay functions failing on overflow.

There can be two possible scenarios for this function to work wrongly.

First is when mctn > 65535 (0xFFFF). The "while" loop will never end. In your case mcnt is 50, so you are safe. To be safer, just change the mcnt's type to uint16_t.

Second, consider what happens when your counter is at 65500 when you are entering into the function. "start" becomes 65500, So when CNT overflows to 0 after 65535 the logic will be flawed.

Ok..please correct me if I misunderstand this, as I try to understand and learn:

my TIM-CNT register depth is 16bit. The variable start was defined by me with uint32_t so the variable gets filled up with zeros. The problem now occurs when I have a wrap around from the timer i.e. lets say the timer should count until value 2600 and I have a start value of 2400 but mcnt is 300. So the timer will wrap around after 200 counts and start from zero but now the while equation is a negative value as 0 -2400 = -2400 in this case the expression tim10_tick() - start would be an int32_t, right? and the while loop would break because -2400 < 300, correct?

but I am not sure what happens with the explicit conversion. Does the processor just treat the -2400 as an unsigend integer? bit this would be much higher than a starting value of 2600 after wrap around. I am a bit confused, I think.

uint32_t is an unsigned type, it can never be negative. 0 - 2400 wraps around and becomes 4294964896 instead of -2400.

Benjamin Brammer
Senior II

Ok, thanks for all the answers and clearification!

I now corrected the code and my oscillsocope gets triggered.. :D

but what is strange is that my scope shows me something different in free running than in stepped mode. in stepped mode I can see that pin _5_PLUS_COIL gets HIGH and after I step through until the end STANDARD_COIL and _5_MINUS_COIL become LOW, as expected with the program code. But in free running mode STANDARD_COIL and _5_MINUS_COIL become LOW prior to _5_PLUS_COIL becomming HIGH. And this takes about 300ms...really strange. Since I have interrupts active that could interrupt this process these might be the problem, but wouldn't I then be stepped to the appropriate ISR with manual stepping?

I was happy too early. When I am in free running mode inside a debug session the oscilloscope again gets not triggered. This is so strange..

Can anyone tell me why the processor is behaving like this? Since I have corrected the delay function, this should not be the cause of this problem, right?

I now seperatily measure the voltage on the pin with a multimeter..it does not become HIGH. so this means for reason I don't know yet the program code gets not executed under free run... I must say I quite don't understand this. since in debugging mode it works and the breakpoint gets triggered, so my software is running inside the apropriate ISR.

OK I will now examine the problem more in detail.