Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save projectgus/29e9f3b3d344bfc4d4a0371cc314683c to your computer and use it in GitHub Desktop.
Save projectgus/29e9f3b3d344bfc4d4a0371cc314683c to your computer and use it in GitHub Desktop.
From bd3a676daae9c94afda2720d2e023312cf2d019d Mon Sep 17 00:00:00 2001
From: Angus Gratton <angus@espressif.com>
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