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