mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-08 13:03:39 +00:00
Add ESP32-S3 support (#5091)
* feat: add initial support for ESP32-S3 (#3442) * feat: add initial support for esp32-s3 * esp32s3: fix merge errors * esp32s3: Fix Watchdog registers bad names * esp32s3: fix linker relocation errors and support for ESP binary * esp32s3: fix memory section overlap * esp32s3: correct clock frequencies * esp32s3: more stable cpu * esp32s3: enable basic gpio support * esp32s3: simplify loading and check extensions * esp32s3: synchronize cpu features with clang * esp32s3: correct iram origin --------- Co-authored-by: Denys Vitali <denys@denv.it> Co-authored-by: Olivier Fauchon <ofauchon2204@gmail.com>
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
//go:build esp32s3
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"device/esp"
|
||||
)
|
||||
|
||||
// This is the function called on startup after the flash (IROM/DROM) is
|
||||
// initialized and the stack pointer has been set.
|
||||
//
|
||||
//export main
|
||||
func main() {
|
||||
// This initialization configures the following things:
|
||||
// * It disables all watchdog timers. They might be useful at some point in
|
||||
// the future, but will need integration into the scheduler. For now,
|
||||
// they're all disabled.
|
||||
// * It sets the CPU frequency to 240MHz, which is the maximum speed allowed
|
||||
// for this CPU. Lower frequencies might be possible in the future, but
|
||||
// running fast and sleeping quickly is often also a good strategy to save
|
||||
// power.
|
||||
// TODO: protect certain memory regions, especially the area below the stack
|
||||
// to protect against stack overflows. See
|
||||
// esp_cpu_configure_region_protection in ESP-IDF.
|
||||
|
||||
// Disable RTC watchdog.
|
||||
esp.RTC_CNTL.WDTWPROTECT.Set(0x50D83AA1)
|
||||
esp.RTC_CNTL.WDTCONFIG0.Set(0)
|
||||
esp.RTC_CNTL.WDTWPROTECT.Set(0x0) // Re-enable write protect
|
||||
|
||||
// Disable Timer 0 watchdog.
|
||||
esp.TIMG1.WDTWPROTECT.Set(0x50D83AA1) // write protect
|
||||
esp.TIMG1.WDTCONFIG0.Set(0) // disable TG0 WDT
|
||||
esp.TIMG1.WDTWPROTECT.Set(0x0) // Re-enable write protect
|
||||
|
||||
esp.TIMG0.WDTWPROTECT.Set(0x50D83AA1) // write protect
|
||||
esp.TIMG0.WDTCONFIG0.Set(0) // disable TG0 WDT
|
||||
esp.TIMG0.WDTWPROTECT.Set(0x0) // Re-enable write protect
|
||||
|
||||
// Disable super watchdog.
|
||||
esp.RTC_CNTL.SWD_WPROTECT.Set(0x8F1D312A)
|
||||
esp.RTC_CNTL.SWD_CONF.Set(esp.RTC_CNTL_SWD_CONF_SWD_DISABLE)
|
||||
esp.RTC_CNTL.SWD_WPROTECT.Set(0x0) // Re-enable write protect
|
||||
|
||||
// Change CPU frequency from 20MHz to 80MHz, by switching from the XTAL to the
|
||||
// PLL clock source (see table "CPU Clock Frequency" in the reference manual).
|
||||
esp.SYSTEM.SetSYSCLK_CONF_SOC_CLK_SEL(1)
|
||||
|
||||
// Change CPU frequency from 80MHz to 240MHz by setting SYSTEM_PLL_FREQ_SEL to
|
||||
// 1 and SYSTEM_CPUPERIOD_SEL to 2 (see table "CPU Clock Frequency" in the
|
||||
// reference manual).
|
||||
esp.SYSTEM.SetCPU_PER_CONF_PLL_FREQ_SEL(1)
|
||||
esp.SYSTEM.SetCPU_PER_CONF_CPUPERIOD_SEL(2)
|
||||
|
||||
// Clear bss. Repeat many times while we wait for cpu/clock to stabilize
|
||||
for x := 0; x < 30; x++ {
|
||||
clearbss()
|
||||
}
|
||||
|
||||
// Initialize main system timer used for time.Now.
|
||||
initTimer()
|
||||
|
||||
// Initialize the heap, call main.main, etc.
|
||||
run()
|
||||
|
||||
// Fallback: if main ever returns, hang the CPU.
|
||||
exit(0)
|
||||
}
|
||||
|
||||
func abort() {
|
||||
// lock up forever
|
||||
print("abort called\n")
|
||||
}
|
||||
|
||||
//go:extern _vector_table
|
||||
var _vector_table [0]uintptr
|
||||
|
||||
//go:extern _sbss
|
||||
var _sbss [0]byte
|
||||
|
||||
//go:extern _ebss
|
||||
var _ebss [0]byte
|
||||
@@ -0,0 +1,86 @@
|
||||
//go:build esp32s3
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"device/esp"
|
||||
"machine"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//type timeUnit int64
|
||||
|
||||
func putchar(c byte) {
|
||||
machine.Serial.WriteByte(c)
|
||||
}
|
||||
|
||||
func getchar() byte {
|
||||
for machine.Serial.Buffered() == 0 {
|
||||
Gosched()
|
||||
}
|
||||
v, _ := machine.Serial.ReadByte()
|
||||
return v
|
||||
}
|
||||
|
||||
func buffered() int {
|
||||
return machine.Serial.Buffered()
|
||||
}
|
||||
|
||||
// Initialize .bss: zero-initialized global variables.
|
||||
// The .data section has already been loaded by the ROM bootloader.
|
||||
func clearbss() {
|
||||
ptr := unsafe.Pointer(&_sbss)
|
||||
for ptr != unsafe.Pointer(&_ebss) {
|
||||
*(*uint32)(ptr) = 0
|
||||
ptr = unsafe.Add(ptr, 4)
|
||||
}
|
||||
}
|
||||
|
||||
func initTimer() {
|
||||
// Configure timer 0 in timer group 0, for timekeeping.
|
||||
// EN: Enable the timer.
|
||||
// INCREASE: Count up every tick (as opposed to counting down).
|
||||
// DIVIDER: 16-bit prescaler, set to 2 for dividing the APB clock by two
|
||||
// (40MHz).
|
||||
// esp.TIMG0.T0CONFIG.Set(0 << esp.TIMG_T0CONFIG_T0_EN_Pos)
|
||||
esp.TIMG0.T0CONFIG.Set(esp.TIMG_TCONFIG_EN | esp.TIMG_TCONFIG_INCREASE | 2<<esp.TIMG_TCONFIG_DIVIDER_Pos)
|
||||
// esp.TIMG0.T0CONFIG.Set(1 << esp.TIMG_T0CONFIG_T0_DIVCNT_RST_Pos)
|
||||
// esp.TIMG0.T0CONFIG.Set(esp.TIMG_T0CONFIG_T0_EN)
|
||||
|
||||
// Set the timer counter value to 0.
|
||||
esp.TIMG0.T0LOADLO.Set(0)
|
||||
esp.TIMG0.T0LOADHI.Set(0)
|
||||
esp.TIMG0.T0LOAD.Set(0) // value doesn't matter.
|
||||
}
|
||||
|
||||
func ticks() timeUnit {
|
||||
// First, update the LO and HI register pair by writing any value to the
|
||||
// register. This allows reading the pair atomically.
|
||||
esp.TIMG0.T0UPDATE.Set(0)
|
||||
// Then read the two 32-bit parts of the timer.
|
||||
return timeUnit(uint64(esp.TIMG0.T0LO.Get()) | uint64(esp.TIMG0.T0HI.Get())<<32)
|
||||
}
|
||||
|
||||
func nanosecondsToTicks(ns int64) timeUnit {
|
||||
// Calculate the number of ticks from the number of nanoseconds. At a 80MHz
|
||||
// APB clock, that's 25 nanoseconds per tick with a timer prescaler of 2:
|
||||
// 25 = 1e9 / (80MHz / 2)
|
||||
return timeUnit(ns / 25)
|
||||
}
|
||||
|
||||
func ticksToNanoseconds(ticks timeUnit) int64 {
|
||||
// See nanosecondsToTicks.
|
||||
return int64(ticks) * 25
|
||||
}
|
||||
|
||||
// sleepTicks busy-waits until the given number of ticks have passed.
|
||||
func sleepTicks(d timeUnit) {
|
||||
sleepUntil := ticks() + d
|
||||
for ticks() < sleepUntil {
|
||||
// TODO: suspend the CPU to not burn power here unnecessarily.
|
||||
}
|
||||
}
|
||||
|
||||
func exit(code int) {
|
||||
abort()
|
||||
}
|
||||
Reference in New Issue
Block a user