github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/device/esp/esp32c3.S (about) 1 // This is a very minimal bootloader for the ESP32-C3. It only initializes the 2 // flash and then continues with the generic RISC-V initialization code, which 3 // in turn will call runtime.main. 4 // It is written in assembly (and not in a higher level language) to make sure 5 // it is entirely loaded into IRAM and doesn't accidentally call functions 6 // stored in IROM. 7 // 8 // For reference, here is a nice introduction into RISC-V assembly: 9 // https://www.imperialviolet.org/2016/12/31/riscv.html 10 11 .section .init 12 .global call_start_cpu0 13 .type call_start_cpu0,@function 14 call_start_cpu0: 15 // At this point: 16 // - The ROM bootloader is finished and has jumped to here. 17 // - We're running from IRAM: both IRAM and DRAM segments have been loaded 18 // by the ROM bootloader. 19 // - We have a usable stack (but not the one we would like to use). 20 // - No flash mappings (MMU) are set up yet. 21 22 // Reset MMU, see bootloader_reset_mmu in the ESP-IDF. 23 call Cache_Suspend_ICache 24 mv s0, a0 // autoload value 25 call Cache_Invalidate_ICache_All 26 call Cache_MMU_Init 27 28 // Set up DROM from flash. 29 // Somehow, this also sets up IROM from flash. Not sure why, but it avoids 30 // the need for another such call. 31 // C equivalent: 32 // Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, 0x3C00_0000, 0, 64, 128, 0) 33 li a0, 0 // ext_ram: MMU_ACCESS_FLASH 34 li a1, 0x3C000000 // vaddr: address in the data bus 35 li a2, 0 // paddr: physical address in the flash chip 36 li a3, 64 // psize: always 64 (kilobytes) 37 li a4, 128 // num: pages to be set (8192K / 64K = 128) 38 li a5, 0 // fixed 39 call Cache_Dbus_MMU_Set 40 41 // Enable the flash cache. 42 mv a0, s0 // restore autoload value from Cache_Suspend_ICache call 43 call Cache_Resume_ICache 44 45 // Jump to generic RISC-V initialization, which initializes the stack 46 // pointer and globals register. It should not return. 47 // (It appears that the linker relaxes this jump and instead inserts the 48 // _start function right after here). 49 j _start 50 51 .section .text.exception_vectors 52 .global _vector_table 53 .type _vector_table,@function 54 55 _vector_table: 56 57 .option push 58 .option norvc 59 60 .rept 32 61 j handleInterruptASM /* interrupt handler */ 62 .endr 63 64 .option pop 65 66 .size _vector_table, .-_vector_table 67