-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
us_ticker_read() return a 0xFFFF less value for STM32F103RB. #816
Comments
This issue is related to the 16-bit timer used for the Ticker. |
@bcostm What's the status? |
Same as in June 2015. No solution found on this problem. |
I think leibin2014 found already the reason. The problem is that a 32 bit counter is needed and the implementation to extend the 16 bit counter is wrong. The 16 bit overflow is not handled correctly, it does not increment the high word of the counter. My suggestion: // remove oc_int_part, oc_rem_part declararations
volatile uint32_t SlaveCounter = 0;
volatile uint16_t counterOld = 0;
uint32_t us_ticker_read()
{
uint16_t counter;
if (!us_ticker_inited) us_ticker_init();
counter = TIM_MST->CNT;
if (counter < counterOld) {
SlaveCounter += 0x10000; // timer overflow, increment high word
}
SlaveCounter += (SlaveCounter & 0xFFFF) + counter;
counterOld = counter;
return SlaveCounter;
} I don't have the ARM/Keil toolchain for testing, maybe someone else can try this? |
ok thanks. I have Keil and IAR. I will check this. |
I'm trying also with gcc-arm. And I see already that us_ticker_set_interrupt() needs to be modifyed also. |
sorry, that is too complicated for me at the moment. There is also a dependency on hal_tick.c, function timer_irq_handler(). This tries to handle time spans >65536 µs. |
NUCLEO_F103RB is using a 16-bit timer as a internal ticker but the mBed ticker needs a 32-bit timer implementation, so the upper part of that 32-bit timer is being calculated in software. Software bug has been fixed - Continous HIGH/LOW voltage levels could be observerd for 65ms due to 16-bit timer overflow. Now current value of TIM_MST->CNT is stored in cnt_val and is updated in interrupt context only. This avoids master timer overflow without SlaveCounter update. Change-Id: I09cc262083b66e16affea14c4d2126287519b477
NUCLEO_L053R8 is using a 16 bit timer as a internal ticker but the mBed ticker needs a 32 bit timer, so the upper upart of that timer is being calculated in software. Continous HIGH/LOW voltage levels were observerd for 65ms due to timer overflow, so to narrow down the issue, it was decided to switch to 16 bit values and glue them to get a 32 bit timer. Change-Id: I54a06d5aa0f8ddabd8abc194470845a2509e0c55
Both STM32F0xx and STM32F1xx are using a 16-bit timer as a internal ticker but the mBed ticker needs a 32-bit timer implementation, so the upper part of that 32-bit timer is being calculated in software. Software bug has been fixed where continous HIGH/LOW voltage levels could be observerd for 65ms due to 16-bit timer overflow. Now current value of TIM_MST->CNT is stored in cnt_val and is updated in interrupt context only. This avoids master timer overflow without SlaveCounter update. This fix is only for platforms which already implements a 16-bit timer: F103RB, F070RB, F030R8 Change-Id: I205c70ce155b373c6593ead93ade9ec38993f7f9
This path fixes issue ARMmbed#816. Current value of TIM_MST->CNT is read in interrupt context only. This avoids master timer overflow without SlaveCounter update. Change-Id: Ie7a9bfce76990f85caa84264450d053604af33e5
This path fixes issue ARMmbed#816. Current value of TIM_MST->CNT is read in interrupt context only. This avoids master timer overflow without SlaveCounter update. Change-Id: Iaaf7b9eb33aa8d8992e9354ca5e21bf01ec2413d
This path fixes issue ARMmbed#816. Current value of TIM_MST->CNT is read in interrupt context only. This avoids master timer overflow without SlaveCounter update. Change-Id: I8e2ec02ce7539a4c044c7e3dfe6bedc9fcdf7736
Fix timer #816 issue for STM32F0 and STM32F1
how was this fix tested? A simple ticker test is still not working: #include <mbed.h>
Ticker flipper;
DigitalOut led1(PC_13);
DigitalOut led2(PB_12);
void flip() {
led2 = !led2;
}
int main()
{
flipper.attach_us(&flip, 200); // the address of the function to be attached (flip) and the interval (x microseconds)
// spin in a main loop. flipper will interrupt it to call flip
while(1) {
led1 = !led1;
wait(0.5);
}
} Also led1 does not blink, so the wait() is not working too. |
The fix from BartSX ([NUCLEO_L053R8] Fix issue #816 #1743) worked for me. My current us_ticker.c and hal_tick.c for STM32F103RB are: |
This is a partial revert of 07b841b and currently we are only reverting the STM32F0xx family because new fix will be presented that's why we want to keep, still the original solution only F1xx family (it will be fixed in future). Change-Id: I147065299310c9fea499bf3ced8808a44699a1a1
This fix is a solution for issue ARMmbed#816 when having two separate IRQ handlers in Timers (UPDATE Irq and OutputCompare Irq). The update priority needs to be higher to avoid undefined behaviours. Change-Id: I5ef2c27926167ed22108901cd63586692a5f8f90
This fix is a solution for issue ARMmbed#816 when having two separate IRQ handlers in Timers (UPDATE Irq and OutputCompare Irq). The update priority needs to be higher to avoid undefined behaviours. Change-Id: Ic143ed0f3e4e42ad5f7b95337d8c005b7ec61274
ARM Internal Ref: IOTMORF-301 |
Can we close this issue ? |
I use the following code to simulate a 500us/2000us software PWM on PB_0 :
No problem is found when it run on STM32F100RB, but found a problem when run it on STM32F103RB. I found some 65ms continuous high(1) or low(0) level voltage on PB_0 each about 10 seconds.
After digging into thIS problem, I found this is due to in us_ticker.c of STM32F103RB it uses the same IRQ function for update and compare interrupts. So if us_ticker_read() is called in us_ticker_irq_handler(), and at the same time if a update interrupt happens, the variable SlaveCounter has no chance to increase 1. SlaveCounter will be just updated in the next calling of IRQ function. So the function us_ticker_read() will return a 0xFFFF less value in current IRQ function, then cause the 65ms blank area problem.
If running the previous code is easily to reproduce this problem on STM32F103RB. This problem can't be reproduced on STM32F100R since STM32F100RB uses different IRQ fucntions for update and compare interrupts with different priorities.
I know the cause, but don't have good idea about how to fix it. Could any one help to have a check and help to fix it?
The text was updated successfully, but these errors were encountered: