From c350ebccfc699285f94e69607cbe47a90ef1bb62 Mon Sep 17 00:00:00 2001 From: Khalil Estell Date: Wed, 12 Jul 2023 22:00:35 -0700 Subject: [PATCH] :bug: Fix interrupts Interrupts wouldn't fire for handlers passed into them. systick_timer's interrupt was also reported to not work either. Further changes were made: - Removal of demos as they were not easy to use when demonstrating the usage of the libraries. Platform libraries utilizing libhal-armcortex should be responsible for creating that use the the processor libraries. - Add flags to thumbvX profiles that were removed from libhal/arm-gnu-toolchain/#33. - Update to ci/4.0.1, which builds the demos if and only if the demos directory exists. - Bump to version 2.0.1 - Make hal::cortex_minterrupt::vector_table variable anonymous. Normally this would be an API break, but no users of the project are using this field, so keeping the major number as "2". - Provide static disable and enable interrupts APIs to interrupt class. - Improve correctness of systick timer's implementation. --- .github/workflows/ci.yml | 14 +-- conan/profiles/thumbv6 | 6 +- conan/profiles/thumbv7 | 6 +- conan/profiles/thumbv8 | 6 +- conanfile.py | 2 +- demos/CMakeLists.txt | 48 --------- demos/applications/dwt_counter.cpp | 34 ------- demos/conanfile.py | 50 ---------- demos/linker.ld | 25 ----- demos/main.cpp | 131 ------------------------- include/libhal-armcortex/interrupt.hpp | 15 +-- src/interrupt.cpp | 65 ++++++++---- src/systick_timer.cpp | 6 +- tests/interrupt.test.cpp | 43 ++++---- 14 files changed, 100 insertions(+), 351 deletions(-) delete mode 100644 demos/CMakeLists.txt delete mode 100644 demos/applications/dwt_counter.cpp delete mode 100644 demos/conanfile.py delete mode 100644 demos/linker.ld delete mode 100644 demos/main.cpp diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0e30cb9..81a537b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,43 +13,43 @@ on: jobs: ci: - uses: libhal/ci/.github/workflows/library.yml@4.0.0 + uses: libhal/ci/.github/workflows/library.yml@4.0.1 with: library: libhal-armcortex secrets: inherit cortex-m0: - uses: libhal/ci/.github/workflows/platform_deploy.yml@4.0.0 + uses: libhal/ci/.github/workflows/platform_deploy.yml@4.0.1 with: profile: cortex-m0 secrets: inherit cortex-m0plus: - uses: libhal/ci/.github/workflows/platform_deploy.yml@4.0.0 + uses: libhal/ci/.github/workflows/platform_deploy.yml@4.0.1 with: profile: cortex-m0plus secrets: inherit cortex-m1: - uses: libhal/ci/.github/workflows/platform_deploy.yml@4.0.0 + uses: libhal/ci/.github/workflows/platform_deploy.yml@4.0.1 with: profile: cortex-m1 secrets: inherit cortex-m3: - uses: libhal/ci/.github/workflows/platform_deploy.yml@4.0.0 + uses: libhal/ci/.github/workflows/platform_deploy.yml@4.0.1 with: profile: cortex-m3 secrets: inherit cortex-m4: - uses: libhal/ci/.github/workflows/platform_deploy.yml@4.0.0 + uses: libhal/ci/.github/workflows/platform_deploy.yml@4.0.1 with: profile: cortex-m4 secrets: inherit cortex-m4f: - uses: libhal/ci/.github/workflows/platform_deploy.yml@4.0.0 + uses: libhal/ci/.github/workflows/platform_deploy.yml@4.0.1 with: profile: cortex-m4f secrets: inherit diff --git a/conan/profiles/thumbv6 b/conan/profiles/thumbv6 index 98f010e..62e397c 100644 --- a/conan/profiles/thumbv6 +++ b/conan/profiles/thumbv6 @@ -11,6 +11,6 @@ arch.processor={{ cpu }} arm-gnu-toolchain/12.2.1 [conf] -tools.build:cflags=["-mfloat-abi=soft", "-mcpu={{ cpu }}"] -tools.build:cxxflags=["-mfloat-abi=soft", "-mcpu={{ cpu }}", "-fno-exceptions", "-fno-rtti"] -tools.build:exelinkflags=["--specs=nano.specs", "--specs=nosys.specs", "-mfloat-abi=soft", "-mcpu={{ cpu }}", "-fno-exceptions", "-fno-rtti"] +tools.build:cflags=["-mfloat-abi=soft", "-mcpu={{ cpu }}", "-mthumb", "-ffunction-sections", "-fdata-sections"] +tools.build:cxxflags=["-mfloat-abi=soft", "-mcpu={{ cpu }}", "-fno-exceptions", "-fno-rtti", "-mthumb", "-ffunction-sections", "-fdata-sections"] +tools.build:exelinkflags=["--specs=nano.specs", "--specs=nosys.specs", "-mfloat-abi=soft", "-mcpu={{ cpu }}", "-mthumb", "-fno-exceptions", "-fno-rtti", "-Wl,--gc-sections", "-Wl,--print-memory-usage"] diff --git a/conan/profiles/thumbv7 b/conan/profiles/thumbv7 index 50cc64f..3c7bf3b 100644 --- a/conan/profiles/thumbv7 +++ b/conan/profiles/thumbv7 @@ -13,6 +13,6 @@ arch.processor={{ cpu }} arm-gnu-toolchain/12.2.1 [conf] -tools.build:cflags=["-mfloat-abi={{ float_abi }}", "-mcpu={{ cpu }}", "-mfpu={{ fpu }}"] -tools.build:cxxflags=["-mfloat-abi={{ float_abi }}", "-mcpu={{ cpu }}", "-mfpu={{ fpu }}", "-fno-exceptions", "-fno-rtti"] -tools.build:exelinkflags=["--specs=nano.specs", "--specs=nosys.specs", "-mfloat-abi={{ float_abi }}", "-mcpu={{ cpu }}", "-mfpu={{ fpu }}", "-fno-exceptions", "-fno-rtti"] +tools.build:cflags=["-mfloat-abi={{ float_abi }}", "-mcpu={{ cpu }}", "-mfpu={{ fpu }}", "-mthumb", "-ffunction-sections", "-fdata-sections"] +tools.build:cxxflags=["-mfloat-abi={{ float_abi }}", "-mcpu={{ cpu }}", "-mfpu={{ fpu }}", "-fno-exceptions", "-fno-rtti", "-mthumb", "-ffunction-sections", "-fdata-sections"] +tools.build:exelinkflags=["--specs=nano.specs", "--specs=nosys.specs", "-mfloat-abi={{ float_abi }}", "-mcpu={{ cpu }}", "-mfpu={{ fpu }}", "-fno-exceptions", "-fno-rtti", "-mthumb", "-ffunction-sections", "-fdata-sections"] diff --git a/conan/profiles/thumbv8 b/conan/profiles/thumbv8 index 62c3428..caeab7c 100644 --- a/conan/profiles/thumbv8 +++ b/conan/profiles/thumbv8 @@ -12,6 +12,6 @@ arch.processor={{ cpu }} arm-gnu-toolchain/12.2.1 [conf] -tools.build:cflags=["-mfloat-abi={{ float_abi }}", "-mcpu={{ cpu }}"] -tools.build:cxxflags=["-mfloat-abi={{ float_abi }}", "-mcpu={{ cpu }}", "-fno-exceptions", "-fno-rtti"] -tools.build:exelinkflags=["--specs=nano.specs", "--specs=nosys.specs", "-mfloat-abi={{ float_abi }}", "-mcpu={{ cpu }}", "-fno-exceptions", "-fno-rtti"] +tools.build:cflags=["-mfloat-abi={{ float_abi }}", "-mcpu={{ cpu }}", "-mthumb", "-ffunction-sections", "-fdata-sections"] +tools.build:cxxflags=["-mfloat-abi={{ float_abi }}", "-mcpu={{ cpu }}", "-fno-exceptions", "-fno-rtti", "-mthumb", "-ffunction-sections", "-fdata-sections"] +tools.build:exelinkflags=["--specs=nano.specs", "--specs=nosys.specs", "-mfloat-abi={{ float_abi }}", "-mcpu={{ cpu }}", "-fno-exceptions", "-fno-rtti", "-mthumb", "-ffunction-sections", "-fdata-sections"] diff --git a/conanfile.py b/conanfile.py index 47ee28d..6daf598 100644 --- a/conanfile.py +++ b/conanfile.py @@ -27,7 +27,7 @@ class libhal_arm_cortex_conan(ConanFile): name = "libhal-armcortex" - version = "2.0.0" + version = "2.0.1" license = "Apache-2.0" url = "https://github.com/conan-io/conan-center-index" homepage = "https://libhal.github.io/libhal-armcortex" diff --git a/demos/CMakeLists.txt b/demos/CMakeLists.txt deleted file mode 100644 index d205801..0000000 --- a/demos/CMakeLists.txt +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright 2023 Google LLC -# -# 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. - -cmake_minimum_required(VERSION 3.20) - -# Set project name to demos -project(demos VERSION 0.0.1 LANGUAGES CXX) - -# Import the libhal-armcortex library/package (and all of its dependencies) -find_package(libhal-util REQUIRED CONFIG) -find_package(libhal-armcortex REQUIRED CONFIG) - -# List of demo applications -# To add a new demo to the list, simply add its filename without the .cpp -# extension to this list. -set(DEMOS dwt_counter) - -add_library(startup_code main.cpp) -target_compile_options(startup_code PRIVATE -g) -target_link_libraries(startup_code PRIVATE libhal::armcortex libhal::util) - -foreach(demo IN LISTS DEMOS) - set(current_project ${demo}.elf) - message(STATUS "Generating Demo for \"${current_project}\"") - add_executable(${current_project} applications/${demo}.cpp) - - target_compile_features(${current_project} PRIVATE cxx_std_20) - target_compile_options(${current_project} PRIVATE -g) - target_link_libraries(${current_project} PRIVATE startup_code - libhal::armcortex - libhal::util) - - target_link_options(${current_project} PUBLIC - -T${CMAKE_SOURCE_DIR}/linker.ld) - - libhal_post_build(${current_project}) -endforeach() diff --git a/demos/applications/dwt_counter.cpp b/demos/applications/dwt_counter.cpp deleted file mode 100644 index 584e286..0000000 --- a/demos/applications/dwt_counter.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2023 Google LLC -// -// 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. - -#include -#include - -int value = 0; - -hal::status application() -{ - using namespace hal::literals; - // Assuming 12 MHz for the CPU clock. Change this to the default CPU clock on - // the target system. - hal::cortex_m::dwt_counter counter(12.0_MHz); - - while (true) { - using namespace std::chrono_literals; - value++; - hal::delay(counter, 100ms); - } - - return hal::success(); -} diff --git a/demos/conanfile.py b/demos/conanfile.py deleted file mode 100644 index 277ffa0..0000000 --- a/demos/conanfile.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/python -# -# Copyright 2023 Google LLC -# -# 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. - -from conan import ConanFile -from conan.tools.cmake import CMake, cmake_layout -from conan.errors import ConanInvalidConfiguration - - -class demos(ConanFile): - settings = "compiler", "build_type", "os", "arch" - generators = "CMakeToolchain", "CMakeDeps", "VirtualBuildEnv" - - def layout(self): - platform_directory = "build/" + str(self.settings.arch.processor) - cmake_layout(self, build_folder=platform_directory) - - def validate(self): - valid_build = (self.settings.os == "baremetal" and - (self.settings.arch == "thumbv7" or - self.settings.arch == "thumbv6" or - self.settings.arch == "thumbv8")) - - if not valid_build: - raise ConanInvalidConfiguration( - f"Only baremetal OS is allowed here!") - - def build_requirements(self): - self.tool_requires("libhal-cmake-util/[^1.0.0]") - - def requirements(self): - self.requires("libhal-armcortex/2.0.0") - self.requires("libhal-util/2.0.0") - - def build(self): - cmake = CMake(self) - cmake.configure() - cmake.build() diff --git a/demos/linker.ld b/demos/linker.ld deleted file mode 100644 index de1a46e..0000000 --- a/demos/linker.ld +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2023 Google LLC - * - * 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. - */ - -/* MODIFY THIS FILE TO SUITE YOUR MCU */ - -__flash = 0x00000000; -__flash_size = 64K; -__ram = 0x20000000; -__ram_size = 16K; -__stack_size = 1K; - -INCLUDE "libhal-armcortex/standard.ld" diff --git a/demos/main.cpp b/demos/main.cpp deleted file mode 100644 index 5bff6f4..0000000 --- a/demos/main.cpp +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2023 Google LLC -// -// 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. - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -// Application function must be implemented by one of the compilation units -// (.cpp) files. -extern hal::status application(); - -int main() -{ - hal::cortex_m::initialize_data_section(); - -// GCC provides the __ARM_FP Macros to indicate if float-abi is set to -// "hard" or "softfp" and not defined if set to "soft" -#if defined(__ARM_FP) - hal::cortex_m::initialize_floating_point_unit(); -#endif - - auto is_finished = application(); - - if (!is_finished) { - hal::cortex_m::reset(); - } else { - hal::halt(); - } - - return 0; -} - -namespace boost { -void throw_exception(std::exception const& e) -{ - std::abort(); -} -} // namespace boost - -extern "C" -{ - /// Dummy implementation of getpid - int _getpid() - { - return 1; - } - - /// Dummy implementation of kill - int _kill(int, int) - { - return -1; - } - - /// Dummy implementation of fstat, makes the assumption that the "device" - /// representing, in this case STDIN, STDOUT, and STDERR as character devices. - int _fstat([[maybe_unused]] int file, struct stat* status) - { - status->st_mode = S_IFCHR; - return 0; - } - - int _write([[maybe_unused]] int file, - [[maybe_unused]] const char* ptr, - int length) - { - return length; - } - - int _read([[maybe_unused]] int file, [[maybe_unused]] char* ptr, int length) - { - return length; - } - - int ead([[maybe_unused]] FILE* file, [[maybe_unused]] char* ptr, int length) - { - return length; - } - - // Dummy implementation of _lseek - int _lseek([[maybe_unused]] int file, - [[maybe_unused]] int ptr, - [[maybe_unused]] int dir) - { - return 0; - } - - // Dummy implementation of close - int _close([[maybe_unused]] int file) - { - return -1; - } - - // Dummy implementation of isatty - int _isatty([[maybe_unused]] int file) - { - return 1; - } - - // Dummy implementation of isatty - void _exit([[maybe_unused]] int file) - { - while (1) { - continue; - } - } - // Dummy implementation of isatty - void* _sbrk([[maybe_unused]] int size) - { - return nullptr; - } -} \ No newline at end of file diff --git a/include/libhal-armcortex/interrupt.hpp b/include/libhal-armcortex/interrupt.hpp index 50b0586..7fa6041 100644 --- a/include/libhal-armcortex/interrupt.hpp +++ b/include/libhal-armcortex/interrupt.hpp @@ -31,9 +31,6 @@ using interrupt_pointer = void (*)(); class interrupt { public: - /// Pointer to a statically allocated interrupt vector table - static inline std::span vector_table; - /// The core interrupts that all cortex m3, m4, m7 processors have static constexpr size_t core_interrupts = 16; @@ -130,9 +127,9 @@ class interrupt * @return true - is a valid interrupt for this system * @return false - this interrupt is beyond the range of valid interrupts */ - [[nodiscard]] constexpr bool is_valid() const + [[nodiscard]] bool is_valid() const { - return m_id < vector_table.size(); + return m_id < get_vector_table().size(); } /** @@ -203,9 +200,13 @@ class interrupt /** * @brief Get a reference to interrupt vector table object * - * @return const std::span& - interrupt vector table + * @return const std::span - interrupt vector table */ - static const std::span& get_vector_table(); + static const std::span get_vector_table(); + + static void disable_interrupts(); + + static void enable_interrupts(); /** * @brief Construct a new interrupt object diff --git a/src/interrupt.cpp b/src/interrupt.cpp index 9480bc3..5ccc893 100644 --- a/src/interrupt.cpp +++ b/src/interrupt.cpp @@ -27,9 +27,14 @@ namespace hal::cortex_m { +namespace { +/// Pointer to a statically allocated interrupt vector table +std::span vector_table{}; +} // namespace + bool vector_table_is_initialized() { - return get_interrupt_vector_table_address() != 0x0000'0000; + return get_interrupt_vector_table_address() == vector_table.data(); } /// Place holder interrupt that performs no work @@ -65,7 +70,7 @@ void nvic_disable_irq(interrupt::exception_number p_id) *interrupt_clear = p_id.enable_mask(); } -const std::span& interrupt::get_vector_table() +const std::span interrupt::get_vector_table() { return vector_table; } @@ -125,33 +130,57 @@ bool interrupt::verify_vector_enabled(interrupt_pointer p_handler) void interrupt::reset() { + disable_interrupts(); + // Set all bits in the interrupt clear register to 1s to disable those // interrupt vectors. for (auto& clear_interrupt : nvic->icer) { clear_interrupt = 0xFFFF'FFFF; } - set_interrupt_vector_table_address(nullptr); + // Reset vector table + vector_table = std::span(); } void interrupt::setup(std::span p_vector_table) { - if (get_interrupt_vector_table_address() == nullptr) { - // Assign the statically allocated vector within this scope to the global - // vector_table span so that it can be accessed in other - // functions. This is valid because the interrupt vector table has static - // storage duration and will exist throughout the duration of the - // application. - vector_table = p_vector_table; - - // Will fill the interrupt handler and vector table with a function that - // does nothing. - std::fill(vector_table.begin(), vector_table.end(), nop); - - // Relocate the interrupt vector table the vector buffer. By default this - // will be set to the address of the start of flash memory for the MCU. - set_interrupt_vector_table_address(vector_table.data()); + if (p_vector_table.data() == vector_table.data() && + p_vector_table.size() == vector_table.size()) { + return; } + + // Assign the statically allocated vector within this scope to the global + // vector_table span so that it can be accessed in other + // functions. This is valid because the interrupt vector table has static + // storage duration and will exist throughout the duration of the + // application. + vector_table = p_vector_table; + + // Fill the interrupt handler and vector table with a function that does + // nothing functions. Skip the first 2 which are the top of stock and reset + // handlers. + std::fill(vector_table.begin(), vector_table.end(), &nop); + + disable_interrupts(); + + // Relocate the interrupt vector table the vector buffer. By default this + // will be set to the address of the start of flash memory for the MCU. + set_interrupt_vector_table_address(vector_table.data()); + + enable_interrupts(); +} + +void interrupt::disable_interrupts() +{ +#if defined(__arm__) + asm volatile("cpsid i" : : : "memory"); +#endif } +void interrupt::enable_interrupts() +{ +#if defined(__arm__) + asm volatile("cpsie i" : : : "memory"); +#endif +} } // namespace hal::cortex_m diff --git a/src/systick_timer.cpp b/src/systick_timer.cpp index 92031b7..6140f6d 100644 --- a/src/systick_timer.cpp +++ b/src/systick_timer.cpp @@ -55,7 +55,7 @@ void systick_timer::register_cpu_frequency(hertz p_frequency, // reloading of the register and will stop the timer. sys_tick->current_value = 0; - auto control = hal::bit::modify(sys_tick->control); + auto control = hal::bit::value(0); control.set(); if (p_source == clock_source::processor) { @@ -66,6 +66,8 @@ void systick_timer::register_cpu_frequency(hertz p_frequency, // Disable the counter if it was previously enabled. control.clear(); + + sys_tick->control = control.get(); } systick_timer::~systick_timer() @@ -120,7 +122,7 @@ result systick_timer::driver_schedule( // handler cortex_m::interrupt(event_number).enable(handler.get_handler()); - // Set the time reload value + sys_tick->current_value = 0; sys_tick->reload = static_cast(cycle_count); // Starting the timer will restart the count diff --git a/tests/interrupt.test.cpp b/tests/interrupt.test.cpp index 8617efd..5041b2e 100644 --- a/tests/interrupt.test.cpp +++ b/tests/interrupt.test.cpp @@ -36,18 +36,19 @@ void interrupt_test() should("interrupt::initialize()") = [&] { // Setup - expect(that % nullptr == interrupt::vector_table.data()); - expect(that % 0 == interrupt::vector_table.size()); + expect(that % nullptr == interrupt::get_vector_table().data()); + expect(that % 0 == interrupt::get_vector_table().size()); // Exercise interrupt::initialize(); - auto pointer = reinterpret_cast(interrupt::vector_table.data()); + auto pointer = + reinterpret_cast(interrupt::get_vector_table().data()); // Verify - expect(that % nullptr != interrupt::vector_table.data()); + expect(that % nullptr != interrupt::get_vector_table().data()); expect(that % (expected_interrupt_count + interrupt::core_interrupts) == - interrupt::vector_table.size()); + interrupt::get_vector_table().size()); expect(that % pointer == scb->vtor); }; @@ -67,7 +68,7 @@ void interrupt_test() // Verify expect(that % dummy_handler == - interrupt::vector_table[expected_event_number]); + interrupt::get_vector_table()[expected_event_number]); std::uint32_t iser = (1U << bit_position) & nvic->iser.at(index); expect(that % (1 << shifted_event_number) == iser); }; @@ -85,7 +86,7 @@ void interrupt_test() // Verify expect(that % dummy_handler == - interrupt::vector_table[expected_event_number]); + interrupt::get_vector_table()[expected_event_number]); std::uint32_t iser = (1U << bit_position) & nvic->iser.at(index); expect(that % (1 << shifted_event_number) == iser); }; @@ -101,7 +102,7 @@ void interrupt_test() // Verify // Verify: That the dummy handler was added to the IVT (ISER) expect(that % dummy_handler == - interrupt::vector_table[expected_event_number]); + interrupt::get_vector_table()[expected_event_number]); // Verify: ISER[] should not have changed when enable() succeeds but the // IRQ is less than 0. for (size_t i = 0; i < old_nvic.iser.size(); i++) { @@ -121,8 +122,10 @@ void interrupt_test() // Verify // Verify: Nothing in the interrupt vector table should have changed - for (const auto& interrupt_function : interrupt::vector_table) { - expect(that % &interrupt::nop == interrupt_function); + for (const auto interrupt_function : interrupt::get_vector_table()) { + auto nop_address = reinterpret_cast(&interrupt::nop); + auto function_address = reinterpret_cast(interrupt_function); + expect(that % nop_address == function_address); } // Verify: ISER[] should not have changed when enable() fails. @@ -147,7 +150,7 @@ void interrupt_test() // Verify expect(that % &interrupt::nop == - interrupt::vector_table[expected_event_number]); + interrupt::get_vector_table()[expected_event_number]); std::uint32_t icer = (1U << bit_position) & nvic->icer.at(index); expect(that % (1 << shifted_event_number) == icer); @@ -167,7 +170,7 @@ void interrupt_test() // Verify expect(that % &interrupt::nop == - interrupt::vector_table[expected_event_number]); + interrupt::get_vector_table()[expected_event_number]); std::uint32_t icer = (1U << bit_position) & nvic->icer.at(index); expect(that % (1 << shifted_event_number) == icer); @@ -184,7 +187,7 @@ void interrupt_test() // Verify // Verify: That the dummy handler was added to the IVT (icer ) expect(that % &interrupt::nop == - interrupt::vector_table[expected_event_number]); + interrupt::get_vector_table()[expected_event_number]); // Verify: icer[] should not have changed when disable() succeeds but the // IRQ is less than 0. for (size_t i = 0; i < old_nvic.icer.size(); i++) { @@ -203,8 +206,10 @@ void interrupt_test() interrupt(expected_event_number).disable(); // Verify: Nothing in the interrupt vector table should have changed - for (const auto& interrupt_function : interrupt::vector_table) { - expect(that % &interrupt::nop == interrupt_function); + for (const auto interrupt_function : interrupt::get_vector_table()) { + auto nop_address = reinterpret_cast(&interrupt::nop); + auto function_address = reinterpret_cast(interrupt_function); + expect(that % nop_address == function_address); } // Verify: icer[] should not have changed when disable() fails. @@ -216,13 +221,13 @@ void interrupt_test() should("interrupt::get_vector_table()") = [&] { // Setup - expect(that % nullptr != interrupt::vector_table.data()); - expect(that % 0 != interrupt::vector_table.size()); + expect(that % nullptr != interrupt::get_vector_table().data()); + expect(that % 0 != interrupt::get_vector_table().size()); // Exercise & Verify - expect(interrupt::vector_table.data() == + expect(interrupt::get_vector_table().data() == interrupt::get_vector_table().data()); - expect(that % interrupt::vector_table.size() == + expect(that % interrupt::get_vector_table().size() == interrupt::get_vector_table().size()); }; };