mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-07-26 10:38:41 +00:00
715c33d4b0
For details, see: https://github.com/tinygo-org/tinygo/pull/3927 This change just means we need to be more careful to use the right type, now that types like C.uint32_t don't match to the Go equivalent (like uint32).
58 lines
1.9 KiB
Go
58 lines
1.9 KiB
Go
package delay
|
|
|
|
import (
|
|
"machine"
|
|
"time"
|
|
)
|
|
|
|
/*
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
bool tinygo_drivers_sleep(uint32_t ticks);
|
|
*/
|
|
import "C"
|
|
|
|
// Sleep for a very precise short duration by busy-waiting for the given time.
|
|
// This is not an efficient way to sleep: it will needlessly burn cycles while
|
|
// sleeping. But it is useful for sleeping for a very short duration, for
|
|
// example for bit-banged protocols.
|
|
//
|
|
// Longer durations (longer than a few milliseconds) will be handled by calling
|
|
// time.Sleep instead.
|
|
//
|
|
// This function should be called with a constant duration value, in which case
|
|
// the call will typically be fully inlined and only take up around nine
|
|
// instructions for the entire loop.
|
|
//
|
|
//go:inline
|
|
func Sleep(duration time.Duration) {
|
|
if time.Duration(uint32(duration)&0xff_ffff) != duration {
|
|
// This is a long duration (more than 16ms) which shouldn't be done by
|
|
// busy-waiting.
|
|
time.Sleep(duration)
|
|
return
|
|
}
|
|
|
|
// Calculate the number of cycles we should sleep:
|
|
// cycles = duration * freq / 1e9
|
|
// Avoiding a 64-bit division:
|
|
// cycles = duration * (freq/1000_000) / 1000
|
|
//
|
|
// This assumes:
|
|
// * The CPU frequency is a constant and can trivially be
|
|
// const-propagated, therefore the divide by 1000_000 is done at compile
|
|
// time.
|
|
// * The CPU frequency is a multiple of 1000_000, which is true for most
|
|
// chips (examples: 16MHz, 48MHz, 120MHz, etc).
|
|
// * The division by 1000 can be done efficiently (Cortex-M3 and up), or
|
|
// can be fully const-propagated.
|
|
// * The CPU frequency is lower than 256MHz. If it is higher, long sleep
|
|
// times (1-16ms) may not work correctly.
|
|
cycles := uint32(duration) * (machine.CPUFrequency() / 1000_000) / 1000
|
|
slept := C.tinygo_drivers_sleep(C.uint32_t(cycles))
|
|
if !slept {
|
|
// Fallback for platforms without inline assembly support.
|
|
time.Sleep(duration)
|
|
}
|
|
}
|