mirror of
https://fuchsia.googlesource.com/third_party/pigweed.googlesource.com/pigweed/pigweed
synced 2024-09-21 06:12:09 +00:00
110 lines
4.3 KiB
C
110 lines
4.3 KiB
C
|
// Copyright 2020 The Pigweed Authors
|
||
|
//
|
||
|
// 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
|
||
|
//
|
||
|
// https://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.
|
||
|
|
||
|
// !!!WARNING!!!
|
||
|
//
|
||
|
// Some of the code in this file is run without static initialization expected
|
||
|
// by C/C++. Any accesses to statically initialized objects/variables before
|
||
|
// memory is initialized will result in undefined values and violates the C
|
||
|
// specification. Only code run after memory initialization is complete will be
|
||
|
// compliant and truly safe to run. In general, make early initialization code
|
||
|
// run AFTER memory initialization has completed unless it is ABSOLUTELY
|
||
|
// NECESSARY to modify the way memory is initialized.
|
||
|
//
|
||
|
// This file is similar to a traditional assembly startup file. It turns out
|
||
|
// that everything typically done in ARMv7-M assembly startup can be done
|
||
|
// straight from C code. This makes startup code easier to maintain, modify,
|
||
|
// and read.
|
||
|
//
|
||
|
// When execution begins due to SoC power-on (or the device is reset), three
|
||
|
// key things must happen to properly enter C++ execution context:
|
||
|
// 1. Static variables must be loaded from flash to RAM.
|
||
|
// 2. Zero-initialized variables must be zero-initialized.
|
||
|
// 3. Statically allocated objects must have their constructors run.
|
||
|
// The SoC doesn't inherently have a notion of how to do this, so this is
|
||
|
// handled in StaticInit();
|
||
|
//
|
||
|
// Following this, execution is handed over to pw_PreMainInit() to facilitate
|
||
|
// platform, project, or application pre-main initialization. When
|
||
|
// pw_PreMainInit() returns, main() is executed.
|
||
|
//
|
||
|
// The simple flow is as follows:
|
||
|
// 1. Power on
|
||
|
// 2. PC and SP set (from vector_table by SoC, or by bootloader)
|
||
|
// 3. pw_BootEntry()
|
||
|
// 3.1. Static-init RAM (.data, .bss, C++ constructors)
|
||
|
// 3.2. pw_PreMainInit()
|
||
|
// 3.3. main()
|
||
|
|
||
|
#include <stdbool.h>
|
||
|
#include <stdint.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "pw_boot_armv7m/boot.h"
|
||
|
#include "pw_preprocessor/compiler.h"
|
||
|
|
||
|
// Extern symbols provided by linker script.
|
||
|
// These symbols tell us where various memory sections start and end.
|
||
|
extern uint8_t _pw_static_init_ram_start;
|
||
|
extern uint8_t _pw_static_init_ram_end;
|
||
|
extern uint8_t _pw_static_init_flash_start;
|
||
|
extern uint8_t _pw_zero_init_ram_start;
|
||
|
extern uint8_t _pw_zero_init_ram_end;
|
||
|
|
||
|
// Functions called as part of firmware initialization.
|
||
|
void __libc_init_array(void);
|
||
|
|
||
|
// WARNING: Be EXTREMELY careful when running code before this function
|
||
|
// completes. The context before this function violates the C spec
|
||
|
// (Section 6.7.8, paragraph 10 for example, which requires uninitialized static
|
||
|
// values to be zero-initialized).
|
||
|
void StaticInit(void) {
|
||
|
// Static-init RAM (load static values into ram, .data section init).
|
||
|
memcpy(&_pw_static_init_ram_start,
|
||
|
&_pw_static_init_flash_start,
|
||
|
&_pw_static_init_ram_end - &_pw_static_init_ram_start);
|
||
|
|
||
|
// Zero-init RAM (.bss section init).
|
||
|
memset(&_pw_zero_init_ram_start,
|
||
|
0,
|
||
|
&_pw_zero_init_ram_end - &_pw_zero_init_ram_start);
|
||
|
|
||
|
// Call static constructors.
|
||
|
__libc_init_array();
|
||
|
}
|
||
|
|
||
|
// WARNING: This code is run immediately upon boot, and performs initialization
|
||
|
// of RAM. Note that code running before this function finishes memory
|
||
|
// initialization will violate the C spec (Section 6.7.8, paragraph 10 for
|
||
|
// example, which requires uninitialized static values to be zero-initialized).
|
||
|
// Be EXTREMELY careful when running code before this function finishes RAM
|
||
|
// initialization.
|
||
|
//
|
||
|
// This function runs immediately at boot because it is at index 1 of the
|
||
|
// interrupt vector table.
|
||
|
void pw_BootEntry() {
|
||
|
StaticInit();
|
||
|
|
||
|
// This function is not provided by pw_boot_armv7m, a platform layer, project,
|
||
|
// or application is expected to implement it.
|
||
|
pw_PreMainInit();
|
||
|
|
||
|
// Run main.
|
||
|
main();
|
||
|
|
||
|
// In case main() returns, just sit here until the device is reset.
|
||
|
while (true) {
|
||
|
}
|
||
|
}
|