From be112daa711c0f8158af7b579bde50d286f57405 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 24 Aug 2016 16:21:28 +0800 Subject: [PATCH 1/2] components/esp32: fix and clean up dual core startup This change removes various delays in PRO and APP CPU startup paths. Also some unused code and ets_printf statements are cleaned up or removed. 2nd CPU now communicates that it has started through a global variable. --- components/esp32/cpu_start.c | 52 ++++++++++++------------------------ 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c index d6e8fdd5c5..23e4474810 100644 --- a/components/esp32/cpu_start.c +++ b/components/esp32/cpu_start.c @@ -64,6 +64,8 @@ void uartAttach(); void ets_set_appcpu_boot_addr(uint32_t ent); int ets_getAppEntry(); +static bool app_cpu_started = false; + void IRAM_ATTR call_user_start_cpu0() { //Kill wdt REG_CLR_BIT(0x3ff4808c, BIT(10)); //RTCCNTL+8C RTC_WDTCONFIG0 RTC_ @@ -114,53 +116,34 @@ void IRAM_ATTR call_user_start_cpu0() { heap_alloc_caps_init(); ets_printf("Pro cpu up.\n"); + #ifndef CONFIG_FREERTOS_UNICORE - ets_printf("Running app cpu, entry point is %p\n", call_user_start_cpu1); - ets_delay_us(60000); + ets_printf("Starting app cpu, entry point is %p\n", call_user_start_cpu1); SET_PERI_REG_MASK(APPCPU_CTRL_REG_B, DPORT_APPCPU_CLKGATE_EN); + CLEAR_PERI_REG_MASK(APPCPU_CTRL_REG_C, DPORT_APPCPU_RUNSTALL); SET_PERI_REG_MASK(APPCPU_CTRL_REG_A, DPORT_APPCPU_RESETTING); CLEAR_PERI_REG_MASK(APPCPU_CTRL_REG_A, DPORT_APPCPU_RESETTING); - - - for (int i=0; i<20; i++) ets_delay_us(40000); ets_set_appcpu_boot_addr((uint32_t)call_user_start_cpu1); - ets_delay_us(10000); - -// while (ets_getAppEntry()==(int)call_user_start_cpu1) ; - //Because of Reasons (tm), the pro cpu cannot use the SPI flash while the app cpu is booting. -// while(((READ_PERI_REG(RTC_STORE7))&BIT(31)) == 0) ; // check APP boot complete flag - ets_delay_us(50000); - ets_delay_us(50000); - ets_printf("\n\nBack to pro cpu.\n"); + while (!app_cpu_started) { + ets_delay_us(100); + } #else CLEAR_PERI_REG_MASK(APPCPU_CTRL_REG_B, DPORT_APPCPU_CLKGATE_EN); #endif + ets_printf("Pro cpu start user code\n"); user_start_cpu0(); } -extern int xPortGetCoreID(); - extern int _init_start; -/* -We arrive here because the pro CPU pulled us from reset. IRAM is in place, cache is still disabled, we can execute C code. -*/ void IRAM_ATTR call_user_start_cpu1() { - //We need to do this ASAP because otherwise the structure to catch the SYSCALL instruction, which - //we abuse to do ROM calls, won't work. - asm volatile (\ "wsr %0, vecbase\n" \ ::"r"(&_init_start)); - //Enable SPI flash -// PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, FUNC_SD_DATA3_SPIWP); // swap PIN SDDATA3 from uart1 to spi, because cache need spi - - ets_printf("App cpu up\n"); - //Make page 0 access raise an exception //Also some other unused pages so we can catch weirdness //ToDo: this but nicer. @@ -192,16 +175,15 @@ void IRAM_ATTR call_user_start_cpu1() { "isync\n" \ :::"a4","a5"); + ets_printf("App cpu up.\n"); + app_cpu_started = 1; user_start_cpu1(); } - - extern volatile int port_xSchedulerRunning; extern int xPortStartScheduler(); void user_start_cpu1(void) { - ets_printf("App cpu is running!\n"); //Wait for the freertos initialization is finished on CPU0 while (port_xSchedulerRunning == 0) ; ets_printf("Core0 started initializing FreeRTOS. Jumping to scheduler.\n"); @@ -221,11 +203,12 @@ static void do_global_ctors(void) { void user_start_cpu0(void) { - esp_err_t ret; - ets_setup_syscalls(); do_global_ctors(); + // TODO: consider ethernet interface + +#if CONFIG_WIFI_ENABLED #if 1 //workaround for (uint8_t i = 5; i < 8; i++) { ets_printf("erase sector %d\n", i); @@ -233,8 +216,8 @@ void user_start_cpu0(void) { } #endif ets_printf("nvs_flash_init\n"); - ret = nvs_flash_init(5, 3); - if (ESP_OK != ret) { + esp_err_t ret = nvs_flash_init(5, 3); + if (ret != ESP_OK) { ets_printf("nvs_flash_init fail, ret=%d\n", ret); } @@ -242,9 +225,8 @@ void user_start_cpu0(void) { esp_event_init(NULL); - // TODO: consider ethernet interface -#if CONFIG_WIFI_ENABLED tcpip_adapter_init(); + #endif #if CONFIG_WIFI_ENABLED && CONFIG_WIFI_AUTO_STARTUP From 4d1084120c72a49481c97ee22bc4885cd2686a5a Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 24 Aug 2016 16:25:04 +0800 Subject: [PATCH 2/2] components/bootloader: fix enabling cache for APP CPU This is a workaround for a hardware bug with cache initialization. Only two lines of code related to DPORT_APP_CACHE_MMU_IA_CLR were added around mmu_init(1); call, and two lines at the end of comment block. I reformatted surrounding lines to use spaces for indentation, like the rest of the code in this file does. --- .../bootloader/src/main/bootloader_start.c | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/components/bootloader/src/main/bootloader_start.c b/components/bootloader/src/main/bootloader_start.c index 5c2a186812..b9df64012a 100644 --- a/components/bootloader/src/main/bootloader_start.c +++ b/components/bootloader/src/main/bootloader_start.c @@ -92,23 +92,28 @@ void IRAM_ATTR call_start_cpu0() //Clear bss memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start)); - /* completely reset MMU for both CPUs - (in case serial bootloader was running) */ - Cache_Read_Disable(0); - Cache_Read_Disable(1); - Cache_Flush(0); - Cache_Flush(1); - mmu_init(0); - mmu_init(1); - /* (above steps probably unnecessary for most serial bootloader - usage, all that's absolutely needed is that we unmask DROM0 - cache on the following two lines - normal ROM boot exits with - DROM0 cache unmasked, but serial bootloader exits with it - masked. However can't hurt to be thorough and reset - everything.) - */ - REG_CLR_BIT(PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DROM0); - REG_CLR_BIT(APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DROM0); + /* completely reset MMU for both CPUs + (in case serial bootloader was running) */ + Cache_Read_Disable(0); + Cache_Read_Disable(1); + Cache_Flush(0); + Cache_Flush(1); + mmu_init(0); + REG_SET_BIT(APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR); + mmu_init(1); + REG_CLR_BIT(APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR); + /* (above steps probably unnecessary for most serial bootloader + usage, all that's absolutely needed is that we unmask DROM0 + cache on the following two lines - normal ROM boot exits with + DROM0 cache unmasked, but serial bootloader exits with it + masked. However can't hurt to be thorough and reset + everything.) + + The lines which manipulate DPORT_APP_CACHE_MMU_IA_CLR bit are + necessary to work around a hardware bug. + */ + REG_CLR_BIT(PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DROM0); + REG_CLR_BIT(APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DROM0); bootloader_main(); }