1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

cpu: stm32f1: timer: fix race when combining two 16bit timer values

This commit is contained in:
Kaspar Schleiser 2015-09-05 01:18:36 +02:00
parent 383ada9349
commit efbd5518f6

View File

@ -220,16 +220,33 @@ int timer_clear(tim_t dev, int channel)
unsigned int timer_read(tim_t dev)
{
unsigned a, b;
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
return (((unsigned int)(0xffff & TIMER_0_DEV_0->CNT)) | (TIMER_0_DEV_1->CNT<<16));
break;
/* do OR'ing two times and only use value if results are equal.
* otherwise, the lower 16bit counter could overflow while the
* upper counter is read, leading to an incorrect result. */
do {
a = (((unsigned int)(0xffff & TIMER_0_DEV_0->CNT)) |
(TIMER_0_DEV_1->CNT<<16));
b = (((unsigned int)(0xffff & TIMER_0_DEV_0->CNT)) |
(TIMER_0_DEV_1->CNT<<16));
} while (a!=b);
return a;
#endif
#if TIMER_1_EN
case TIMER_1:
return (((unsigned int)(0xffff & TIMER_1_DEV_0->CNT)) | (TIMER_1_DEV_1->CNT<<16));
break;
/* see above about why loop is needed */
do {
a = (((unsigned int)(0xffff & TIMER_1_DEV_0->CNT)) |
(TIMER_1_DEV_1->CNT<<16));
b = (((unsigned int)(0xffff & TIMER_1_DEV_0->CNT)) |
(TIMER_1_DEV_1->CNT<<16));
} while (a!=b);
return a;
#endif
case TIMER_UNDEFINED:
default: