From ae560594847205154a7b39f1d63d24c9d1bf485c Mon Sep 17 00:00:00 2001 From: ckormanyos Date: Fri, 25 Oct 2024 10:04:09 +0200 Subject: [PATCH] Try hasher 256 on the metal in CI --- .github/workflows/metal.yml | 54 ++++ include/boost/crypt/hash/sha256.hpp | 8 +- include/boost/crypt/utility/algorithm.hpp | 55 ++++ include/boost/crypt/utility/array.hpp | 37 +++ test/metal/.gitignore | 1 + test/metal/app_benchmark_hasher.cpp | 133 +++++++++ .../build/test_app_benchmarks_emulator.py | 131 +++++++++ .../micros/stm32f429/make/single/crt.cpp | 276 ++++++++++++++++++ .../mcal_gcc_cxx_completion_with_stdlib.cpp | 24 ++ .../target/micros/stm32f429/make/stm32f429.ld | 135 +++++++++ 10 files changed, 852 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/metal.yml create mode 100644 include/boost/crypt/utility/algorithm.hpp create mode 100644 test/metal/.gitignore create mode 100644 test/metal/app_benchmark_hasher.cpp create mode 100644 test/metal/target/build/test_app_benchmarks_emulator.py create mode 100644 test/metal/target/micros/stm32f429/make/single/crt.cpp create mode 100644 test/metal/target/micros/stm32f429/make/single/mcal_gcc_cxx_completion_with_stdlib.cpp create mode 100644 test/metal/target/micros/stm32f429/make/stm32f429.ld diff --git a/.github/workflows/metal.yml b/.github/workflows/metal.yml new file mode 100644 index 00000000..9ed32da6 --- /dev/null +++ b/.github/workflows/metal.yml @@ -0,0 +1,54 @@ +# ------------------------------------------------------------------------------ +# Copyright Matt Borland 2023 - 2024. +# Copyright Christopher Kormanyos 2023 - 2024. +# Distributed under the Boost Software License, +# Version 1.0. (See accompanying file LICENSE_1_0.txt +# or copy at http://www.boost.org/LICENSE_1_0.txt) +# ------------------------------------------------------------------------------ + +name: metal +on: + push: + branches: + - master + - develop + - feature/** + pull_request: + types: [opened, synchronize, reopened] +jobs: + benchmark_single-stm32f429-qemu: + runs-on: ubuntu-latest + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: '0' + - name: update-tools + run: | + sudo apt install libncurses5 libpython2.7 + mkdir -p emu_env && cd emu_env + wget --no-check-certificate https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu-rm/10.3-2021.10/gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2 + tar -xf gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2 + wget --no-check-certificate https://github.com/xpack-dev-tools/qemu-arm-xpack/releases/download/v7.1.0-1/xpack-qemu-arm-7.1.0-1-linux-x64.tar.gz + tar -xzf xpack-qemu-arm-7.1.0-1-linux-x64.tar.gz + working-directory: ./test/metal/ + - name: build benchmark_single-stm32f429 + run: | + mkdir -p bin + emu_env/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-g++ -std=c++20 -Wall -Wextra -Wpedantic -Os -g -gdwarf-2 -ffunction-sections -fdata-sections -x c++ -fno-rtti -fno-use-cxa-atexit -fno-exceptions -fno-nonansi-builtins -fno-threadsafe-statics -fno-enforce-eh-specs -fno-inline-functions -mcpu=cortex-m4 -mtune=cortex-m4 -mthumb -mfloat-abi=soft -mno-unaligned-access -mno-long-calls -I../../include -DBOOST_CRYPT_DISABLE_IOSTREAM -DAPP_BENCHMARK_STANDALONE_MAIN app_benchmark_hasher.cpp ./target/micros/stm32f429/make/single/crt.cpp ./target/micros/stm32f429/make/single/mcal_gcc_cxx_completion_with_stdlib.cpp -nostartfiles -Wl,--gc-sections -Wl,-Map,./bin/app_benchmark_hasher.map -T ./target/micros/stm32f429/make/stm32f429.ld --specs=nano.specs --specs=nosys.specs -Wl,--print-memory-usage -o ./bin/app_benchmark_hasher.elf + emu_env/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-objcopy ./bin/app_benchmark_hasher.elf -O ihex ./bin/app_benchmark_hasher.hex + ls -la ./bin/app_benchmark_hasher.elf ./bin/app_benchmark_hasher.hex ./bin/app_benchmark_hasher.map + working-directory: ./test/metal/ + - name: emulate-target stm32f429 + run: | + ./emu_env/xpack-qemu-arm-7.1.0-1/bin/qemu-system-gnuarmeclipse --verbose --mcu STM32F429ZI --nographic --gdb tcp::9999 -d unimp,guest_errors & + working-directory: ./test/metal/ + - name: run-test-on-target + run: | + ./emu_env/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gdb-py ./bin/app_benchmark_hasher.elf -x ./target/build/test_app_benchmarks_emulator.py + qemu_result=$? + echo "qemu_result" "$qemu_result" + echo "qemu_result" "$qemu_result" | grep 'qemu_result 0' + working-directory: ./test/metal/ diff --git a/include/boost/crypt/hash/sha256.hpp b/include/boost/crypt/hash/sha256.hpp index a341279e..03f00a1a 100644 --- a/include/boost/crypt/hash/sha256.hpp +++ b/include/boost/crypt/hash/sha256.hpp @@ -217,6 +217,8 @@ auto sha256_file_impl(utility::file_reader& reader) noexcept -> sha2 } // namespace detail +#ifndef BOOST_CRYPT_DISABLE_IOSTREAM + BOOST_CRYPT_EXPORT inline auto sha256_file(const std::string& filepath) noexcept -> sha256_hasher::return_type { try @@ -248,7 +250,9 @@ BOOST_CRYPT_EXPORT inline auto sha256_file(const char* filepath) noexcept -> sha } } -#ifdef BOOST_CRYPT_HAS_STRING_VIEW +#endif // !BOOST_CRYPT_DISABLE_IOSTREAM + +#if (defined(BOOST_CRYPT_HAS_STRING_VIEW) && !defined(BOOST_CRYPT_DISABLE_IOSTREAM)) BOOST_CRYPT_EXPORT inline auto sha256_file(std::string_view filepath) noexcept -> sha256_hasher::return_type { @@ -263,7 +267,7 @@ BOOST_CRYPT_EXPORT inline auto sha256_file(std::string_view filepath) noexcept - } } -#endif // BOOST_CRYPT_HAS_STRING_VIEW +#endif // BOOST_CRYPT_HAS_STRING_VIEW && !BOOST_CRYPT_DISABLE_IOSTREAM #endif // BOOST_CRYPT_HAS_CUDA diff --git a/include/boost/crypt/utility/algorithm.hpp b/include/boost/crypt/utility/algorithm.hpp new file mode 100644 index 00000000..196aa2d7 --- /dev/null +++ b/include/boost/crypt/utility/algorithm.hpp @@ -0,0 +1,55 @@ +// Copyright 2024 Matt Borland +// Copyright 2024 Christopher Kormanyos +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_CRYPT_UTILITIES_ALGORITHM_HPP +#define BOOST_CRYPT_UTILITIES_ALGORITHM_HPP + +#include + +namespace boost { namespace crypt { + +template +BOOST_CRYPT_GPU_ENABLED constexpr auto equal(InputIt1 first1, InputIt1 last1, InputIt2 first2) -> bool +{ + while(first1 != last1) + { + if(!(*first1 == *first2)) + { + return false; + } + + ++first1; + ++first2; + } + + return true; +} + +template +BOOST_CRYPT_GPU_ENABLED constexpr auto lexicographical_compare(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2) -> bool +{ + while((first1 != last1) && (first2 != last2)) + { + if(*first1 < *first2) + { + return true; + } + + if(*first2 < *first1) + { + return false; + } + + ++first1; + ++first2; + } + + return ((first1 == last1) && (first2 != last2)); +} + +} // namespace crypt +} // namespace boost + +#endif // BOOST_CRYPT_UTILITIES_ALGORITHM_HPP diff --git a/include/boost/crypt/utility/array.hpp b/include/boost/crypt/utility/array.hpp index edf797f7..362857a8 100644 --- a/include/boost/crypt/utility/array.hpp +++ b/include/boost/crypt/utility/array.hpp @@ -7,6 +7,7 @@ #define BOOST_CRYPT_UTILITIES_ARRAY_HPP #include +#include #include #include #include @@ -126,6 +127,42 @@ BOOST_CRYPT_GPU_ENABLED constexpr auto fill_array(ForwardIter first, ForwardIter } } +template +BOOST_CRYPT_GPU_ENABLED constexpr auto operator==(const array& left, const array& right) -> bool +{ + return boost::crypt::equal(left.begin(), left.end(), right.begin()); +} + +template +BOOST_CRYPT_GPU_ENABLED constexpr auto operator<(const array& left, const array& right) -> bool +{ + return boost::crypt::lexicographical_compare(left.begin(), left.end(), right.begin(), right.end()); +} + +template +BOOST_CRYPT_GPU_ENABLED constexpr auto operator!=(const array& left, const array& right) -> bool +{ + return (!(left == right)); +} + +template +BOOST_CRYPT_GPU_ENABLED constexpr auto operator>(const array& left, const array& right) -> bool +{ + return (right < left); +} + +template +BOOST_CRYPT_GPU_ENABLED constexpr auto operator>=(const array& left, const array& right) -> bool +{ + return (!(left < right)); +} + +template +BOOST_CRYPT_GPU_ENABLED constexpr auto operator<=(const array& left, const array& right) -> bool +{ + return (!(right < left)); +} + template class tuple_size; diff --git a/test/metal/.gitignore b/test/metal/.gitignore new file mode 100644 index 00000000..ba077a40 --- /dev/null +++ b/test/metal/.gitignore @@ -0,0 +1 @@ +bin diff --git a/test/metal/app_benchmark_hasher.cpp b/test/metal/app_benchmark_hasher.cpp new file mode 100644 index 00000000..6aeda686 --- /dev/null +++ b/test/metal/app_benchmark_hasher.cpp @@ -0,0 +1,133 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2023. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#endif + +// cd /mnt/c/ChrisGitRepos/cppalliance/crypt/test/metal +// mkdir -p bin +// arm-none-eabi-g++ -std=c++17 -Wall -Wextra -Wpedantic -O0 -g -gdwarf-2 -ffunction-sections -fdata-sections -x c++ -fno-rtti -fno-use-cxa-atexit -fno-exceptions -fno-nonansi-builtins -fno-threadsafe-statics -fno-enforce-eh-specs -ftemplate-depth=128 -mcpu=cortex-m4 -mtune=cortex-m4 -mthumb -mfloat-abi=soft -mno-unaligned-access -mno-long-calls -I../../include -DBOOST_DECIMAL_DISABLE_CLIB -DAPP_BENCHMARK_STANDALONE_MAIN app_benchmark_hasher.cpp ./target/micros/stm32f429/make/single/crt.cpp ./target/micros/stm32f429/make/single/mcal_gcc_cxx_completion_with_stdlib.cpp -nostartfiles -Wl,--gc-sections -Wl,-Map,./bin/app_benchmark_hasher.map -T ./target/micros/stm32f429/make/stm32f429.ld --specs=nano.specs --specs=nosys.specs -Wl,--print-memory-usage -o ./bin/app_benchmark_hasher.elf +// arm-none-eabi-objcopy ./bin/app_benchmark_hasher.elf -O ihex ./bin/app_benchmark_hasher.hex +// ls -la ./bin/app_benchmark_hasher.elf ./bin/app_benchmark_hasher.hex ./bin/app_benchmark_hasher.map + +#if !defined(BOOST_CRYPT_STANDALONE) +#define BOOST_DECIMAL_STANDALONE +#endif + +#include + +namespace app { namespace benchmark { + +namespace detail { + +} // namespace detail + +auto run_hasher() -> bool; + +} // namespace benchmark +} // namespace app + +namespace local +{ + + using hasher_type = boost::crypt::sha256_hasher; + +} // namespace local + +auto app::benchmark::run_hasher() -> bool +{ + auto app_benchmark_result_is_ok = true; + + // "abc" + const std::array message = + {{ + 0x61U, 0x62U, 0x63U + }}; + + using local_hasher_type = local::hasher_type; + using local_result_type = typename local_hasher_type::return_type; + + const local_result_type control = + {{ + 0xBAU, 0x78U, 0x16U, 0xBFU, 0x8FU, 0x01U, 0xCFU, 0xEAU, + 0x41U, 0x41U, 0x40U, 0xDEU, 0x5DU, 0xAEU, 0x22U, 0x23U, + 0xB0U, 0x03U, 0x61U, 0xA3U, 0x96U, 0x17U, 0x7AU, 0x9CU, + 0xB4U, 0x10U, 0xFFU, 0x61U, 0xF2U, 0x00U, 0x15U, 0xADU, + }}; + + local_hasher_type my_hasher { }; + + my_hasher.init(); + + my_hasher.process_bytes(message.data(), message.size()); + + const local_result_type result = my_hasher.get_digest(); + + const bool result_hash_is_ok { result == control }; + + app_benchmark_result_is_ok = (result_hash_is_ok && app_benchmark_result_is_ok); + + return app_benchmark_result_is_ok; +} + +#if defined(APP_BENCHMARK_STANDALONE_MAIN) +constexpr auto app_benchmark_standalone_foodcafe = static_cast(UINT32_C(0xF00DCAFE)); + +extern "C" +{ + extern volatile std::uint32_t app_benchmark_standalone_result; + + auto app_benchmark_run_standalone (void) -> bool; + auto app_benchmark_get_standalone_result(void) -> bool; + + auto app_benchmark_run_standalone(void) -> bool + { + auto result_is_ok = true; + + for(unsigned i = 0U; i < 64U; ++i) + { + result_is_ok &= app::benchmark::run_hasher(); + } + + app_benchmark_standalone_result = + static_cast + ( + result_is_ok ? app_benchmark_standalone_foodcafe : static_cast(UINT32_C(0xFFFFFFFF)) + ); + + return result_is_ok; + } + + auto app_benchmark_get_standalone_result(void) -> bool + { + volatile auto result_is_ok = (app_benchmark_standalone_result == static_cast(UINT32_C(0xF00DCAFE))); + + return result_is_ok; + } +} + +auto main() -> int +{ + auto result_is_ok = true; + + result_is_ok = (::app_benchmark_run_standalone () && result_is_ok); + result_is_ok = (::app_benchmark_get_standalone_result() && result_is_ok); + + return (result_is_ok ? 0 : -1); +} + +extern "C" +{ + volatile std::uint32_t app_benchmark_standalone_result; +} +#endif // APP_BENCHMARK_STANDALONE_MAIN + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif diff --git a/test/metal/target/build/test_app_benchmarks_emulator.py b/test/metal/target/build/test_app_benchmarks_emulator.py new file mode 100644 index 00000000..44bf8af5 --- /dev/null +++ b/test/metal/target/build/test_app_benchmarks_emulator.py @@ -0,0 +1,131 @@ +#------------------------------------------------------------------------------- +# Name: test_app_benchmarks_emulator.py +# Purpose: +# +# Author: Christopher Kormanyos +# +# Created: 02/04/2021 +# +# Copyright: Copyright Christopher Kormanyos 2020 - 2023 +# +# Licence: Distributed under the Boost Software License, +# Version 1.0. (See accompanying file LICENSE_1_0.txt +# or copy at http://www.boost.org/LICENSE_1_0.txt) +#------------------------------------------------------------------------------- + +#!/usr/bin/env python2 + +# import python packages +import gdb +import time +import logging +import sys + +#------------------------------------------------------------------------------- +# --- class: qemu_emulator +#------------------------------------------------------------------------------- +class qemu_emulator: + def __init__(self, tcp_port, iterations): + self.tcp_port = tcp_port + self.iterations = iterations + + # qemu initialization + def initialize(self): + self.connect_to_server(self.tcp_port) + self.create_log_file() + self.load_elf() + + # Excute gdb commands + def execute(self, command, from_tty = False, to_string = False): + gdb.execute('{}'.format(command), from_tty, to_string) + + # Create log file + def create_log_file(self): + logging.basicConfig(filename='emu-target.log',level=logging.DEBUG, filemode='w') + logging.info('------- Running GDB Test -----') + + # Connect to server + def connect_to_server(self, tcp_port): + self.execute('target remote localhost:{}'.format(tcp_port)) + self.execute('monitor reset') + self.execute('set confirm off') + + # Load object data base + def load_elf(self): + self.execute('load') + + # Run the benchmark + def run(self): + self.execute('continue') + + def next(self): + self.execute('next') + + # Set gdb Bp + def set_gdb_break_point(self): + my_bp = gdb.Breakpoint('app_benchmark_get_standalone_result') + return my_bp + + # Delete gdb Bp + def delete_gdb_break_point(self, bp): + bp.delete() + + # Get gdb result + def get_gdb_result(self): + my_result = gdb.parse_and_eval("app_benchmark_standalone_result") + return my_result + + # Convert from gdb type to hex + def convert_to_hex(self, gdb_value): + val_as_str = str(gdb_value) + val_as_hex = hex(int(val_as_str)) + return val_as_hex + + # Check the gdb return value + def check_gdb_result(self, result_as_hex): + if result_as_hex == "0xf00dcafe": + return True + else: + return False + +#------------------------------------------------------------------------------- +# --- GDB Script starts here +# See also https://embeddedartistry.com/blog/2020/11/09/metal-gdb-controlling-gdb-through-python-scripts-with-the-gdb-python-api/ +#------------------------------------------------------------------------------- + +# Script Config +tcp_port = 9999 +iterations = 64 + +# Create a qemu object +obj = qemu_emulator(tcp_port, iterations) + +# Initialize +obj.initialize() + +# Set break point +bp1 = obj.set_gdb_break_point() + +# Run the benchmark +obj.run() + +# Get gdb result +my_value = obj.get_gdb_result() +time.sleep(0.5) + +# Delete break point +obj.delete_gdb_break_point(bp1) + +# Convert gdb result to hex +value_as_hex = obj.convert_to_hex(my_value) + +# Print the return value +print("Result value as hex: " + value_as_hex) + +# Check the gdb result and quit +result_is_ok = obj.check_gdb_result(value_as_hex) + +if result_is_ok == True: + sys.exit(0) +else: + sys.exit(-1) diff --git a/test/metal/target/micros/stm32f429/make/single/crt.cpp b/test/metal/target/micros/stm32f429/make/single/crt.cpp new file mode 100644 index 00000000..25daf821 --- /dev/null +++ b/test/metal/target/micros/stm32f429/make/single/crt.cpp @@ -0,0 +1,276 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2023. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include +#include +#include +#include +#include + +namespace crt +{ + void init_ram(); +} + +namespace crt +{ + void init_ctors(); +} + +extern "C" void __my_startup(void) __attribute__((used, noinline)); + +void __my_startup(void) +{ + // Load the stack pointer. + // The stack pointer is automatically loaded from + // the base position of the interrupt vector table. + // So we do nothing here. + + // TBD: Chip init: Watchdog, port, and oscillator, if any needed. + + // Initialize statics from ROM to RAM. + // Zero-clear default-initialized static RAM. + crt::init_ram(); + + // Call all ctor initializations. + crt::init_ctors(); + + // Jump to main (and never return). + asm volatile("ldr r3, =main"); + asm volatile("blx r3"); + + exit(EXIT_SUCCESS); + + // TBD: Nothing on return from main. +} + +extern "C" void _exit (int); + +extern "C" void _exit (int) { } + +extern "C" +{ + extern std::uintptr_t _rom_data_begin; // Start address for the initialization values of the rom-to-ram section. + extern std::uintptr_t _data_begin; // Start address for the .data section. + extern std::uintptr_t _data_end; // End address for the .data section. + extern std::uintptr_t _bss_begin; // Start address for the .bss section. + extern std::uintptr_t _bss_end; // End address for the .bss section. +} + +void crt::init_ram() +{ + typedef std::uint32_t memory_aligned_type; + + // Copy the data segment initializers from ROM to RAM. + // Note that all data segments are aligned by 4. + const std::size_t size_data = + std::size_t( static_cast(static_cast(&_data_end)) + - static_cast(static_cast(&_data_begin))); + + std::copy(static_cast(static_cast(&_rom_data_begin)), + static_cast(static_cast(&_rom_data_begin)) + size_data, + static_cast< memory_aligned_type*>(static_cast< void*>(&_data_begin))); + + // Clear the bss segment. + // Note that the bss segment is aligned by 4. + std::fill(static_cast(static_cast(&_bss_begin)), + static_cast(static_cast(&_bss_end)), + static_cast(0U)); +} + +extern "C" +{ + struct ctor_type + { + typedef void(*function_type)(); + typedef std::reverse_iterator const_reverse_iterator; + }; + + extern ctor_type::function_type _ctors_end[]; + extern ctor_type::function_type _ctors_begin[]; +} + +void crt::init_ctors() +{ + std::for_each(ctor_type::const_reverse_iterator(_ctors_end), + ctor_type::const_reverse_iterator(_ctors_begin), + [](const ctor_type::function_type pf) + { + pf(); + }); +} + +extern "C" void __initial_stack_pointer(); + +extern "C" void __my_startup () __attribute__((used, noinline)); +extern "C" void __vector_unused_irq () __attribute__((used, noinline)); +extern "C" void __nmi_handler () __attribute__((used, noinline)); +extern "C" void __hard_fault_handler () __attribute__((used, noinline)); +extern "C" void __mem_manage_handler () __attribute__((used, noinline)); +extern "C" void __bus_fault_handler () __attribute__((used, noinline)); +extern "C" void __usage_fault_handler() __attribute__((used, noinline)); +extern "C" void __svc_handler () __attribute__((used, noinline)); +extern "C" void __debug_mon_handler () __attribute__((used, noinline)); +extern "C" void __pend_sv_handler () __attribute__((used, noinline)); +extern "C" void __sys_tick_handler () __attribute__((used, noinline)); +extern "C" void __vector_timer4 (); + +extern "C" void __vector_unused_irq () { for(;;) { ; } } +extern "C" void __nmi_handler () { for(;;) { ; } } +extern "C" void __hard_fault_handler () { for(;;) { ; } } +extern "C" void __mem_manage_handler () { for(;;) { ; } } +extern "C" void __bus_fault_handler () { for(;;) { ; } } +extern "C" void __usage_fault_handler() { for(;;) { ; } } +extern "C" void __svc_handler () { for(;;) { ; } } +extern "C" void __debug_mon_handler () { for(;;) { ; } } +extern "C" void __pend_sv_handler () { for(;;) { ; } } +extern "C" void __sys_tick_handler () { for(;;) { ; } } + +namespace +{ + typedef void(*isr_type)(); + + constexpr std::size_t number_of_interrupts = 128U; +} + +extern "C" +const volatile std::array __isr_vector __attribute__((section(".isr_vector"))); + +extern "C" +const volatile std::array __isr_vector = +{{ + __initial_stack_pointer, // 0x0000, initial stack pointer + __my_startup, // 0x0004, reset + __nmi_handler, // 0x0008, nmi exception + __hard_fault_handler, // 0x000C, hard fault exception + __mem_manage_handler, // 0x0010, memory management exception + __bus_fault_handler, // 0x0014, bus fault exception + __usage_fault_handler, // 0x0018, usage fault exception + __vector_unused_irq, // 0x001C, reserved + __vector_unused_irq, // 0x0020, reserved + __vector_unused_irq, // 0x0024, reserved + __vector_unused_irq, // 0x0028, reserved + __svc_handler, // 0x002C, svc handler + __debug_mon_handler, // 0x0030, debug monitor + __vector_unused_irq, // 0x0034, reserved + __pend_sv_handler, // 0x0038, pending svc, + __sys_tick_handler, // 0x003C, system tick handler, + __vector_unused_irq, // 0x0040, wwdg irq handler, + __vector_unused_irq, // 0x0044, pvd irq handler, + __vector_unused_irq, // 0x0048, tamper irq handler, + __vector_unused_irq, // 0x004C, rtc irq handler, + __vector_unused_irq, // 0x0050, flash irq handler, + __vector_unused_irq, // 0x0054, rcc irq handler, + __vector_unused_irq, // 0x0058, exti0 irq handler, + __vector_unused_irq, // 0x005C, exti1 irq handler, + __vector_unused_irq, // 0x0060, exti2 irq handler, + __vector_unused_irq, // 0x0064, exti3 irq handler, + __vector_unused_irq, // 0x0068, exti4 irq handler, + __vector_unused_irq, // 0x006C, dma_channel1 irq handler, + __vector_unused_irq, // 0x0070, dma_channel2 irq handler, + __vector_unused_irq, // 0x0074, dma_channel3 irq handler, + __vector_unused_irq, // 0x0078, dma_channel4 irq handler, + __vector_unused_irq, // 0x007C, dma_channel5 irq handler, + __vector_unused_irq, // 0x0080, dma_channel6 irq handler, + __vector_unused_irq, // 0x0084, dma_channel7 irq handler, + __vector_unused_irq, // 0x0088, adc irq handler, + __vector_unused_irq, // 0x008C, usb_hp_can_tx irq handler, + __vector_unused_irq, // 0x0090, usb_lp_can_rx0 irq handler, + __vector_unused_irq, // 0x0094, can_rx1 irq handler, + __vector_unused_irq, // 0x0098, can_sce irq handler, + __vector_unused_irq, // 0x009C, exti9_5 irq handler, + __vector_unused_irq, // 0x00A0, tim1_brk irq handler, + __vector_unused_irq, // 0x00A4, tim1_up irq handler, + __vector_unused_irq, // 0x00A8, tim1_trg_com irq handler, + __vector_unused_irq, // 0x00AC, tim1_cc irq handler, + __vector_unused_irq, // 0x00B0, tim2 irq handler, + __vector_unused_irq, // 0x00B4, tim3 irq handler, + __vector_unused_irq, // 0x00B8, tim4 irq handler, + __vector_unused_irq, // 0x00BC, i2c1_ev irq handler, + __vector_unused_irq, // 0x00C0, i2c1_er irq handler, + __vector_unused_irq, // 0x00C4, i2c2_ev irq handler, + __vector_unused_irq, // 0x00C8, i2c2_er irq handler, + __vector_unused_irq, // 0x00CC, spi1 irq handler, + __vector_unused_irq, // 0x00D0, spi2 irq handler, + __vector_unused_irq, // 0x00D4, usart1 irq handler, + __vector_unused_irq, // 0x00D8, usart2 irq handler, + __vector_unused_irq, // 0x00DC, usart3 irq handler, + __vector_unused_irq, // 0x00E0, exti15_10 irq handler, + __vector_unused_irq, // 0x00E4, rtcalarm irq handler, + __vector_unused_irq, // 0x00E8, usbwakeup irq handler, + __vector_unused_irq, // 0x00EC, tim8 break and tim12 + __vector_unused_irq, // 0x00F0, tim8 update and tim13 + __vector_unused_irq, // 0x00F4, tim8 trigger and commutation and tim14 + __vector_unused_irq, // 0x00F8, tim8 capture compare + __vector_unused_irq, // 0x00FC, dma1 stream7 + __vector_unused_irq, // 0x0100, fmc + __vector_unused_irq, // 0x0104, sdio + __vector_unused_irq, // 0x0108, tim5 + __vector_unused_irq, // 0x010C, spi3 + __vector_unused_irq, // 0x0110, uart4 + __vector_unused_irq, // 0x0114, uart5 + __vector_unused_irq, // 0x0118, tim6 and dac1&2 underrun errors + __vector_unused_irq, // 0x011C, tim7 + __vector_unused_irq, // 0x0120, dma2 stream 0 + __vector_unused_irq, // 0x0124, dma2 stream 1 + __vector_unused_irq, // 0x0128, dma2 stream 2 + __vector_unused_irq, // 0x012C, dma2 stream 3 + __vector_unused_irq, // 0x0130, dma2 stream 4 + __vector_unused_irq, // 0x0134, ethernet + __vector_unused_irq, // 0x0138, ethernet wakeup through exti line + __vector_unused_irq, // 0x013C, can2 tx + __vector_unused_irq, // 0x0140, can2 rx0 + __vector_unused_irq, // 0x0144, can2 rx1 + __vector_unused_irq, // 0x0148, can2 sce + __vector_unused_irq, // 0x014C, usb otg fs + __vector_unused_irq, // 0x0150, dma2 stream 5 + __vector_unused_irq, // 0x0154, dma2 stream 6 + __vector_unused_irq, // 0x0158, dma2 stream 7 + __vector_unused_irq, // 0x015C, usart6 + __vector_unused_irq, // 0x0160, i2c3 event + __vector_unused_irq, // 0x0164, i2c3 error + __vector_unused_irq, // 0x0168, usb otg hs end point 1 out + __vector_unused_irq, // 0x016C, usb otg hs end point 1 in + __vector_unused_irq, // 0x0170, usb otg hs wakeup through exti + __vector_unused_irq, // 0x0174, usb otg hs + __vector_unused_irq, // 0x0178, dcmi + __vector_unused_irq, // 0x017C, cryp crypto + __vector_unused_irq, // 0x0180, hash and rng + __vector_unused_irq, // 0x0184, fpu + __vector_unused_irq, // 0x0188, uart7 + __vector_unused_irq, // 0x018C, uart8 + __vector_unused_irq, // 0x0190, spi4 + __vector_unused_irq, // 0x0194, spi5 + __vector_unused_irq, // 0x0198, spi6 + __vector_unused_irq, // 0x019C, sai1 + __vector_unused_irq, // 0x01A0, reserved + __vector_unused_irq, // 0x01A4, reserved + __vector_unused_irq, // 0x01A8, dma2d + nullptr, // 0x01AC, dummy + nullptr, // 0x01B0, dummy + nullptr, // 0x01B4, dummy + nullptr, // 0x01B8, dummy + nullptr, // 0x01BC, dummy + nullptr, // 0x01C0, dummy + nullptr, // 0x01C4, dummy + nullptr, // 0x01C8, dummy + nullptr, // 0x01CC, dummy + nullptr, // 0x01D0, dummy + nullptr, // 0x01D4, dummy + nullptr, // 0x01D8, dummy + nullptr, // 0x01DC, dummy + nullptr, // 0x01E0, dummy + nullptr, // 0x01E4, dummy + nullptr, // 0x01E8, dummy + nullptr, // 0x01EC, dummy + nullptr, // 0x01F0, dummy + nullptr, // 0x01F4, dummy + nullptr, // 0x01F8, dummy + nullptr // 0x01FC, dummy +}}; + diff --git a/test/metal/target/micros/stm32f429/make/single/mcal_gcc_cxx_completion_with_stdlib.cpp b/test/metal/target/micros/stm32f429/make/single/mcal_gcc_cxx_completion_with_stdlib.cpp new file mode 100644 index 00000000..d8739751 --- /dev/null +++ b/test/metal/target/micros/stm32f429/make/single/mcal_gcc_cxx_completion_with_stdlib.cpp @@ -0,0 +1,24 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2023. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +extern "C" +{ + // Patched functions. + void __cxa_pure_virtual (void); + char* __cxa_demangle (const char*, char*, size_t*, int*); + + void __cxa_pure_virtual (void) { } + char* __cxa_demangle (const char*, char*, size_t*, int*) { return nullptr; } +} + +extern "C" +{ + // Patched labels. + void* __dso_handle; +} diff --git a/test/metal/target/micros/stm32f429/make/stm32f429.ld b/test/metal/target/micros/stm32f429/make/stm32f429.ld new file mode 100644 index 00000000..35e9f8ec --- /dev/null +++ b/test/metal/target/micros/stm32f429/make/stm32f429.ld @@ -0,0 +1,135 @@ + +/* + Copyright Christopher Kormanyos 2007 - 2022. + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://www.boost.org/LICENSE_1_0.txt) +*/ + +/* Linker script for STM32F4xx ARM(R) Cortex(TM)-M4 MCU */ + +ENTRY(__my_startup) + +INPUT(libc.a libm.a libgcc.a) + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) + +/* The beginning and end of the program ROM area */ +/* Set up a ROM area with a size of 32K */ +_rom_begin = 0x08000000; +_rom_end = 0x08008000; + +/* The beginning and end (i.e., the top) of the stack */ +/* Set up a stack with a size of 4K */ +_stack_begin = 0x20007000; +_stack_end = 0x20008000; + +__initial_stack_pointer = 0x20008000 - 4; + +MEMORY +{ + ROM(rx) : ORIGIN = 0x08000000, LENGTH = 32K + RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 0x7000 +} + +SECTIONS +{ + . = 0x08000000; + . = ALIGN(4); + + /* ISR vectors */ + .isr_vector : + { + *(.isr_vector) + . = ALIGN(0x10); + KEEP(*(.isr_vector)) + } > ROM = 0xAAAA + + /* startup */ + .startup : + { + *(.startup) + . = ALIGN(0x10); + KEEP(*(.startup)) + } > ROM = 0x5555 + + /* Program code (text), read-only data and static ctors */ + .text : + { + _ctors_begin = .; + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array*)) + _ctors_end = .; + *(.progmem*) + . = ALIGN(4); + *(.text) + . = ALIGN(4); + *(.text*) + . = ALIGN(4); + *(.rodata) + . = ALIGN(4); + *(.rodata*) + . = ALIGN(4); + *(.glue_7) + . = ALIGN(4); + *(.glue_7t) + . = ALIGN(4); + } > ROM + + .ARM.extab : + { + . = ALIGN(4); + *(.ARM.extab) + *(.gnu.linkonce.armextab.*) + . = ALIGN(4); + } > ROM + + .exidx : + { + . = ALIGN(4); + PROVIDE(__exidx_start = .); + *(.ARM.exidx*) + . = ALIGN(4); + PROVIDE(__exidx_end = .); + } > ROM + + .ARM.attributes : + { + *(.ARM.attributes) + } > ROM + + . = 0x20000000; + . = ALIGN(4); + + /* The ROM-to-RAM initialized data section */ + .data : + { + _data_begin = .; + *(.data) + . = ALIGN(4); + KEEP (*(.data)) + *(.data*) + . = ALIGN(4); + KEEP (*(.data*)) + _data_end = .; + } > RAM AT > ROM + + /* The uninitialized (zero-cleared) data section */ + .bss : + { + _bss_begin = .; + *(.bss) + . = ALIGN(4); + KEEP (*(.bss)) + *(.bss*) + . = ALIGN(4); + KEEP (*(.bss*)) + _bss_end = .; + } > RAM + + PROVIDE(end = .); + PROVIDE(_fini = .); + + _rom_data_begin = LOADADDR(.data); +}