Created
November 9, 2017 21:20
-
-
Save projectgus/29e9f3b3d344bfc4d4a0371cc314683c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From bd3a676daae9c94afda2720d2e023312cf2d019d Mon Sep 17 00:00:00 2001 | |
From: Angus Gratton <[email protected]> | |
Date: Tue, 11 Jul 2017 17:59:02 +0800 | |
Subject: [PATCH] WIP allow first 128KB of DRAM to be allocated statically | |
- Moves stacks to end of RAM | |
- Doesn't yet provide a way to block out this RAM from heap | |
--- | |
components/bootloader/src/main/bootloader_jump.S | 55 ++++++++++++++++++++++ | |
components/bootloader/src/main/bootloader_start.c | 23 +++++---- | |
components/bootloader/src/main/esp32.bootloader.ld | 3 +- | |
components/esp32/bootstrap_cpu1.S | 38 +++++++++++++++ | |
components/esp32/cpu_start.c | 23 +++++---- | |
5 files changed, 125 insertions(+), 17 deletions(-) | |
create mode 100644 components/bootloader/src/main/bootloader_jump.S | |
create mode 100644 components/esp32/bootstrap_cpu1.S | |
diff --git a/components/bootloader/src/main/bootloader_jump.S b/components/bootloader/src/main/bootloader_jump.S | |
new file mode 100644 | |
index 000000000..3e4b8c04b | |
--- /dev/null | |
+++ b/components/bootloader/src/main/bootloader_jump.S | |
@@ -0,0 +1,55 @@ | |
+// Copyright 2017 Espressif Systems (Shanghai) PTE LTD | |
+// | |
+// Licensed under the Apache License, Version 2.0 (the "License"); | |
+// you may not use this file except in compliance with the License. | |
+// You may obtain a copy of the License at | |
+ | |
+// http://www.apache.org/licenses/LICENSE-2.0 | |
+// | |
+// Unless required by applicable law or agreed to in writing, software | |
+// distributed under the License is distributed on an "AS IS" BASIS, | |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
+// See the License for the specific language governing permissions and | |
+// limitations under the License. | |
+ | |
+.data | |
+.align 4 | |
+bootloader_jump_scratch_space: | |
+.word 0 | |
+.word 0 | |
+ | |
+.text | |
+ /* Function to reset the stack pointer to beginning of bootloader bss, | |
+ and jump to a given entry point function. | |
+ */ | |
+ .global bootloader_reset_stack_and_jump_to | |
+ .type bootloader_reset_stack_and_jump_to,@function | |
+ .section ".iram1" | |
+ .align 4 | |
+bootloader_reset_stack_and_jump_to: | |
+ entry sp, 16 /* We are called via call8/etc, so need to rotate */ | |
+ | |
+ /* save args */ | |
+ movi a0, bootloader_jump_scratch_space | |
+ s32i a2, a0, 0 /* dest addr */ | |
+ s32i a3, a0, 4 /* new stack pointer */ | |
+ | |
+ /* Reset register window and clobber registers */ | |
+ movi a0, 1 | |
+ wsr a0, WindowStart | |
+ movi a0, 0 | |
+ wsr a0, WindowBase | |
+ | |
+ /* Note: perhaps we should clear some PS fields here? */ | |
+ | |
+ /* reload args */ | |
+ movi a0, bootloader_jump_scratch_space | |
+ l32i a2, a0, 0 /* dest addr */ | |
+ l32i a3, a0, 4 /* new stack pointer */ | |
+ | |
+ /* initialize a call8-compatible stack, see ISA RM 8.7 */ | |
+ addi sp, a3, -16 /* save area */ | |
+ addi a3, sp, 32 /* 16 past save area */ | |
+ s32e a3, sp, -12 /* write pointer to end of stack */ | |
+ isync | |
+ jx a2 | |
diff --git a/components/bootloader/src/main/bootloader_start.c b/components/bootloader/src/main/bootloader_start.c | |
index fd062a5f9..b7b96368f 100644 | |
--- a/components/bootloader/src/main/bootloader_start.c | |
+++ b/components/bootloader/src/main/bootloader_start.c | |
@@ -61,7 +61,8 @@ flash cache is down and the app CPU is in reset. We do have a stack, so we can d | |
*/ | |
-void bootloader_main(); | |
+static void bootloader_main(); | |
+static void bootloader_call_main() __attribute__((noreturn)); | |
static void unpack_load_app(const esp_partition_pos_t *app_node); | |
void print_flash_info(const esp_image_header_t* pfhdr); | |
static void set_cache_and_start_app(uint32_t drom_addr, | |
@@ -76,6 +77,8 @@ static void clock_configure(void); | |
static void uart_console_configure(void); | |
static void wdt_reset_check(void); | |
+void bootloader_reset_stack_and_jump_to(void *destination, void *new_top_of_stack) __attribute__((noreturn)); | |
+ | |
void IRAM_ATTR call_start_cpu0() | |
{ | |
cpu_configure_region_protection(); | |
@@ -106,7 +109,8 @@ void IRAM_ATTR call_start_cpu0() | |
DPORT_REG_CLR_BIT(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DROM0); | |
DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DROM0); | |
- bootloader_main(); | |
+ extern int _bootloader_dram_start; | |
+ bootloader_reset_stack_and_jump_to(bootloader_call_main, &_bootloader_dram_start); | |
} | |
@@ -228,6 +232,13 @@ static bool ota_select_valid(const esp_ota_select_entry_t *s) | |
return s->ota_seq != UINT32_MAX && s->crc == ota_select_crc(s); | |
} | |
+static void bootloader_call_main() | |
+{ | |
+ bootloader_main(); | |
+ ESP_LOGI(TAG, "Halting."); | |
+ while(1) {} | |
+} | |
+ | |
/** | |
* @function : bootloader_main | |
* @description: entry function of 2nd bootloader | |
@@ -586,12 +597,8 @@ static void set_cache_and_start_app( | |
// Application will need to do Cache_Flush(1) and Cache_Read_Enable(1) | |
ESP_LOGD(TAG, "start: 0x%08x", entry_addr); | |
- typedef void (*entry_t)(void); | |
- entry_t entry = ((entry_t) entry_addr); | |
- | |
- // TODO: we have used quite a bit of stack at this point. | |
- // use "movsp" instruction to reset stack back to where ROM stack starts. | |
- (*entry)(); | |
+ /* TODO: use a soc_memory_layout.h constant here instead of 0x400000000... */ | |
+ bootloader_reset_stack_and_jump_to((void *)entry_addr, (void *)0x40000000); | |
} | |
static void update_flash_config(const esp_image_header_t* pfhdr) | |
diff --git a/components/bootloader/src/main/esp32.bootloader.ld b/components/bootloader/src/main/esp32.bootloader.ld | |
index 500478814..2557485c2 100644 | |
--- a/components/bootloader/src/main/esp32.bootloader.ld | |
+++ b/components/bootloader/src/main/esp32.bootloader.ld | |
@@ -17,7 +17,7 @@ MEMORY | |
dport0_seg (RW) : org = 0x3FF00000, len = 0x10 /* IO */ | |
iram_seg (RWX) : org = 0x40080000, len = 0x400 /* 1k of IRAM used by bootloader functions which need to flush/enable APP CPU cache */ | |
iram_pool_1_seg (RWX) : org = 0x40078000, len = 0x8000 /* IRAM POOL1, used for APP CPU cache. We can abuse it in bootloader because APP CPU is still held in reset, until we enable APP CPU cache */ | |
- dram_seg (RW) : org = 0x3FFF0000, len = 0x10000 /* 64k at the end of DRAM, after ROM bootloader stack */ | |
+ dram_seg (RW) : org = 0x3FFFE000, len = 0x2000 /* 8KB at the end of DRAM, after ROM bootloader stack. Can be made bigger if necessary. */ | |
} | |
/* Default entry point: */ | |
@@ -48,6 +48,7 @@ SECTIONS | |
.dram0.bss (NOLOAD) : | |
{ | |
. = ALIGN (8); | |
+ _bootloader_dram_start = ABSOLUTE(.); | |
_bss_start = ABSOLUTE(.); | |
*(.dynsbss) | |
*(.sbss) | |
diff --git a/components/esp32/bootstrap_cpu1.S b/components/esp32/bootstrap_cpu1.S | |
new file mode 100644 | |
index 000000000..9ca0ef6f7 | |
--- /dev/null | |
+++ b/components/esp32/bootstrap_cpu1.S | |
@@ -0,0 +1,38 @@ | |
+// Copyright 2017 Espressif Systems (Shanghai) PTE LTD | |
+// | |
+// Licensed under the Apache License, Version 2.0 (the "License"); | |
+// you may not use this file except in compliance with the License. | |
+// You may obtain a copy of the License at | |
+ | |
+// http://www.apache.org/licenses/LICENSE-2.0 | |
+// | |
+// Unless required by applicable law or agreed to in writing, software | |
+// distributed under the License is distributed on an "AS IS" BASIS, | |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
+// See the License for the specific language governing permissions and | |
+// limitations under the License. | |
+ | |
+.extern call_start_cpu1 | |
+.extern cpu1_stack_end | |
+ | |
+ /* Function to set the CPU1 stack pointer to cpu1_stack_end, | |
+ then jump to a given entry point function. | |
+ */ | |
+ .global bootstrap_cpu1 | |
+ .type bootstrap_cpu1,@function | |
+ .align 4 | |
+bootstrap_cpu1: | |
+ /* Reset register window and clobber registers */ | |
+ movi a0, 1 | |
+ wsr a0, WindowStart | |
+ movi a0, 0 | |
+ wsr a0, WindowBase | |
+ | |
+ movi a0, cpu1_stack_end | |
+ l32i a0, a0, 0 | |
+ addi sp, a0, -16 /* save area */ | |
+ addi a0, sp, 32 /* 16 past save area */ | |
+ s32e a0, sp, -12 /* write pointer to end of stack */ | |
+ isync | |
+ j call_start_cpu1 | |
+ | |
diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c | |
index 858036c67..4085a2670 100644 | |
--- a/components/esp32/cpu_start.c | |
+++ b/components/esp32/cpu_start.c | |
@@ -68,12 +68,12 @@ | |
#define STRINGIFY(s) STRINGIFY2(s) | |
#define STRINGIFY2(s) #s | |
-void start_cpu0(void) __attribute__((weak, alias("start_cpu0_default"))); | |
-void start_cpu0_default(void) IRAM_ATTR; | |
+void start_cpu0(void) __attribute__((weak, alias("start_cpu0_default"))) __attribute__((noreturn)); | |
+void start_cpu0_default(void) IRAM_ATTR __attribute__((noreturn)); | |
#if !CONFIG_FREERTOS_UNICORE | |
-static void IRAM_ATTR call_start_cpu1(); | |
-void start_cpu1(void) __attribute__((weak, alias("start_cpu1_default"))); | |
-void start_cpu1_default(void) IRAM_ATTR; | |
+void IRAM_ATTR call_start_cpu1() __attribute__((noreturn)); | |
+void start_cpu1(void) __attribute__((weak, alias("start_cpu1_default"))) __attribute__((noreturn)); | |
+void start_cpu1_default(void) IRAM_ATTR __attribute__((noreturn)); | |
static bool app_cpu_started = false; | |
#endif //!CONFIG_FREERTOS_UNICORE | |
@@ -90,6 +90,9 @@ extern void (*__init_array_start)(void); | |
extern void (*__init_array_end)(void); | |
extern volatile int port_xSchedulerRunning[2]; | |
+/* TODO: use a constant in soc_memory_layout.h for this not hardcoded */ | |
+uint32_t cpu1_stack_end = 0x3fff8000; | |
+ | |
static const char* TAG = "cpu_start"; | |
/* | |
@@ -97,7 +100,7 @@ static const char* TAG = "cpu_start"; | |
* and the app CPU is in reset. We do have a stack, so we can do the initialization in C. | |
*/ | |
-void IRAM_ATTR call_start_cpu0() | |
+void IRAM_ATTR __attribute__((noreturn)) call_start_cpu0() | |
{ | |
#if CONFIG_FREERTOS_UNICORE | |
RESET_REASON rst_reas[1]; | |
@@ -137,7 +140,8 @@ void IRAM_ATTR call_start_cpu0() | |
ESP_EARLY_LOGI(TAG, "Pro cpu up."); | |
#if !CONFIG_FREERTOS_UNICORE | |
- ESP_EARLY_LOGI(TAG, "Starting app cpu, entry point is %p", call_start_cpu1); | |
+ extern void bootstrap_cpu1(void); /* asm function, calls call_start_cpu1() */ | |
+ ESP_EARLY_LOGI(TAG, "Starting app cpu, entry point is %p -> %p", call_start_cpu1, bootstrap_cpu1); | |
//Flush and enable icache for APP CPU | |
Cache_Flush(1); | |
Cache_Read_Enable(1); | |
@@ -152,7 +156,7 @@ void IRAM_ATTR call_start_cpu0() | |
DPORT_SET_PERI_REG_MASK(DPORT_APPCPU_CTRL_A_REG, DPORT_APPCPU_RESETTING); | |
DPORT_CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_A_REG, DPORT_APPCPU_RESETTING); | |
} | |
- ets_set_appcpu_boot_addr((uint32_t)call_start_cpu1); | |
+ ets_set_appcpu_boot_addr((intptr_t)&bootstrap_cpu1); | |
while (!app_cpu_started) { | |
ets_delay_us(100); | |
@@ -182,6 +186,7 @@ static void wdt_reset_cpu1_info_enable(void) | |
DPORT_REG_CLR_BIT(DPORT_APP_CPU_RECORD_CTRL_REG, DPORT_APP_CPU_RECORD_ENABLE); | |
} | |
+/* called from bootstrap_cpu1() */ | |
void IRAM_ATTR call_start_cpu1() | |
{ | |
asm volatile (\ | |
@@ -287,6 +292,7 @@ void start_cpu0_default(void) | |
ESP_TASK_MAIN_PRIO, NULL, 0); | |
ESP_LOGI(TAG, "Starting scheduler on PRO CPU."); | |
vTaskStartScheduler(); | |
+ abort(); /* abort() here indicates there wasn't enough free memory to start scheduler */ | |
} | |
#if !CONFIG_FREERTOS_UNICORE | |
@@ -313,6 +319,7 @@ void start_cpu1_default(void) | |
ESP_EARLY_LOGI(TAG, "Starting scheduler on APP CPU."); | |
xPortStartScheduler(); | |
+ abort(); /* abort() here indicates something went wrong starting scheduler */ | |
} | |
#endif //!CONFIG_FREERTOS_UNICORE | |
-- | |
2.13.2 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment