#![no_std]
pub mod gpio;
esp_bootloader_esp_idf::esp_app_desc!();
const CPU_HZ: u32 = 40_000_000;
const WDT_WKEY_UNLOCK: u32 = 0x50D8_3AA1;
const WDT_WKEY_LOCK: u32 = 0;
const SWD_WKEY_UNLOCK: u32 = 0x8F1D_312A; const SWD_WKEY_LOCK: u32 = 0;
pub fn disable_watchdogs() {
unsafe {
let rtc_cntl = &*esp32s3::RTC_CNTL::ptr();
rtc_cntl
.wdtwprotect()
.write(|w| w.bits(WDT_WKEY_UNLOCK));
rtc_cntl.wdtconfig0().write(|w| w.bits(0));
rtc_cntl.wdtwprotect().write(|w| w.bits(WDT_WKEY_LOCK));
rtc_cntl
.swd_wprotect()
.write(|w| w.swd_wkey().bits(SWD_WKEY_UNLOCK));
rtc_cntl.swd_conf().write(|w| w.swd_auto_feed_en().set_bit());
rtc_cntl
.swd_wprotect()
.write(|w| w.swd_wkey().bits(SWD_WKEY_LOCK));
let timg0 = &*esp32s3::TIMG0::ptr();
timg0.wdtwprotect().write(|w| w.wdt_wkey().bits(WDT_WKEY_UNLOCK));
timg0.wdtconfig0().write(|w| w.bits(0));
timg0.wdtwprotect().write(|w| w.wdt_wkey().bits(WDT_WKEY_LOCK));
}
}
unsafe extern "C" {
fn rom_config_instruction_cache_mode(cache_size: u32, ways: u8, line_size: u8);
fn rom_config_data_cache_mode(cache_size: u32, ways: u8, line_size: u8);
fn Cache_Suspend_DCache();
fn Cache_Resume_DCache(param: u32);
}
#[no_mangle]
extern "C" fn __pre_init() {
unsafe {
rom_config_instruction_cache_mode(0x8000, 8, 32);
Cache_Suspend_DCache();
rom_config_data_cache_mode(0x8000, 8, 32);
Cache_Resume_DCache(0);
}
disable_watchdogs();
}
#[no_mangle]
extern "Rust" fn __rivet_board_init() {
disable_watchdogs();
rivet_arch_xtensa::timer::configure(CPU_HZ);
release_app_cpu();
}
unsafe extern "C" {
fn rivet_appcpu_entry();
}
fn release_app_cpu() {
if rivet::config::MAX_HARTS < 2 {
return;
}
unsafe extern "C" {
fn ets_set_appcpu_boot_addr(addr: u32);
}
unsafe {
ets_set_appcpu_boot_addr(rivet_appcpu_entry as *const () as u32);
let system = &*esp32s3::SYSTEM::ptr();
system
.core_1_control_0()
.modify(|_, w| w.control_core_1_clkgate_en().set_bit());
system
.core_1_control_0()
.modify(|_, w| w.control_core_1_runstall().clear_bit());
system
.core_1_control_0()
.modify(|_, w| w.control_core_1_reseting().set_bit());
system
.core_1_control_0()
.modify(|_, w| w.control_core_1_reseting().clear_bit());
}
}
#[no_mangle]
extern "Rust" fn __rivet_board_now_us() -> u64 {
now_us()
}
#[no_mangle]
extern "Rust" fn __rivet_board_tick_start(hz: u32) {
rivet_arch_xtensa::timer::tick_start(hz);
}
#[no_mangle]
unsafe extern "Rust" fn __rivet_board_console_write(ptr: *const u8, len: usize) {
let bytes = unsafe { core::slice::from_raw_parts(ptr, len) };
rivet::critical::enter(|| {
let uart0 = unsafe { &*esp32s3::UART0::ptr() };
for &b in bytes {
while uart0.status().read().txfifo_cnt().bits() >= 124 {
core::hint::spin_loop();
}
uart0.fifo().write(|w| unsafe { w.rxfifo_rd_byte().bits(b) });
}
});
}
#[no_mangle]
extern "Rust" fn __rivet_board_console_kick_tx() {
}
#[no_mangle]
extern "Rust" fn __rivet_board_reset() -> ! {
let deadline = now_us().wrapping_add(20_000);
while now_us() < deadline {
core::hint::spin_loop();
}
unsafe {
(&*esp32s3::RTC_CNTL::ptr())
.options0()
.write(|w| w.sw_sys_rst().set_bit());
}
loop {
core::hint::spin_loop();
}
}
#[no_mangle]
extern "Rust" fn __rivet_board_exit(code: u32) -> ! {
if code == 0 {
rivet::console::write_str("RIVET_EXIT_OK\n");
} else {
rivet::console::write_str("RIVET_EXIT_FAIL code=");
print_dec(code);
rivet::console::write_str("\n");
}
loop {
core::hint::spin_loop();
}
}
fn print_dec(mut n: u32) {
if n == 0 {
rivet::console::write_str("0");
return;
}
let mut digits = [0u8; 10];
let mut i = 0;
while n > 0 {
digits[i] = b'0' + (n % 10) as u8;
n /= 10;
i += 1;
}
let mut buf = [0u8; 10];
for j in 0..i {
buf[j] = digits[i - 1 - j];
}
if let Ok(s) = core::str::from_utf8(&buf[..i]) {
rivet::console::write_str(s);
}
}
#[no_mangle]
extern "Rust" fn __rivet_board_wdt_init(period_us: u32) {
rivet_bsp_support::sw_watchdog::init(period_us, now_us());
}
#[no_mangle]
extern "Rust" fn __rivet_board_wdt_feed() {
rivet_bsp_support::sw_watchdog::feed(now_us());
}
#[no_mangle]
extern "Rust" fn __rivet_board_wdt_check() {
if rivet_bsp_support::sw_watchdog::expired(now_us()) {
rivet::console::write_str("RIVET WATCHDOG TIMEOUT\n");
rivet::port::board::reset();
}
}
static mut LAST_CCOUNT: u32 = 0;
static mut CYCLES_HIGH: u64 = 0;
fn now_us() -> u64 {
rivet::critical::enter(|| {
unsafe {
let now = xtensa_lx::timer::get_cycle_count();
if now < LAST_CCOUNT {
CYCLES_HIGH += 1u64 << 32;
}
LAST_CCOUNT = now;
let cycles = CYCLES_HIGH + now as u64;
cycles / (CPU_HZ as u64 / 1_000_000)
}
})
}
pub mod irq {
pub const UART0: u32 = 27;
}