2019-01-21 12:59 AM
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
Solved! Go to Solution.
2019-01-21 07:47 AM
I have now done a lot of different experiments and checking and I can surely tell that sometimes my oscilloscope does not trigger a rising edge. I have contacted the manufacturer and hope to find the answer..
2019-01-21 09:35 AM
I should add, that my example is correct only when using full scale of uint16_t - rolling over after 0xFFFF. That's because for uint16_t math the following is true: 1 - 65534 == 3. Do You use other rollover value? Is there a reason for it? Of course code can be made for other rollover values also, but using full unsigned integer scale is the most simple and efficient way.
2019-01-21 09:37 AM
Hey Piranha,
I use 65535 as a roll over Value, so to my beliefs, the max value.
2019-01-22 01:25 AM
I have now checked the program run with a different oscilloscope and the errors are the same. After I have replaced the delay_TIM10(50) function with a while(!HAL_GPIO_ReadPin(_5_PLUS_COIL_GPIO_Port, _5_PLUS_COIL_Pin)); the oscilloscope's diagram looks correct except of the timings:
Approx. 117ms between just two simple register writes seems an awful lot to me. But in manual stepping this program code get's not interrupted by something else.
What Do you guys think could take so long? The HAL function?? I doubt that. The HAL routine looks clean and fast to me.
2019-01-22 02:05 AM
I think I found the error: My delay function seems not to work properly. I tried to put a 500ms delay with delay_TIM10(500). I get an approx. 175ms delay.
I put the defines here again. Maybe I have still done something wrong. Btw my prescaler value is 64000 as for 1ms tick with a APB1/2 timer clock of 64MHz.
void delay_TIM10(uint16_t mcnt) // IMPORTANT!! always check with clock speed for correct delays in STM32CubeMX
{
uint16_t start = TIM10->CNT;
while((uint16_t)(tim10_tick() - start) < mcnt);
}
#define tim10_tick() (uint16_t)(TIM10->CNT)
2019-01-22 02:56 AM
If your SysTick is configured to tick every millisecond then just use its counter for millisecond delays:
void ms_delay(uint32_t ms)
{
volatile uint32_t discard32 = SysTick->CTRL;
(void) discard32;
while (ms) {
if (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) {
ms--;
}
}
}
Or if you must use general purpose timers then use their interrupts. I.e. declare a global volatile uint32_t variable, in the timer overflow interrupt check if it's not zero then decrease it. When you want a delay just set the variable to some value and wait until it becomes zero.
2019-01-22 03:58 AM
Off course I could do that, but this doesn't explain why the delay function is not working properly and why the HAL_GPIO_ReadPin(..) API takes 117ms to process with a 64MHz MCLK
2019-01-22 04:20 AM
It's hard to tell.. It's a simple function, it just can't take that long to execute.
When you are sure that the delay function is correct, we could try to use __DMB() memory barrier between the IO operations.
Not that important, but why are you mixing CMSIS level code (i.e. manipulating BSRR manually) with HAL functions (i.e. calling HAL_GPIO_ReadPin)? Maybe it's OK. It's just I thought you are not using HAL, otherwise I would not suggest writing a new millisecond delay function, as you can use HAL's delay function instead.
2019-01-22 05:01 AM
For the output settings I allways wanted to have zero latency, so I used the direct register writes. Generally I like HAL as it eases development and spares time, especially when handling peripherals together wiht DMA.
The problme is, I am not sure if the function is correct. I tried to use SWV to check how long the code execution of the HAL_GPIO_READ() function takes. What makes me suspicious that there is something really really wrong is that I permanently get exception errors on ovrflow on the SWV Exception Trace. And even if I only use ITM port 31 I get thousands of reports of not received timestamps for different ITM ports I did not activate in the settings. And Sync problems. I would guess this means there is something wrong with the core clock not matching the SWV clock. But When I update the SystemCoreClock value with the CMSIS function SystemCoreClockUpdate() it tells me 64MHz..
2019-01-22 06:05 AM
I must say I am really desperate :( . I don't understand why my processor is not doing as it should. I tried now several approches:
I tried using the HAL functions towrite to the appropriate output pin:
HAL_GPIO_WritePin(_5_PLUS_COIL_GPIO_Port,_5_PLUS_COIL_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(_5_PLUS_COIL_GPIO_Port,_5_PLUS_COIL_Pin,GPIO_PIN_RESET);
with this program exectution my oscilloscope gets not triggered at all, and I don't understand why. It's a 200MHz oscilloscope with digital probes...
Even if I put in a GPIO read, the oscilloscope gets not triggered:
HAL_GPIO_WritePin(_5_PLUS_COIL_GPIO_Port,_5_PLUS_COIL_Pin,GPIO_PIN_SET);
HAL_GPIO_ReadPin(_5_PLUS_COIL_GPIO_Port, _5_PLUS_COIL_Pin);
HAL_GPIO_WritePin(_5_PLUS_COIL_GPIO_Port,_5_PLUS_COIL_Pin,GPIO_PIN_RESET);
But when I put in the while statement, the oscilloscope triggers:
HAL_GPIO_WritePin(_5_PLUS_COIL_GPIO_Port,_5_PLUS_COIL_Pin,GPIO_PIN_SET);
while(!HAL_GPIO_ReadPin(_5_PLUS_COIL_GPIO_Port, _5_PLUS_COIL_Pin));
HAL_GPIO_WritePin(_5_PLUS_COIL_GPIO_Port,_5_PLUS_COIL_Pin,GPIO_PIN_RESET);
the HIGH duration is approx. 100ms . This makes no sense to me at all if the MCLK is running at 64MHz.
I mean it cannot be that I have to put the __DMB() memory barrier between every IO operation. There has to be something completely messed up :(
I really appreciate some help and guidance here.