1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/cpu/esp32/startup.c

330 lines
9.0 KiB
C
Raw Normal View History

2018-10-08 12:20:49 +02:00
/*
* Copyright (C) 2018 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp32
* @{
*
* @file
* @brief Implementation of the CPU initialization
*
* @author Gunar Schorcht <gunar@schorcht.net>
* @author Jens Alfke <jens@mooseyard.com>
2018-10-08 12:20:49 +02:00
* @}
*/
#include "esp_common.h"
#include <stdlib.h>
#include <string.h>
#include <sys/reent.h>
2022-02-01 22:11:43 +01:00
/* RIOT headers have to be included before ESP-IDF headers! */
2018-10-08 12:20:49 +02:00
#include "board.h"
2022-02-01 22:11:43 +01:00
#include "esp/common_macros.h"
2018-10-08 12:20:49 +02:00
#include "exceptions.h"
#include "irq_arch.h"
#include "kernel_defines.h"
#include "kernel_init.h"
#include "log.h"
2022-02-01 22:11:43 +01:00
#include "periph_cpu.h"
#include "stdio_base.h"
2018-10-08 12:20:49 +02:00
#include "syscalls.h"
#include "thread_arch.h"
2022-02-01 22:11:43 +01:00
#include "tools.h"
2018-10-08 12:20:49 +02:00
#include "periph/cpuid.h"
#include "periph/init.h"
#include "periph/rtc.h"
2022-02-01 22:11:43 +01:00
/* ESP-IDF headers */
2018-10-08 12:20:49 +02:00
#include "driver/periph_ctrl.h"
2022-02-01 22:11:43 +01:00
#include "esp_attr.h"
#include "esp_clk_internal.h"
2022-02-01 22:11:43 +01:00
#include "esp_heap_caps_init.h"
#include "esp_log.h"
#include "esp_private/startup_internal.h"
#include "esp_private/esp_clk.h"
#include "esp_rom_uart.h"
2022-02-01 22:11:43 +01:00
#include "esp_sleep.h"
#include "esp_timer.h"
#include "hal/interrupt_controller_types.h"
#include "hal/interrupt_controller_ll.h"
2018-10-08 12:20:49 +02:00
#include "rom/cache.h"
#include "rom/ets_sys.h"
#include "rom/rtc.h"
#include "rom/uart.h"
#include "soc/apb_ctrl_reg.h"
#include "soc/cpu.h"
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/rtc_cntl_struct.h"
#include "soc/timer_group_struct.h"
#if __xtensa__
#include "soc/dport_reg.h"
#include "soc/dport_access.h"
2018-10-08 12:20:49 +02:00
#include "xtensa/core-macros.h"
#include "xtensa/xtensa_api.h"
#endif
2018-10-08 12:20:49 +02:00
2022-02-01 22:11:43 +01:00
#if IS_USED(MODULE_ESP_SPI_RAM)
#include "spiram.h"
#endif
2018-10-08 12:20:49 +02:00
2022-02-01 22:11:43 +01:00
#if IS_USED(MODULE_PUF_SRAM)
2022-02-17 11:08:11 +01:00
#include "puf_sram.h"
#endif
2022-02-01 22:11:43 +01:00
#if IS_USED(MODULE_STDIO_UART)
2018-10-08 12:20:49 +02:00
#include "stdio_uart.h"
#endif
#define ENABLE_DEBUG 0
#include "debug.h"
2018-10-08 12:20:49 +02:00
#define STRINGIFY(s) STRINGIFY2(s)
#define STRINGIFY2(s) #s
2022-02-01 22:11:43 +01:00
#if IS_USED(MODULE_ESP_LOG_STARTUP)
#define LOG_STARTUP(format, ...) LOG_TAG_EARLY(LOG_INFO, D, __func__, format, ##__VA_ARGS__)
#else
#define LOG_STARTUP(format, ...)
#endif
2018-10-08 12:20:49 +02:00
/* following variables are defined in linker script */
extern uint8_t _bss_start;
extern uint8_t _bss_end;
extern uint8_t _sheap;
extern uint8_t _eheap;
extern uint8_t _rtc_bss_start;
extern uint8_t _rtc_bss_end;
extern uint8_t _rtc_bss_rtc_start;
extern uint8_t _rtc_bss_rtc_end;
2022-02-01 22:11:43 +01:00
extern uint8_t _iram_start;
2018-10-08 12:20:49 +02:00
/* external esp function declarations */
extern uint32_t hwrand (void);
2022-02-01 22:11:43 +01:00
2018-10-08 12:20:49 +02:00
/* forward declarations */
static void IRAM system_startup_cpu0(void);
static void IRAM system_init(void);
extern void IRAM_ATTR thread_yield_isr(void* arg);
2018-10-08 12:20:49 +02:00
2022-02-01 22:11:43 +01:00
uint64_t g_startup_time = 0;
const sys_startup_fn_t g_startup_fn[1] = { system_startup_cpu0 };
#if CONFIG_ESP_TIMER_IMPL_FRC2
/* dummy function required if FRC2 (legacy) timer of the ESP32 is used */
esp_err_t esp_timer_impl_early_init(void)
{
return ESP_OK;
}
#endif
2022-02-01 22:11:43 +01:00
2018-10-08 12:20:49 +02:00
/**
* @brief System startup function
2018-10-08 12:20:49 +02:00
*
* This function is the entry point in the user application. It is called
* after a CPU initialization to startup the system.
2018-10-08 12:20:49 +02:00
*/
static NORETURN void IRAM system_startup_cpu0(void)
2018-10-08 12:20:49 +02:00
{
#if __xtensa__
2018-10-08 12:20:49 +02:00
register uint32_t *sp __asm__ ("a1"); (void)sp;
#endif
#if __riscv
register uint32_t *sp __asm__ ("x2"); (void)sp;
#endif
2018-10-08 12:20:49 +02:00
2022-02-17 11:08:11 +01:00
#ifdef MODULE_PUF_SRAM
puf_sram_init((uint8_t *)&_sheap, SEED_RAM_LEN);
#endif
#if IS_USED(MODULE_ESP_IDF_HEAP)
/* init heap */
heap_caps_init();
if (IS_ACTIVE(ENABLE_DEBUG)) {
ets_printf("Heap free: %u byte\n", get_free_heap_size());
}
#endif
/* initialize system call tables of ESP32x rom and newlib */
syscalls_init();
/* systemwide UART initialization */
extern void uart_system_init (void);
uart_system_init();
/* initialize stdio */
esp_rom_uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM);
2023-01-02 18:08:35 +01:00
early_init();
2018-10-08 12:20:49 +02:00
RESET_REASON reset_reason = rtc_get_reset_reason(PRO_CPU_NUM);
2018-10-08 12:20:49 +02:00
/* initialize RTC data after power on or RTC WDT reset */
2018-10-08 12:20:49 +02:00
if (reset_reason == POWERON_RESET || reset_reason == RTCWDT_RTC_RESET) {
2021-11-16 16:50:28 +01:00
/* cppcheck-suppress comparePointers */
2018-10-08 12:20:49 +02:00
memset(&_rtc_bss_rtc_start, 0, (&_rtc_bss_rtc_end - &_rtc_bss_rtc_start));
}
uint8_t cpu_id[CPUID_LEN];
cpuid_get ((void*)cpu_id);
2022-02-01 22:11:43 +01:00
#if IS_USED(MODULE_ESP_LOG_STARTUP)
LOG_STARTUP("\nStarting ESP32x with ID: ");
2018-10-08 12:20:49 +02:00
for (unsigned i = 0; i < CPUID_LEN; i++) {
ets_printf("%02x", cpu_id[i]);
}
ets_printf("\n");
extern char* esp_get_idf_version(void);
LOG_STARTUP("ESP-IDF SDK Version %s\n\n", esp_get_idf_version());
#endif
2018-10-08 12:20:49 +02:00
2020-02-20 08:30:06 +01:00
if (reset_reason == DEEPSLEEP_RESET) {
/* the cause has to be read to clear it */
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
(void)cause;
LOG_STARTUP("Restart after deep sleep, wake-up cause: %d\n", cause);
}
LOG_STARTUP("Current clocks in Hz: CPU=%d APB=%d XTAL=%d SLOW=%d\n",
2022-02-01 22:11:43 +01:00
esp_clk_cpu_freq(),
esp_clk_apb_freq(), esp_clk_xtal_freq(),
2018-10-08 12:20:49 +02:00
rtc_clk_slow_freq_get_hz());
if (IS_ACTIVE(ENABLE_DEBUG)) {
ets_printf("reset reason: %d\n", reset_reason);
ets_printf("_stack %p\n", sp);
ets_printf("_bss_start %p\n", &_bss_start);
ets_printf("_bss_end %p\n", &_bss_end);
if (!IS_ACTIVE(MODULE_ESP_IDF_HEAP)) {
ets_printf("_heap_start %p\n", &_sheap);
ets_printf("_heap_end %p\n", &_eheap);
ets_printf("_heap_free %u\n", get_free_heap_size());
}
}
2018-10-08 12:20:49 +02:00
LOG_STARTUP("PRO cpu is up (single core mode, only PRO cpu is used)\n");
2018-10-08 12:20:49 +02:00
/* init esp_timer implementation */
esp_timer_early_init();
LOG_STARTUP("PRO cpu starts user code\n");
2018-10-08 12:20:49 +02:00
system_init();
UNREACHABLE();
}
static NORETURN void IRAM system_init (void)
{
static_assert(MAXTHREADS >= 3,
"ESP32x SoCs require at least 3 threads, esp_timer, idle, and main");
#if defined(CPU_FAM_ESP32)
2018-10-08 12:20:49 +02:00
/* enable cached read from flash */
Cache_Read_Enable(PRO_CPU_NUM);
#endif
2018-10-08 12:20:49 +02:00
/* initialize the ISR stack for usage measurements */
thread_isr_stack_init();
2019-10-23 21:13:52 +02:00
/* install exception handlers */
2018-10-08 12:20:49 +02:00
init_exceptions();
/* set log levels for SDK library outputs */
extern void esp_log_level_set(const char* tag, esp_log_level_t level);
esp_log_level_set("wifi", (esp_log_level_t)LOG_DEBUG);
esp_log_level_set("gpio", (esp_log_level_t)LOG_DEBUG);
2018-10-08 12:20:49 +02:00
/* init watchdogs */
system_wdt_init();
/* init random number generator */
srand(hwrand());
/* add SPI RAM to heap if enabled */
2022-02-01 22:11:43 +01:00
#if CONFIG_SPIRAM_SUPPORT && CONFIG_SPIRAM_BOOT_INIT
esp_spiram_init_cache();
esp_spiram_add_to_heapalloc();
#endif
2018-10-08 12:20:49 +02:00
/* print some infos */
LOG_STARTUP("Used clocks in Hz: CPU=%d APB=%d XTAL=%d FAST=%d SLOW=%d\n",
2022-02-01 22:11:43 +01:00
esp_clk_cpu_freq(),
esp_clk_apb_freq(), esp_clk_xtal_freq(),
rtc_clk_fast_freq_get() == RTC_FAST_FREQ_8M ? 8 * MHZ
: esp_clk_xtal_freq()/4,
rtc_clk_slow_freq_get_hz());
LOG_STARTUP("XTAL calibration value: %d\n", esp_clk_slowclk_cal_get());
LOG_STARTUP("Heap free: %u bytes\n", get_free_heap_size());
2018-10-08 12:20:49 +02:00
/* initialize architecture specific interrupt handling */
esp_irq_init();
/* disable buffering in stdio */
setvbuf(_stdout_r(_REENT), NULL, _IONBF, 0);
setvbuf(_stderr_r(_REENT), NULL, _IONBF, 0);
2018-10-08 12:20:49 +02:00
/* trigger static peripheral initialization */
periph_init();
/* print system time */
2022-02-01 22:11:43 +01:00
#if IS_USED(MODULE_PERIPH_RTC)
struct tm _sys_time;
rtc_get_time(&_sys_time);
LOG_STARTUP("System time: %04d-%02d-%02d %02d:%02d:%02d\n",
_sys_time.tm_year + 1900, _sys_time.tm_mon + 1, _sys_time.tm_mday,
_sys_time.tm_hour, _sys_time.tm_min, _sys_time.tm_sec);
#endif
2018-10-08 12:20:49 +02:00
/* print the board config */
2022-02-01 22:11:43 +01:00
#if IS_USED(MODULE_ESP_LOG_STARTUP)
2018-10-08 12:20:49 +02:00
print_board_config();
#endif
2018-10-08 12:20:49 +02:00
2023-01-07 13:11:31 +01:00
#if IS_USED(MODULE_PERIPH_FLASHPAGE)
extern void esp_flashpage_init(void);
esp_flashpage_init();
#endif
2022-02-01 22:11:43 +01:00
#if IS_USED(MODULE_MTD)
/* init flash drive */
extern void spi_flash_drive_init (void);
spi_flash_drive_init();
2022-02-01 22:11:43 +01:00
#endif
/* initialize the board */
extern void board_init(void);
board_init();
2018-10-08 12:20:49 +02:00
/* route a software interrupt source to CPU as trigger for thread yields */
intr_matrix_set(PRO_CPU_NUM, ETS_FROM_CPU_INTR0_SOURCE, CPU_INUM_SOFTWARE);
/* set thread yield handler and enable the software interrupt */
intr_cntrl_ll_set_int_handler(CPU_INUM_SOFTWARE, thread_yield_isr, NULL);
intr_cntrl_ll_enable_interrupts(BIT(CPU_INUM_SOFTWARE));
2018-10-08 12:20:49 +02:00
/* initialize ESP system event loop */
extern void esp_event_handler_init(void);
esp_event_handler_init();
2022-02-01 22:11:43 +01:00
/* initialize ESP-IDF timer task */
esp_timer_init();
2018-10-08 12:20:49 +02:00
/* starting RIOT */
2022-02-01 22:11:43 +01:00
#if IS_USED(MODULE_ESP_LOG_STARTUP)
LOG_STARTUP("Starting RIOT kernel on PRO cpu\n");
esp_rom_uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM);
#else
ets_printf("\n");
#endif
2018-10-08 12:20:49 +02:00
kernel_init();
UNREACHABLE();
}