github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/runtime/runtime_esp32xx.go (about)

     1  //go:build esp32 || esp32c3
     2  
     3  package runtime
     4  
     5  import (
     6  	"device/esp"
     7  	"machine"
     8  	"unsafe"
     9  )
    10  
    11  type timeUnit int64
    12  
    13  // Initialize .bss: zero-initialized global variables.
    14  // The .data section has already been loaded by the ROM bootloader.
    15  func clearbss() {
    16  	ptr := unsafe.Pointer(&_sbss)
    17  	for ptr != unsafe.Pointer(&_ebss) {
    18  		*(*uint32)(ptr) = 0
    19  		ptr = unsafe.Add(ptr, 4)
    20  	}
    21  }
    22  
    23  func initTimer() {
    24  	// Configure timer 0 in timer group 0, for timekeeping.
    25  	//   EN:       Enable the timer.
    26  	//   INCREASE: Count up every tick (as opposed to counting down).
    27  	//   DIVIDER:  16-bit prescaler, set to 2 for dividing the APB clock by two
    28  	//             (40MHz).
    29  	// esp.TIMG0.T0CONFIG.Set(0 << esp.TIMG_T0CONFIG_T0_EN_Pos)
    30  	esp.TIMG0.T0CONFIG.Set(esp.TIMG_T0CONFIG_EN | esp.TIMG_T0CONFIG_INCREASE | 2<<esp.TIMG_T0CONFIG_DIVIDER_Pos)
    31  	// esp.TIMG0.T0CONFIG.Set(1 << esp.TIMG_T0CONFIG_T0_DIVCNT_RST_Pos)
    32  	// esp.TIMG0.T0CONFIG.Set(esp.TIMG_T0CONFIG_T0_EN)
    33  
    34  	// Set the timer counter value to 0.
    35  	esp.TIMG0.T0LOADLO.Set(0)
    36  	esp.TIMG0.T0LOADHI.Set(0)
    37  	esp.TIMG0.T0LOAD.Set(0) // value doesn't matter.
    38  }
    39  
    40  func ticks() timeUnit {
    41  	// First, update the LO and HI register pair by writing any value to the
    42  	// register. This allows reading the pair atomically.
    43  	esp.TIMG0.T0UPDATE.Set(0)
    44  	// Then read the two 32-bit parts of the timer.
    45  	return timeUnit(uint64(esp.TIMG0.T0LO.Get()) | uint64(esp.TIMG0.T0HI.Get())<<32)
    46  }
    47  
    48  func nanosecondsToTicks(ns int64) timeUnit {
    49  	// Calculate the number of ticks from the number of nanoseconds. At a 80MHz
    50  	// APB clock, that's 25 nanoseconds per tick with a timer prescaler of 2:
    51  	// 25 = 1e9 / (80MHz / 2)
    52  	return timeUnit(ns / 25)
    53  }
    54  
    55  func ticksToNanoseconds(ticks timeUnit) int64 {
    56  	// See nanosecondsToTicks.
    57  	return int64(ticks) * 25
    58  }
    59  
    60  // sleepTicks busy-waits until the given number of ticks have passed.
    61  func sleepTicks(d timeUnit) {
    62  	sleepUntil := ticks() + d
    63  	for ticks() < sleepUntil {
    64  		// TODO: suspend the CPU to not burn power here unnecessarily.
    65  	}
    66  }
    67  
    68  func exit(code int) {
    69  	abort()
    70  }
    71  
    72  func putchar(c byte) {
    73  	machine.Serial.WriteByte(c)
    74  }
    75  
    76  func getchar() byte {
    77  	for machine.Serial.Buffered() == 0 {
    78  		Gosched()
    79  	}
    80  	v, _ := machine.Serial.ReadByte()
    81  	return v
    82  }
    83  
    84  func buffered() int {
    85  	return machine.Serial.Buffered()
    86  }