瀏覽代碼

components/esp32: clean up cpu_start

Move CPU region protection setup into soc/cpu.h
change tabs to spaces
remove unused extern declarations
use RTC_WDTCONFIG0 instead of numeric address (still need to fix BB reg)
Ivan Grokhotkov 9 年之前
父節點
當前提交
0290a34b55
共有 3 個文件被更改,包括 113 次插入171 次删除
  1. 2 30
      components/bootloader/src/main/bootloader_start.c
  2. 76 141
      components/esp32/cpu_start.c
  3. 35 0
      components/esp32/include/soc/cpu.h

+ 2 - 30
components/bootloader/src/main/bootloader_start.c

@@ -24,6 +24,7 @@
 #include "rom/crc.h"
 
 #include "soc/soc.h"
+#include "soc/cpu.h"
 #include "soc/dport_reg.h"
 #include "soc/io_mux_reg.h"
 #include "soc/efuse_reg.h"
@@ -60,36 +61,7 @@ void IRAM_ATTR set_cache_and_start_app(uint32_t drom_addr,
 
 void IRAM_ATTR call_start_cpu0()
 {
-    //Make page 0 access raise an exception
-    //Also some other unused pages so we can catch weirdness
-    //ToDo: this but nicer.
-    asm volatile (\
-                  "movi a4,0x00000000\n" \
-                  "movi a5,0xf\n" \
-                  "wdtlb a5,a4\n" \
-                  "witlb a5,a4\n" \
-                  "movi a4,0x80000000\n" \
-                  "wdtlb a5,a4\n" \
-                  "witlb a5,a4\n" \
-                  "movi a4,0xa0000000\n" \
-                  "wdtlb a5,a4\n" \
-                  "witlb a5,a4\n" \
-                  "movi a4,0xc0000000\n" \
-                  "wdtlb a5,a4\n" \
-                  "witlb a5,a4\n" \
-                  "movi a4,0xe0000000\n" \
-                  "wdtlb a5,a4\n" \
-                  "witlb a5,a4\n" \
-                  "movi a4,0x20000000\n" \
-                  "movi a5,0x0\n" \
-                  "wdtlb a5,a4\n" \
-                  "witlb a5,a4\n" \
-                  "movi a4,0x40000000\n" \
-                  "movi a5,0x2\n" \
-                  "wdtlb a5,a4\n" \
-                  "witlb a5,a4\n" \
-                  "isync\n" \
-                  :::"a4","a5");
+    cpu_configure_region_protection();
 
     //Clear bss
     memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start));

+ 76 - 141
components/esp32/cpu_start.c

@@ -20,8 +20,10 @@
 #include "rom/ets_sys.h"
 #include "rom/uart.h"
 
+#include "soc/cpu.h"
 #include "soc/dport_reg.h"
 #include "soc/io_mux_reg.h"
+#include "soc/rtc_cntl_reg.h"
 
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
@@ -45,169 +47,104 @@ static void IRAM_ATTR user_start_cpu0(void);
 static void IRAM_ATTR call_user_start_cpu1();
 static void IRAM_ATTR user_start_cpu1(void);
 extern void ets_setup_syscalls(void);
+extern esp_err_t app_main(void *ctx);
 
-
-extern int __cpu1_entry_point;
 extern int _bss_start;
 extern int _bss_end;
 extern int _init_start;
-extern int _init_end;
-extern int _iram_romjumptable_start;
-extern int _iram_romjumptable_end;
-extern int _iram_text_start;
-extern int _iram_text_end;
+extern void (*__init_array_start)(void);
+extern void (*__init_array_end)(void);
+extern volatile int port_xSchedulerRunning[2];
 
 static const char* TAG = "cpu_start";
+static bool app_cpu_started = false;
 
 /*
-We arrive here after the bootloader finished loading the program from flash. The hardware is mostly uninitialized,
-flash cache is down and the app CPU is in reset. We do have a stack, so we can do the initialization in C.
-*/
+ * We arrive here after the bootloader finished loading the program from flash. The hardware is mostly uninitialized,
+ * and the app CPU is in reset. We do have a stack, so we can do the initialization in C.
+ */
 
-static bool app_cpu_started = false;
+void IRAM_ATTR call_user_start_cpu0()
+{
+    //Kill wdt
+    REG_CLR_BIT(RTC_WDTCONFIG0, RTC_CNTL_WDT_FLASHBOOT_MOD_EN);
+    REG_CLR_BIT(0x6001f048, BIT(14)); //DR_REG_BB_BASE+48
+
+    cpu_configure_region_protection();
+
+    //Move exception vectors to IRAM
+    asm volatile (\
+                  "wsr    %0, vecbase\n" \
+                  ::"r"(&_init_start));
+
+    uartAttach();
+    ets_install_uart_printf();
+
+    memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start));
+
+    // Initialize heap allocator
+    heap_alloc_caps_init();
+
+    ESP_EARLY_LOGI(TAG, "Pro cpu up.");
 
