Skip to content

Commit

Permalink
[irq] Validate IRQ name on Cortex-M devices
Browse files Browse the repository at this point in the history
Co-authored-by: Jeff McBride <mcbridejc@gmail.com>
  • Loading branch information
salkinium and mcbridejc committed Sep 17, 2021
1 parent 69b5bf9 commit 6057873
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 0 deletions.
24 changes: 24 additions & 0 deletions src/modm/architecture/interface/interrupt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@
* This maps to `MODM_ISR_NAME({vector})()`.
* @note You may have to forward declare the interrupt using `MODM_ISR_DECL({vector})`.
*
* On Cortex-M the vector name is validated at compile time against the device's
* vector table, so that misspelled vector names get caught during compilation.
* If this is undesirable you can manually call the vector using
* `MODM_ISR_NAME(vector)()` or disable the validation by defining
* `MODM_ISR_DISABLE_VALIDATION`.
*
* @param vector
* The name of the interrupt without any suffix (neither `_vect`, nor `_IRQHandler`).
*
Expand All @@ -79,6 +85,10 @@
* On Cortex-M and Hosted this maps to `void MODM_ISR_NAME({vector})(void) args`.
* `extern "C"` is automatically added in a C++ environment.
*
* On Cortex-M the vector name is validated at compile time against the device's
* vector table, so that misspelled vector names get caught during compilation.
* You can disable the validation by defining `MODM_ISR_DISABLE_VALIDATION`.
*
* @param vector
* The name of the interrupt without any suffix (neither `_vect`, nor `_IRQHandler`).
* @param ...
Expand All @@ -103,13 +113,27 @@

#elif defined MODM_CPU_ARM


#ifdef __cplusplus
# include <modm/platform/core/vectors.hpp>
#else
# ifndef MODM_ISR_DISABLE_VALIDATION
# define MODM_ISR_VALIDATE(vector_str, vector) \
_Static_assert(vector ## _IRQn > -127);
# else
# define MODM_ISR_VALIDATE(...)
# endif
#endif

# define MODM_ISR_NAME(vector) \
vector ## _IRQHandler
# define MODM_ISR_DECL(vector) \
modm_extern_c void vector ## _IRQHandler(void)
# define MODM_ISR_CALL(vector) \
MODM_ISR_VALIDATE(#vector, vector); \
vector ## _IRQHandler()
# define MODM_ISR(vector, ...) \
MODM_ISR_VALIDATE(#vector, vector); \
modm_extern_c void vector ## _IRQHandler(void) \
__attribute__((externally_visible)) __VA_ARGS__; \
void vector ## _IRQHandler(void)
Expand Down
1 change: 1 addition & 0 deletions src/modm/platform/core/cortex/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ def build(env):
env.template("reset_handler.sx.in")
env.template("startup.c.in")
env.template("vectors.c.in")
env.template("vectors.hpp.in")
env.collect(":build:linkflags", "-nostartfiles")

# dealing with runtime assertions
Expand Down
79 changes: 79 additions & 0 deletions src/modm/platform/core/cortex/vectors.hpp.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright (c) 2021, Niklas Hauser
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#pragma once

#include <stdint.h>
#include <modm/architecture/utils.hpp>
#include <string_view>

extern "C"
{

void Reset_Handler(void);
void NMI_Handler(void);
void HardFault_Handler(void);
%% for pos in range(4 - 16, highest_irq + 1)
%% if pos in vector_table
void {{vector_table[pos]}}(void);
%% endif
%% endfor

}

namespace modm::platform::detail
{

constexpr std::string_view vectorNames[] =
{
"__main_stack_top",
"Reset",
"NMI",
"HardFault",
%% for pos in range(4 - 16, highest_irq)
%% if pos in vector_table
"{{vector_table[pos] | replace('_Handler', '') | replace('_IRQHandler', '')}}",
%% else
"Undefined",
%% endif
%% endfor
};


#ifndef MODM_ISR_DISABLE_VALIDATION
#define MODM_ISR_VALIDATE(vector_str, vector) \
static_assert(::modm::platform::detail::validateIrqName(vector_str), \
"'" vector_str "' is not a valid IRQ name!\n" \
" Hint: You do not need to add '_IRQHandler' to the name.\n" \
" Hint: Here are all the IRQs on this device:\n" \
%% for pos in range(0, highest_irq)
%% if pos in vector_table
" - {{vector_table[pos] | replace('_Handler', '') | replace('_IRQHandler', '')}}\n" \
%% endif
%% endfor
)
#else
#define MODM_ISR_VALIDATE(...)
#endif

constexpr int getIrqPosition(std::string_view name)
{
for (int pos = 0; pos < {{highest_irq+16}}; pos++)
if (vectorNames[pos] == name) return pos;
return -1;
}

constexpr bool validateIrqName(std::string_view name)
{
return getIrqPosition(name) != -1;
}

} // namespace modm::platform::detail

0 comments on commit 6057873

Please sign in to comment.