Skip to content

Commit

Permalink
esp_system: Do not rely on bootloader cache settings, do cache settin…
Browse files Browse the repository at this point in the history
…gs unconditionally at startup app

It makes multicore app runnable by unicore bootloader

Closes #10714
  • Loading branch information
KonstantinKondrashov authored and espressif-bot committed May 11, 2023
1 parent 42a6b47 commit 1b608a1
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 0 deletions.
8 changes: 8 additions & 0 deletions components/bootloader_support/src/bootloader_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,12 @@ void bootloader_print_banner(void)
{
ESP_LOGI(TAG, "ESP-IDF %s 2nd stage bootloader", IDF_VER);
ESP_LOGI(TAG, "compile time " __TIME__);

#if CONFIG_FREERTOS_UNICORE
#if (SOC_CPU_CORES_NUM > 1)
ESP_EARLY_LOGW(TAG, "Unicore bootloader");
#endif
#else
ESP_EARLY_LOGI(TAG, "Multicore bootloader");
#endif
}
45 changes: 45 additions & 0 deletions components/esp_system/port/cpu_start.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@
#include "hal/wdt_hal.h"
#include "soc/rtc.h"
#include "soc/efuse_reg.h"
#if (SOC_CPU_CORES_NUM > 1)
#include "hal/cache_ll.h"
#endif
#include "hal/efuse_ll.h"
#include "soc/periph_defs.h"
#include "soc/cpu.h"
#include "soc/rtc.h"
Expand Down Expand Up @@ -244,6 +248,39 @@ static void start_other_core(void)
esp_rom_delay_us(100);
}
}

// This function is needed to make the multicore app runnable on a unicore bootloader (built with FREERTOS UNICORE).
// It does some cache settings for other CPUs.
void IRAM_ATTR do_multicore_settings(void)
{
// We intentionally do not check the cache settings before changing them,
// because it helps to get the application to run on older bootloaders.
#ifdef CONFIG_IDF_TARGET_ESP32
if (!efuse_ll_get_disable_app_cpu()) {
Cache_Read_Disable(1);
Cache_Flush(1);
DPORT_REG_SET_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
// We do not enable cache for CPU1 now because it will be done later in start_other_core().
}
#endif

cache_bus_mask_t cache_bus_mask_core0 = cache_ll_l1_get_enabled_bus(0);
#ifndef CONFIG_IDF_TARGET_ESP32
// 1. disable the cache before changing its settings.
Cache_Disable_ICache();
Cache_Disable_DCache();
#endif
for (unsigned core = 1; core < SOC_CPU_CORES_NUM; core++) {
// 2. change cache settings. All cores must have the same settings.
cache_ll_l1_enable_bus(core, cache_bus_mask_core0);
}
#ifndef CONFIG_IDF_TARGET_ESP32
// 3. enable the cache after changing its settings.
Cache_Enable_ICache(0);
Cache_Enable_DCache(0);
#endif
}
#endif // !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE

/*
Expand Down Expand Up @@ -312,6 +349,14 @@ void IRAM_ATTR call_start_cpu0(void)
memset(&_rtc_bss_start, 0, (&_rtc_bss_end - &_rtc_bss_start) * sizeof(_rtc_bss_start));
}

#if CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
ESP_EARLY_LOGI(TAG, "Unicore app");
#else
ESP_EARLY_LOGI(TAG, "Multicore app");
// It helps to fix missed cache settings for other cores. It happens when bootloader is unicore.
do_multicore_settings();
#endif

#if CONFIG_IDF_TARGET_ESP32S2
/* Configure the mode of instruction cache : cache size, cache associated ways, cache line size. */
extern void esp_config_instruction_cache_mode(void);
Expand Down
32 changes: 32 additions & 0 deletions components/hal/esp32/include/hal/cache_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,38 @@ static inline void cache_ll_l1_enable_bus(uint32_t cache_id, cache_bus_mask_t ma
}
}