-void IRAM_ATTR call_user_start_cpu0() {
-	//Kill wdt
-	REG_CLR_BIT(0x3ff4808c, BIT(10)); //RTCCNTL+8C RTC_WDTCONFIG0 RTC_
-	REG_CLR_BIT(0x6001f048, BIT(14)); //DR_REG_BB_BASE+48
-
-	//Move exception vectors to IRAM
-	asm volatile (\
-		"wsr	%0, vecbase\n" \
-		::"r"(&_init_start));
-
-	uartAttach();
-	ets_install_uart_printf();
-
-	//Make page 0 access raise an exception
-	//Also some other unused pages so we can catch weirdness
-	//ToDo: this but nicer.
-	asm volatile (\
-		"movi a4,0x00000000\n" \
-		"movi a5,0xf\n" \
-		"wdtlb a5,a4\n" \
-		"witlb a5,a4\n" \
-		"movi a4,0x80000000\n" \
-		"wdtlb a5,a4\n" \
-		"witlb a5,a4\n" \
-		"movi a4,0xa0000000\n" \
-		"wdtlb a5,a4\n" \
-		"witlb a5,a4\n" \
-		"movi a4,0xc0000000\n" \
-		"wdtlb a5,a4\n" \
-		"witlb a5,a4\n" \
-		"movi a4,0xe0000000\n" \
-		"wdtlb a5,a4\n" \
-		"witlb a5,a4\n" \
-		"movi a4,0x20000000\n" \
-		"movi a5,0x0\n" \
-		"wdtlb a5,a4\n" \
-		"witlb a5,a4\n" \
-		"movi a4,0x40000000\n" \
-		"movi a5,0x2\n" \
-		"wdtlb a5,a4\n" \
-		"witlb a5,a4\n" \
-		"isync\n" \
-		:::"a4","a5");
-
-	memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start));
-
-	// Initialize heap allocator
-	heap_alloc_caps_init();
-
-	ESP_EARLY_LOGI(TAG, "Pro cpu up.");
-    
 #ifndef CONFIG_FREERTOS_UNICORE
-	ESP_EARLY_LOGI(TAG, "Starting app cpu, entry point is %p", call_user_start_cpu1);
+    ESP_EARLY_LOGI(TAG, "Starting app cpu, entry point is %p", 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);
-	ets_set_appcpu_boot_addr((uint32_t)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);
+    ets_set_appcpu_boot_addr((uint32_t)call_user_start_cpu1);
 
-	while (!app_cpu_started) {
-		ets_delay_us(100);
-	}
+    while (!app_cpu_started) {
+        ets_delay_us(100);
+    }
 #else
-	ESP_EARLY_LOGI(TAG, "Single core mode");
-	CLEAR_PERI_REG_MASK(APPCPU_CTRL_REG_B, DPORT_APPCPU_CLKGATE_EN);
+    ESP_EARLY_LOGI(TAG, "Single core mode");
+    CLEAR_PERI_REG_MASK(APPCPU_CTRL_REG_B, DPORT_APPCPU_CLKGATE_EN);
 #endif
-	ESP_EARLY_LOGI(TAG, "Pro cpu start user code");
-	user_start_cpu0();
+    ESP_EARLY_LOGI(TAG, "Pro cpu start user code");
+    user_start_cpu0();
 }
 
 
