From 0f43a2620d0f9d89f906661441519312e34c9361 Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Wed, 5 Feb 2020 19:57:40 +0800 Subject: [PATCH] esp_system: component init functions macro Allows components to declare initialization function, such that the startup code does not have direct dependency on the component. --- components/esp32/ld/esp32.project.ld.in | 6 +++ components/esp32s2/ld/esp32s2.project.ld.in | 4 ++ .../private_include/startup_internal.h | 37 +++++++++++++++++++ components/esp_system/startup.c | 17 +++++++++ 4 files changed, 64 insertions(+) create mode 100644 components/esp_system/private_include/startup_internal.h diff --git a/components/esp32/ld/esp32.project.ld.in b/components/esp32/ld/esp32.project.ld.in index 369ebb5d6..96557ed62 100644 --- a/components/esp32/ld/esp32.project.ld.in +++ b/components/esp32/ld/esp32.project.ld.in @@ -208,6 +208,10 @@ SECTIONS _coredump_dram_end = ABSOLUTE(.); /* should be placed after coredump mapping */ + _esp_system_init_fn_array_start = ABSOLUTE(.); + KEEP (*(SORT(.esp_system_init_fn) SORT(.esp_system_init_fn.*))) + _esp_system_init_fn_array_end = ABSOLUTE(.); + mapping[dram0_data] _data_end = ABSOLUTE(.); @@ -278,6 +282,7 @@ SECTIONS mapping[flash_rodata] + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) @@ -297,6 +302,7 @@ SECTIONS __init_array_start = ABSOLUTE(.); KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .ctors SORT(.ctors.*))) __init_array_end = ABSOLUTE(.); + KEEP (*crtbegin.*(.dtors)) KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors)) KEEP (*(SORT(.dtors.*))) diff --git a/components/esp32s2/ld/esp32s2.project.ld.in b/components/esp32s2/ld/esp32s2.project.ld.in index cffa42e9c..71b24f706 100644 --- a/components/esp32s2/ld/esp32s2.project.ld.in +++ b/components/esp32s2/ld/esp32s2.project.ld.in @@ -214,6 +214,10 @@ SECTIONS _coredump_dram_end = ABSOLUTE(.); /* should be placed after coredump mapping */ + _esp_system_init_fn_array_start = ABSOLUTE(.); + KEEP (*(SORT(.esp_system_init_fn) SORT(.esp_system_init_fn.*))) + _esp_system_init_fn_array_end = ABSOLUTE(.); + mapping[dram0_data] _data_end = ABSOLUTE(.); diff --git a/components/esp_system/private_include/startup_internal.h b/components/esp_system/private_include/startup_internal.h new file mode 100644 index 000000000..4d18c950e --- /dev/null +++ b/components/esp_system/private_include/startup_internal.h @@ -0,0 +1,37 @@ +// Copyright 2015-2018 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. + +#pragma once + +#include "esp_attr.h" +typedef struct { + void (*fn)(void); + uint32_t cores; +} esp_system_init_fn_t; + +/* + * Declare an component initialization function that will execute on the specified cores (ex. if BIT0 == 1, will execute + * on CORE0, CORE1 if BIT1 and so on). + * + * @note Initialization functions should be placed in a compilation unit where at least one other + * symbol is referenced 'meaningfully' in another compilation unit, otherwise this gets discarded during linking. (By + * 'meaningfully' we mean the reference should not itself get optimized out by the compiler/discarded by the linker). + */ +#define ESP_SYSTEM_INIT_FN(f, c, ...) \ +static void __attribute__((used)) __VA_ARGS__ __esp_system_init_fn_##f(void); \ +static __attribute__((used)) esp_system_init_fn_t _SECTION_ATTR_IMPL(".esp_system_init_fn", f) \ + esp_system_init_fn_##f = { .fn = ( __esp_system_init_fn_##f), .cores = (c) }; \ +static __attribute__((used)) __VA_ARGS__ void __esp_system_init_fn_##f(void) // [refactor-todo] this can be made public API if we allow components to declare init functions, + // instead of calling them explicitly + diff --git a/components/esp_system/startup.c b/components/esp_system/startup.c index 517d86c48..1eeda8d5d 100644 --- a/components/esp_system/startup.c +++ b/components/esp_system/startup.c @@ -97,6 +97,20 @@ static void do_global_ctors(void) } } +static void do_system_init_fn(void) +{ + extern esp_system_init_fn_t _esp_system_init_fn_array_start; + extern esp_system_init_fn_t _esp_system_init_fn_array_end; + + esp_system_init_fn_t *p; + + for (p = &_esp_system_init_fn_array_end - 1; p >= &_esp_system_init_fn_array_start; --p) { + if (p->cores & BIT(cpu_hal_get_core_id())) { + (*(p->fn))(); + } + } +} + static void main_task(void* args) { #if !CONFIG_FREERTOS_UNICORE @@ -312,6 +326,7 @@ void IRAM_ATTR start_cpu0_default(void) esp_dport_access_int_init(); #endif + spi_flash_init(); /* init default OS-aware flash access critical section */ spi_flash_guard_set(&g_flash_guard_default_ops); @@ -345,6 +360,8 @@ void IRAM_ATTR start_cpu0_default(void) #endif #endif + do_system_init_fn(); + portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main", ESP_TASK_MAIN_STACK, NULL, ESP_TASK_MAIN_PRIO, NULL, 0);