github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/runtime/runtime_esp8266.go (about) 1 //go:build esp8266 2 3 package runtime 4 5 import ( 6 "device" 7 "device/esp" 8 "machine" 9 "unsafe" 10 ) 11 12 type timeUnit int64 13 14 var currentTime timeUnit = 0 15 16 func putchar(c byte) { 17 machine.Serial.WriteByte(c) 18 } 19 20 func getchar() byte { 21 for machine.Serial.Buffered() == 0 { 22 Gosched() 23 } 24 v, _ := machine.Serial.ReadByte() 25 return v 26 } 27 28 func buffered() int { 29 return machine.Serial.Buffered() 30 } 31 32 // Write to the internal control bus (using I2C?). 33 // Signature found here: 34 // https://github.com/espressif/ESP8266_RTOS_SDK/blob/14171de0/components/esp8266/include/esp8266/rom_functions.h#L54 35 // 36 //export rom_i2c_writeReg 37 func rom_i2c_writeReg(block, host_id, reg_add, data uint8) 38 39 //export main 40 func main() { 41 // Clear .bss section. .data has already been loaded by the ROM bootloader. 42 preinit() 43 44 // Initialize PLL. 45 // I'm not quite sure what this magic incantation means, but it does set the 46 // esp8266 to the right clock speed. Without this, it is running too slow. 47 rom_i2c_writeReg(103, 4, 1, 136) 48 rom_i2c_writeReg(103, 4, 2, 145) 49 50 // Initialize UART. 51 machine.InitSerial() 52 53 // Initialize timer. Bits: 54 // ENABLE: timer enable 55 // ROLLOVER: automatically reload when hitting 0 56 // PRESCALE: divide by 256 57 esp.TIMER.FRC1_CTRL.Set( 58 esp.TIMER_FRC1_CTRL_TIMER_ENABLE | esp.TIMER_FRC1_CTRL_ROLLOVER | esp.TIMER_FRC1_CTRL_PRESCALE_DIVIDER_DEVIDED_BY_256<<esp.TIMER_FRC1_CTRL_PRESCALE_DIVIDER_Pos) 59 esp.TIMER.FRC1_LOAD.Set(0x3fffff) // set all 22 bits to 1 60 esp.TIMER.FRC1_COUNT.Set(0x3fffff) // set all 22 bits to 1 61 62 run() 63 64 // Fallback: if main ever returns, hang the CPU. 65 exit(0) 66 } 67 68 //go:extern _sbss 69 var _sbss [0]byte 70 71 //go:extern _ebss 72 var _ebss [0]byte 73 74 func preinit() { 75 // Initialize .bss: zero-initialized global variables. 76 ptr := unsafe.Pointer(&_sbss) 77 for ptr != unsafe.Pointer(&_ebss) { 78 *(*uint32)(ptr) = 0 79 ptr = unsafe.Add(ptr, 4) 80 } 81 } 82 83 func ticks() timeUnit { 84 // Get the counter value of the timer. It is 22 bits and starts with all 85 // ones (0x3fffff). To make it easier to work with, let it count upwards. 86 count := 0x3fffff - esp.TIMER.FRC1_COUNT.Get() 87 88 // Replace the lowest 22 bits of the current time with the counter. 89 newTime := (currentTime &^ 0x3fffff) | timeUnit(count) 90 91 // If there was an overflow, the new time will be lower than the current 92 // time, so will need to add (1<<22). 93 if newTime < currentTime { 94 newTime += 0x400000 95 } 96 97 // Update the timestamp for the next call to ticks(). 98 currentTime = newTime 99 100 return currentTime 101 } 102 103 const tickNanos = 3200 // time.Second / (80MHz / 256) 104 105 func ticksToNanoseconds(ticks timeUnit) int64 { 106 return int64(ticks) * tickNanos 107 } 108 109 func nanosecondsToTicks(ns int64) timeUnit { 110 return timeUnit(ns / tickNanos) 111 } 112 113 // sleepTicks busy-waits until the given number of ticks have passed. 114 func sleepTicks(d timeUnit) { 115 sleepUntil := ticks() + d 116 for ticks() < sleepUntil { 117 } 118 } 119 120 func exit(code int) { 121 abort() 122 } 123 124 func abort() { 125 for { 126 device.Asm("waiti 0") 127 } 128 }