-extern int _init_start;
-
-void IRAM_ATTR call_user_start_cpu1() {
-	asm volatile (\
-		"wsr	%0, vecbase\n" \
-		::"r"(&_init_start));
-
-	//Make page 0 access raise an exception
-	//Also some other unused pages so we can catch weirdness
-	//ToDo: this but nicer.
-	asm volatile (\
-		"movi a4,0x00000000\n" \
-		"movi a5,0xf\n" \
-		"wdtlb a5,a4\n" \
-		"witlb a5,a4\n" \
-		"movi a4,0x80000000\n" \
-		"wdtlb a5,a4\n" \
-		"witlb a5,a4\n" \
-		"movi a4,0xa0000000\n" \
-		"wdtlb a5,a4\n" \
-		"witlb a5,a4\n" \
-		"movi a4,0xc0000000\n" \
-		"wdtlb a5,a4\n" \
-		"witlb a5,a4\n" \
-		"movi a4,0xe0000000\n" \
-		"wdtlb a5,a4\n" \
-		"witlb a5,a4\n" \
-		"movi a4,0x20000000\n" \
-		"movi a5,0x0\n" \
-		"wdtlb a5,a4\n" \
-		"witlb a5,a4\n" \
-		"movi a4,0x40000000\n" \
-		"movi a5,0x2\n" \
-		"wdtlb a5,a4\n" \
-		"witlb a5,a4\n" \
-		"isync\n" \
-		:::"a4","a5");
-	
-	ESP_EARLY_LOGI(TAG, "App cpu up.");
-	app_cpu_started = 1;
-	user_start_cpu1();
-}
+void IRAM_ATTR call_user_start_cpu1()
+{
+    asm volatile (\
+                  "wsr    %0, vecbase\n" \
+                  ::"r"(&_init_start));
 
-extern volatile int port_xSchedulerRunning[2];
+    cpu_configure_region_protection();
 
-void IRAM_ATTR user_start_cpu1(void) {
-	// Wait for FreeRTOS initialization to finish on PRO CPU
-	while (port_xSchedulerRunning[0] == 0) {
-	    ;
-	}
-	ESP_LOGI(TAG, "Starting scheduler on APP CPU.");
-	xPortStartScheduler();
+    ESP_EARLY_LOGI(TAG, "App cpu up.");
+    app_cpu_started = 1;
+    user_start_cpu1();
 }
 
-extern void (*__init_array_start)(void);
-extern void (*__init_array_end)(void);
+void IRAM_ATTR user_start_cpu1(void)
+{
+    // Wait for FreeRTOS initialization to finish on PRO CPU
+    while (port_xSchedulerRunning[0] == 0) {
+        ;
+    }
+    ESP_LOGI(TAG, "Starting scheduler on APP CPU.");
+    xPortStartScheduler();
+}
 
-static void do_global_ctors(void) {
+static void do_global_ctors(void)
+{
     void (**p)(void);
-    for(p = &__init_array_start; p != &__init_array_end; ++p)
+    for (p = &__init_array_start; p != &__init_array_end; ++p) {
         (*p)();
+    }
 }
 
-extern esp_err_t app_main(void *ctx);
-
-void user_start_cpu0(void) {
+void user_start_cpu0(void)
+{
     ets_setup_syscalls();
-	do_global_ctors();
-	esp_ipc_init();
-	spi_flash_init();
+    do_global_ctors();
+    esp_ipc_init();
+    spi_flash_init();
 
 #if CONFIG_WIFI_ENABLED
     esp_err_t ret = nvs_flash_init(5, 3);
@@ -216,20 +153,18 @@ void user_start_cpu0(void) {
     }
 
     system_init();
-
     esp_event_init(NULL, NULL);
-
     tcpip_adapter_init();
 #endif
 
 #if CONFIG_WIFI_ENABLED && CONFIG_WIFI_AUTO_STARTUP
 #include "esp_wifi.h"
-	esp_wifi_startup(app_main, NULL);
+    esp_wifi_startup(app_main, NULL);
 #else
-	app_main(NULL);
+    app_main(NULL);
 #endif
 
-	ESP_LOGI(TAG, "Starting scheduler on PRO CPU.");
-	vTaskStartScheduler();
+    ESP_LOGI(TAG, "Starting scheduler on PRO CPU.");
+    vTaskStartScheduler();
 }
 

+ 35 - 0
components/esp32/include/soc/cpu.h

@@ -33,4 +33,39 @@ static inline bool cpu_in_interrupt_context(void)
     return (ps & PS_UM) == 0;
 }
 
+/* Functions to set page attributes for Region Protection option in the CPU.
+ * See Xtensa ISA Reference manual for explanation of arguments (section 4.6.3.2).
+ */
+
+static inline void cpu_write_dtlb(uint32_t vpn, unsigned attr)
+{
+    asm volatile ("wdtlb  %1, %0; dsync\n" :: "r" (vpn), "r" (attr));
+}
+
+
+static inline void cpu_write_itlb(unsigned vpn, unsigned attr)
+{
+    asm volatile ("witlb  %1, %0; isync\n" :: "r" (vpn), "r" (attr));
+}
+
+/* Make page 0 access raise an exception.
+ * Also protect some other unused pages so we can catch weirdness.
+ * Useful attribute values:
+ * 0 — cached, RW
+ * 2 — bypass cache, RWX (default value after CPU reset)
+ * 15 — no access, raise exception
+ */
+
+static inline void cpu_configure_region_protection()
+{
+    const uint32_t pages_to_protect[] = {0x00000000, 0x80000000, 0xa0000000, 0xc0000000, 0xe0000000};
+    for (int i = 0; i < sizeof(pages_to_protect)/sizeof(pages_to_protect[0]); ++i) {
+        cpu_write_dtlb(pages_to_protect[i], 0xf);
+        cpu_write_itlb(pages_to_protect[i], 0xf);
+    }
+    cpu_write_dtlb(0x20000000, 0);
+    cpu_write_itlb(0x20000000, 0);
+}
+
+
 #endif