diff --git a/delay-stm32.c b/delay-stm32.c index 6804723..bfb036c 100644 --- a/delay-stm32.c +++ b/delay-stm32.c @@ -5,46 +5,5 @@ #if defined TEACUP_C_INCLUDE && defined __ARM_STM32__ -#include "cmsis-stm32f4xx.h" // For __ASM() and ... - - -/** Delay in microseconds. - - \param delay Time to wait in microseconds. - - Execution times on ARM aren't as predictable as they could be, because - there's a code prefetch engine which can change timings depending on the - position of the code in Flash. We could use the System Tick Timer for this - task, but this timer is probably better used for more important tasks. - delay_us() and delay_ms() are used only rarely and not in a way which would - require high precision. - - Nevertheless, calibrated on the oscilloscope. Measured accuracy: - - delay_us(10) ...(100) ...(1000) ...(10000) ...(65000) - 96 MHz 10.23 us 99.3 us 0.994 ms 9.93 ms 64.5 ms - - CAUTION: this currently works for a 96 MHz clock, only! As other clock rates - appear, there's more math neccessary, see the AVR version. Or simply - a second implementation. -*/ -void delay_us(uint16_t delay) { - - __ASM (".balign 16"); // No gambling with the prefetch engine. - while (delay) { - __ASM volatile ( - " nop \n\t" // One nop before the loop slows about 2%. - " movs r7, #9 \n\t" // One more loop round slows about 20% - "1: nop \n\t" - " sub r7, #1 \n\t" - " cmp r7, #0 \n\t" - " bne 1b \n\t" - : - : - : "r7", "cc" - ); - delay--; - } -} #endif /* defined TEACUP_C_INCLUDE && defined __ARM_STM32__ */ diff --git a/delay-stm32.h b/delay-stm32.h new file mode 100644 index 0000000..6adf11a --- /dev/null +++ b/delay-stm32.h @@ -0,0 +1,36 @@ +#ifndef _DELAY_STM32_H +#define _DELAY_STM32_H + +#include "cmsis-stm32f4xx.h" // For __ASM() and ... + +/** Delay in microseconds. + + \param delay Time to wait in microseconds. + + Execution times on ARM aren't as predictable as they could be, because + there's a code prefetch engine which can change timings depending on the + position of the code in Flash. We could use the System Tick Timer for this + task, but this timer is probably better used for more important tasks. + delay_us() and delay_ms() are used only rarely and not in a way which would + require high precision. +*/ +static void _delay(uint32_t) __attribute__ ((always_inline)); +inline void _delay(uint32_t delay) +{ + + if (delay) + { + __ASM volatile( + "1: subs %0, %0, #1 \n\t" + " bne 1b\n\t" + : "+r"(delay)); + } + else + __ASM volatile("nop \n\t"); +} + +// void _delay(uint32_t delay); +#define TUNER 1 +#define delay_us(delay) (_delay((uint32_t)(((uint64_t)__SYSTEM_CLOCK) * (delay) / 3000000ULL * TUNER))) + +#endif /* _DELAY_STM32_H */ \ No newline at end of file diff --git a/delay.h b/delay.h index 81bb705..8177c56 100644 --- a/delay.h +++ b/delay.h @@ -3,9 +3,14 @@ #include +#ifndef __ARM_STM32__ // microsecond delay, does NOT reset WDT if feature enabled void delay_us(uint16_t delay); +#else +#include "delay-stm32.h" +#endif + // millisecond delay, does reset WDT if feature enabled void delay_ms(uint32_t delay);