tinygo.org/x/drivers@v0.27.1-0.20240509133757-7dbca2a54349/delay/sleep.go (about) 1 package delay 2 3 import ( 4 "machine" 5 "time" 6 ) 7 8 /* 9 #include <stdint.h> 10 #include <stdbool.h> 11 bool tinygo_drivers_sleep(uint32_t ticks); 12 */ 13 import "C" 14 15 // Sleep for a very precise short duration by busy-waiting for the given time. 16 // This is not an efficient way to sleep: it will needlessly burn cycles while 17 // sleeping. But it is useful for sleeping for a very short duration, for 18 // example for bit-banged protocols. 19 // 20 // Longer durations (longer than a few milliseconds) will be handled by calling 21 // time.Sleep instead. 22 // 23 // This function should be called with a constant duration value, in which case 24 // the call will typically be fully inlined and only take up around nine 25 // instructions for the entire loop. 26 // 27 //go:inline 28 func Sleep(duration time.Duration) { 29 if time.Duration(uint32(duration)&0xff_ffff) != duration { 30 // This is a long duration (more than 16ms) which shouldn't be done by 31 // busy-waiting. 32 time.Sleep(duration) 33 return 34 } 35 36 // Calculate the number of cycles we should sleep: 37 // cycles = duration * freq / 1e9 38 // Avoiding a 64-bit division: 39 // cycles = duration * (freq/1000_000) / 1000 40 // 41 // This assumes: 42 // * The CPU frequency is a constant and can trivially be 43 // const-propagated, therefore the divide by 1000_000 is done at compile 44 // time. 45 // * The CPU frequency is a multiple of 1000_000, which is true for most 46 // chips (examples: 16MHz, 48MHz, 120MHz, etc). 47 // * The division by 1000 can be done efficiently (Cortex-M3 and up), or 48 // can be fully const-propagated. 49 // * The CPU frequency is lower than 256MHz. If it is higher, long sleep 50 // times (1-16ms) may not work correctly. 51 cycles := uint32(duration) * (machine.CPUFrequency() / 1000_000) / 1000 52 slept := C.tinygo_drivers_sleep(C.uint32_t(cycles)) 53 if !slept { 54 // Fallback for platforms without inline assembly support. 55 time.Sleep(duration) 56 } 57 }