File interrupt.hpp
File List > include > libhal-armcortex > interrupt.hpp
Go to the documentation of this file
// 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.
#pragma once
#include <array>
#include <span>
#include <utility>
#include <libhal/error.hpp>
namespace hal::cortex_m {
using interrupt_pointer = void (*)();
enum class irq
{
top_of_stack = 0,
reset = 1,
nmi = 2,
hard_fault = 3,
memory_management_fault = 4,
bus_fault = 5,
usage_fault = 6,
reserve7 = 7,
reserve8 = 8,
reserve9 = 9,
reserve10 = 10,
sv_call = 11,
reserve12 = 12,
reserve13 = 13,
pend_sv = 14,
systick = 15,
};
class interrupt
{
public:
static constexpr size_t core_interrupts = 16;
class exception_number
{
public:
constexpr exception_number(std::uint16_t p_id)
: m_id(p_id)
{
}
constexpr exception_number(exception_number& p_id) = default;
constexpr exception_number& operator=(exception_number& p_id) = default;
static constexpr uint32_t index_position = 5;
static constexpr uint32_t enable_mask_code = 0x1F;
[[nodiscard]] constexpr bool default_enabled() const
{
return m_id < core_interrupts;
}
[[nodiscard]] constexpr std::uint32_t to_irq_number() const
{
return static_cast<std::uint32_t>(m_id - core_interrupts);
}
[[nodiscard]] constexpr std::uint32_t register_index() const
{
return to_irq_number() >> index_position;
}
[[nodiscard]] constexpr std::uint32_t enable_mask() const
{
return 1U << (to_irq_number() & enable_mask_code);
}
[[nodiscard]] constexpr size_t vector_index() const
{
return m_id;
}
[[nodiscard]] bool is_valid() const
{
return m_id < get_vector_table().size();
}
[[nodiscard]] constexpr std::uint16_t get_event_number()
{
return m_id;
}
private:
std::uint16_t m_id = 0;
};
static void nop();
template<size_t VectorCount>
static void initialize()
{
// Statically allocate a buffer of vectors to be used as the new IVT.
static constexpr size_t total_vector_count = VectorCount + core_interrupts;
alignas(512) static std::array<interrupt_pointer, total_vector_count>
vector_buffer{};
setup(vector_buffer);
}
template<size_t VectorCount>
static void reinitialize()
{
reset();
initialize<VectorCount>();
}
static const std::span<interrupt_pointer> get_vector_table();
static void disable_interrupts();
static void enable_interrupts();
explicit interrupt(exception_number p_id);
void enable(interrupt_pointer p_handler);
void disable();
[[nodiscard]] bool verify_vector_enabled(interrupt_pointer p_handler);
private:
static void reset();
static void setup(std::span<interrupt_pointer> p_vector_table);
exception_number m_id;
};
} // namespace hal::cortex_m