diff options
author | Damien George <damien.p.george@gmail.com> | 2014-11-30 21:23:25 +0000 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2014-11-30 21:23:25 +0000 |
commit | 1960475ed7e190bcf537f8f7714a543b7513e2d5 (patch) | |
tree | 63399c90530b3e5d517a0ce1c2e6bc625c529698 /stmhal/systick.c | |
parent | c7ca01ad962e70a7ecc3beb4feb41da47a372309 (diff) | |
download | micropython-1960475ed7e190bcf537f8f7714a543b7513e2d5.tar.gz micropython-1960475ed7e190bcf537f8f7714a543b7513e2d5.zip |
stmhal: Make pyb.[u]delay use systick with IRQs, busy loop otherwise.
pyb.delay and pyb.udelay now use systick if IRQs are enabled, otherwise
they use a busy loop. Thus they work correctly when IRQs are disabled.
The busy loop is computed from the current CPU frequency, so works no
matter the CPU frequency.
Diffstat (limited to 'stmhal/systick.c')
-rw-r--r-- | stmhal/systick.c | 39 |
1 files changed, 33 insertions, 6 deletions
diff --git a/stmhal/systick.c b/stmhal/systick.c index b4dd68ffec..fc462943f8 100644 --- a/stmhal/systick.c +++ b/stmhal/systick.c @@ -36,12 +36,39 @@ // We provide our own version of HAL_Delay that calls __WFI while waiting, in // order to reduce power consumption. void HAL_Delay(uint32_t Delay) { - extern __IO uint32_t uwTick; - uint32_t start = uwTick; - // Wraparound of tick is taken care of by 2's complement arithmetic. - while (uwTick - start < Delay) { - // Enter sleep mode, waiting for (at least) the SysTick interrupt. - __WFI(); + if (query_irq() == IRQ_STATE_ENABLED) { + // IRQs enabled, so can use systick counter to do the delay + extern __IO uint32_t uwTick; + uint32_t start = uwTick; + // Wraparound of tick is taken care of by 2's complement arithmetic. + while (uwTick - start < Delay) { + // Enter sleep mode, waiting for (at least) the SysTick interrupt. + __WFI(); + } + } else { + // IRQs disabled, so need to use a busy loop for the delay. + // To prevent possible overflow of the counter we use a double loop. + const uint32_t count_1ms = HAL_RCC_GetSysClockFreq() / 4000; + for (int i = 0; i < Delay; i++) { + for (uint32_t count = 0; ++count <= count_1ms;) { + } + } + } +} + +// delay for given number of microseconds +void sys_tick_udelay(uint32_t usec) { + if (query_irq() == IRQ_STATE_ENABLED) { + // IRQs enabled, so can use systick counter to do the delay + uint32_t start = sys_tick_get_microseconds(); + while (sys_tick_get_microseconds() - start < usec) { + } + } else { + // IRQs disabled, so need to use a busy loop for the delay + // sys freq is always a multiple of 2MHz, so division here won't lose precision + const uint32_t ucount = HAL_RCC_GetSysClockFreq() / 2000000 * usec / 2; + for (uint32_t count = 0; ++count <= ucount;) { + } } } |