Controller: STM32F103 Compiler: ARM-MDK 4.14
I have a flow-meter connected to a portpin. I like to count on rising and falling slope. So I initialized this ext. irq to meet these requirements. The software works since a couple of weeks without any problem.
This week I recognized that the optimiziation level is accidentally set to 0. Ok, no problem, I set it to maximum level 3.
After this action the code shrunk significantly - nice!
But my flow-meter gave me values twice as high as usual.
I put some LED-switchings into the isr and could detect that every slope of the flow meter triggers the isr exactly twice.
This is my isr for EXTI Line 14
void IHW_DfmImpulseIsr(void) { COUNT_iCount(COUNT_kDFMBRUEHWASSER); //count on each slope EXTI_ClearITPendingBit(EXTI_Line14); } // IHW_DfmImpulseIsr()
I found an other thread, that the reason might be that the isr-pending-bit is not cleared in time. But where is the casual connetion to optimization level.
And the crucial question, HOW to clear pending-bit correctly? Unfortunately I could not find any commendation neither from KEIL/ARM nor from ST.
if your signal is noisy it is VERY possible that the slow code does not pick up the spike, but the fast code does. Have a look with a GOOD scope. I do not know, but maybe a slow rise/fall time could cause the same, a VERY slow could.
Erik
> if your signal is noisy No, the signal is nearly perfect. No noise, good slopes and slow (approx. 40ms high 15ms low in worst case).
I guess that if you reverse these two both versions will "double" COUNT_iCount(COUNT_kDFMBRUEHWASSER); //count on each slope EXTI_ClearITPendingBit(EXTI_Line14);
did you use a GOOD scope (min ability 3* uC clock speed) did you look with a horizontal sweep of 25nS/cm or better (if 72 MHz clock)
I hope this will reflect the preview and thuis be understandable
repeating the post above:
I guess that if you reverse these two both versions will "double"
COUNT_iCount(COUNT_kDFMBRUEHWASSER); //count on each slope EXTI_ClearITPendingBit(EXTI_Line14);
> did you use a GOOD scope
1. LeCroy waveSurfer 424 (200 MHz, 2 GS/s, bandwidth limiter = OFF)
2. I stimulate the port with a digital pulse generator (slope < 5us)
I am almost shure that the problem in not based on bad signal shape. The isr is EXACTLY triggered twice on both edges. No accidentally events.
.
Clear the interrupt flag as early as possible in your ISR. That way you increase your chance of the interrupt flag actually having been cleared before leaving the ISR. Otherwise you might catch the same interrupt again, which explains the "twice as high" values. To be on the safe side you might also want to consider inserting a synchronization barrier (DSB) before leaving the ISR to ensure that memory accesses are guaranteed to have completed.
Hope this helps, Marcus http://www.doulos.com/arm
Did you mean the below thread? http://www.keil.com/forum/18951/
My guess about where is the casual connetion to optimization level: When the optimization level is low, the instructions are more, so the processor has more time to clear the flag. When the optimization level is high, the instructions are less, so the processor has less time to clear the flag, then it misses to clear the flag.
> Did you mean the below thread? > http://www.keil.com/forum/18951/ Yepp. But finally I do not understand what's exactly happening here. And I don't like code I do not understand, not in essential functions.
> synchronization barrier (DSB) This seems to be an interesting topic to get involved with. The whole behaviour is new for me haven't even heard about DSB. So I think I have to comb through the documentation once again. Thanks, helpful hint.
> did you try the line reversal Yes of course. I tried this before I opended this thread. But the question was not how to solve my problem for this specific isr. I am looking for the reason whats going on to avoid this trap for good and all.
Recapitulatory it seems that I have to engage myself with how the write-cycle is handled at Cortex M3 exactly.
Thank you for all answers!
two solutions
1. usage of __DSB()
void IHW_DfmImpulseIsr(void) { COUNT_iCount(COUNT_kDFMBRUEHWASSER); //count on each slope EXTI_ClearITPendingBit(EXTI_Line14); //clear pending bit __DSB(); //make shure, pending bit is cleared before return } // IHW_DfmImpulseIsr()
2. clear pending bit as early as possible
void IHW_DfmImpulseIsr(void) { EXTI_ClearITPendingBit(EXTI_Line14); //clear pending bit COUNT_iCount(COUNT_kDFMBRUEHWASSER); //count on each slope //hope, that pending bit is already cleared :) } // IHW_DfmImpulseIsr()
Both solutions are working correctly on my system (optimization Level 3, -O3). The first one takes approximately 100ns longer (measured).
To be shure never get traped by this one could execute __DSB() at the end of the library function EXTI_CleareITPentdingBit().
My suggestion was actually a combination of both, 1. and 2. That way the execution time should not be affected as badly.
-- Marcus
> To be shure never get traped by this one could execute __DSB() at > the end of the library function EXTI_CleareITPentdingBit().
That would work but remove some of the flexibility. The DSB stalls the processor until pending memory accesses have completed. Without an implicit DSB, you increase the chances that the processor has executed the memory access during COUNT_iCount() so the DSB doesn't have to wait at all.