github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/runtime/runtime_esp32c3.go (about) 1 //go:build esp32c3 2 3 package runtime 4 5 import ( 6 "device/esp" 7 "device/riscv" 8 "machine" 9 "runtime/volatile" 10 "unsafe" 11 ) 12 13 // This is the function called on startup after the flash (IROM/DROM) is 14 // initialized and the stack pointer has been set. 15 // 16 //export main 17 func main() { 18 // This initialization configures the following things: 19 // * It disables all watchdog timers. They might be useful at some point in 20 // the future, but will need integration into the scheduler. For now, 21 // they're all disabled. 22 // * It sets the CPU frequency to 160MHz, which is the maximum speed allowed 23 // for this CPU. Lower frequencies might be possible in the future, but 24 // running fast and sleeping quickly is often also a good strategy to save 25 // power. 26 // TODO: protect certain memory regions, especially the area below the stack 27 // to protect against stack overflows. See 28 // esp_cpu_configure_region_protection in ESP-IDF. 29 30 // Disable Timer 0 watchdog. 31 esp.TIMG0.WDTCONFIG0.Set(0) 32 33 // Disable RTC watchdog. 34 esp.RTC_CNTL.WDTWPROTECT.Set(0x50D83AA1) 35 esp.RTC_CNTL.WDTCONFIG0.Set(0) 36 37 // Disable super watchdog. 38 esp.RTC_CNTL.SWD_WPROTECT.Set(0x8F1D312A) 39 esp.RTC_CNTL.SWD_CONF.Set(esp.RTC_CNTL_SWD_CONF_SWD_DISABLE) 40 41 // Change CPU frequency from 20MHz to 80MHz, by switching from the XTAL to 42 // the PLL clock source (see table "CPU Clock Frequency" in the reference 43 // manual). 44 esp.SYSTEM.SYSCLK_CONF.Set(1 << esp.SYSTEM_SYSCLK_CONF_SOC_CLK_SEL_Pos) 45 46 // Change CPU frequency from 80MHz to 160MHz by setting SYSTEM_CPUPERIOD_SEL 47 // to 1 (see table "CPU Clock Frequency" in the reference manual). 48 // Note: we might not want to set SYSTEM_CPU_WAIT_MODE_FORCE_ON to save 49 // power. It is set here to keep the default on reset. 50 esp.SYSTEM.CPU_PER_CONF.Set(esp.SYSTEM_CPU_PER_CONF_CPU_WAIT_MODE_FORCE_ON | esp.SYSTEM_CPU_PER_CONF_PLL_FREQ_SEL | 1<<esp.SYSTEM_CPU_PER_CONF_CPUPERIOD_SEL_Pos) 51 52 clearbss() 53 54 // Configure interrupt handler 55 interruptInit() 56 57 // Initialize UART. 58 machine.USBCDC.Configure(machine.UARTConfig{}) 59 machine.InitSerial() 60 61 // Initialize main system timer used for time.Now. 62 initTimer() 63 64 // Initialize the heap, call main.main, etc. 65 run() 66 67 // Fallback: if main ever returns, hang the CPU. 68 exit(0) 69 } 70 71 func abort() { 72 // lock up forever 73 for { 74 riscv.Asm("wfi") 75 } 76 } 77 78 // interruptInit initialize the interrupt controller and called from runtime once. 79 func interruptInit() { 80 mie := riscv.DisableInterrupts() 81 82 // Reset all interrupt source priorities to zero. 83 priReg := &esp.INTERRUPT_CORE0.CPU_INT_PRI_1 84 for i := 0; i < 31; i++ { 85 priReg.Set(0) 86 priReg = (*volatile.Register32)(unsafe.Add(unsafe.Pointer(priReg), 4)) 87 } 88 89 // default threshold for interrupts is 5 90 esp.INTERRUPT_CORE0.CPU_INT_THRESH.Set(5) 91 92 // Set the interrupt address. 93 // Set MODE field to 1 - a vector base address (only supported by ESP32C3) 94 // Note that this address must be aligned to 256 bytes. 95 riscv.MTVEC.Set((uintptr(unsafe.Pointer(&_vector_table))) | 1) 96 97 riscv.EnableInterrupts(mie) 98 } 99 100 //go:extern _vector_table 101 var _vector_table [0]uintptr