/**
* Returns enabled buses for a given core
*
* @param cache_id cache ID (when l1 cache is per core)
*
* @return State of enabled buses
*/
__attribute__((always_inline))
static inline cache_bus_mask_t cache_ll_l1_get_enabled_bus(uint32_t cache_id)
{
cache_bus_mask_t mask = 0;
HAL_ASSERT(cache_id == 0 || cache_id == 1);
if (cache_id == 0) {
uint32_t bus_mask= DPORT_REG_READ(DPORT_PRO_CACHE_CTRL1_REG);
mask |= (!(bus_mask & DPORT_PRO_CACHE_MASK_IRAM0)) ? CACHE_BUS_IBUS0 : 0;
mask |= (!(bus_mask & DPORT_PRO_CACHE_MASK_IRAM1)) ? CACHE_BUS_IBUS1 : 0;
mask |= (!(bus_mask & DPORT_PRO_CACHE_MASK_IROM0)) ? CACHE_BUS_IBUS2 : 0;

mask |= (!(bus_mask & DPORT_PRO_CACHE_MASK_DROM0)) ? CACHE_BUS_DBUS0 : 0;
mask |= (!(bus_mask & DPORT_PRO_CACHE_MASK_DRAM1)) ? CACHE_BUS_DBUS1 : 0;
} else {
uint32_t bus_mask= DPORT_REG_READ(DPORT_APP_CACHE_CTRL1_REG);
mask |= (!(bus_mask & DPORT_APP_CACHE_MASK_IRAM0)) ? CACHE_BUS_IBUS0 : 0;
mask |= (!(bus_mask & DPORT_APP_CACHE_MASK_IRAM1)) ? CACHE_BUS_IBUS1 : 0;
mask |= (!(bus_mask & DPORT_APP_CACHE_MASK_IROM0)) ? CACHE_BUS_IBUS2 : 0;

mask |= (!(bus_mask & DPORT_APP_CACHE_MASK_DROM0)) ? CACHE_BUS_DBUS0 : 0;
mask |= (!(bus_mask & DPORT_APP_CACHE_MASK_DRAM1)) ? CACHE_BUS_DBUS1 : 0;
}
return mask;
}

/**
* Disable the Cache Buses
*
Expand Down
31 changes: 31 additions & 0 deletions components/hal/esp32s3/include/hal/cache_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,37 @@ static inline void cache_ll_l1_enable_bus(uint32_t cache_id, cache_bus_mask_t ma
REG_CLR_BIT(EXTMEM_DCACHE_CTRL1_REG, dbus_mask);
}

/**
* Returns enabled buses for a given core
*
* @param cache_id cache ID (when l1 cache is per core)
*
* @return State of enabled buses
*/
__attribute__((always_inline))
static inline cache_bus_mask_t cache_ll_l1_get_enabled_bus(uint32_t cache_id)
{
cache_bus_mask_t mask = 0;
HAL_ASSERT(cache_id == 0 || cache_id == 1);
//On esp32s3, only `CACHE_BUS_IBUS0` and `CACHE_BUS_DBUS0` are supported. Use `cache_ll_l1_get_bus()` to get your bus first

uint32_t ibus_mask = REG_READ(EXTMEM_ICACHE_CTRL1_REG);
if (cache_id == 0) {
mask |= (!(ibus_mask & EXTMEM_ICACHE_SHUT_CORE0_BUS)) ? CACHE_BUS_IBUS0 : 0;
} else {
mask |= (!(ibus_mask & EXTMEM_ICACHE_SHUT_CORE1_BUS)) ? CACHE_BUS_IBUS0 : 0;
}

uint32_t dbus_mask = REG_READ(EXTMEM_DCACHE_CTRL1_REG);
if (cache_id == 1) {
mask |= (!(dbus_mask & EXTMEM_DCACHE_SHUT_CORE0_BUS)) ? CACHE_BUS_DBUS0 : 0;
} else {
mask |= (!(dbus_mask & EXTMEM_DCACHE_SHUT_CORE1_BUS)) ? CACHE_BUS_DBUS0 : 0;
}

return mask;
}

/**
* Disable the Cache Buses
*
Expand Down

0 comments on commit 1b608a1

Please sign in to comment.