Skip to content

Commit 6057873

Browse files
salkiniummcbridejc
andcommitted
[irq] Validate IRQ name on Cortex-M devices
Co-authored-by: Jeff McBride <[email protected]>
1 parent 69b5bf9 commit 6057873

File tree

3 files changed

+104
-0
lines changed

3 files changed

+104
-0
lines changed

src/modm/architecture/interface/interrupt.hpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@
6262
* This maps to `MODM_ISR_NAME({vector})()`.
6363
* @note You may have to forward declare the interrupt using `MODM_ISR_DECL({vector})`.
6464
*
65+
* On Cortex-M the vector name is validated at compile time against the device's
66+
* vector table, so that misspelled vector names get caught during compilation.
67+
* If this is undesirable you can manually call the vector using
68+
* `MODM_ISR_NAME(vector)()` or disable the validation by defining
69+
* `MODM_ISR_DISABLE_VALIDATION`.
70+
*
6571
* @param vector
6672
* The name of the interrupt without any suffix (neither `_vect`, nor `_IRQHandler`).
6773
*
@@ -79,6 +85,10 @@
7985
* On Cortex-M and Hosted this maps to `void MODM_ISR_NAME({vector})(void) args`.
8086
* `extern "C"` is automatically added in a C++ environment.
8187
*
88+
* On Cortex-M the vector name is validated at compile time against the device's
89+
* vector table, so that misspelled vector names get caught during compilation.
90+
* You can disable the validation by defining `MODM_ISR_DISABLE_VALIDATION`.
91+
*
8292
* @param vector
8393
* The name of the interrupt without any suffix (neither `_vect`, nor `_IRQHandler`).
8494
* @param ...
@@ -103,13 +113,27 @@
103113

104114
#elif defined MODM_CPU_ARM
105115

116+
117+
#ifdef __cplusplus
118+
# include <modm/platform/core/vectors.hpp>
119+
#else
120+
# ifndef MODM_ISR_DISABLE_VALIDATION
121+
# define MODM_ISR_VALIDATE(vector_str, vector) \
122+
_Static_assert(vector ## _IRQn > -127);
123+
# else
124+
# define MODM_ISR_VALIDATE(...)
125+
# endif
126+
#endif
127+
106128
# define MODM_ISR_NAME(vector) \
107129
vector ## _IRQHandler
108130
# define MODM_ISR_DECL(vector) \
109131
modm_extern_c void vector ## _IRQHandler(void)
110132
# define MODM_ISR_CALL(vector) \
133+
MODM_ISR_VALIDATE(#vector, vector); \
111134
vector ## _IRQHandler()
112135
# define MODM_ISR(vector, ...) \
136+
MODM_ISR_VALIDATE(#vector, vector); \
113137
modm_extern_c void vector ## _IRQHandler(void) \
114138
__attribute__((externally_visible)) __VA_ARGS__; \
115139
void vector ## _IRQHandler(void)

src/modm/platform/core/cortex/module.lb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ def build(env):
296296
env.template("reset_handler.sx.in")
297297
env.template("startup.c.in")
298298
env.template("vectors.c.in")
299+
env.template("vectors.hpp.in")
299300
env.collect(":build:linkflags", "-nostartfiles")
300301

301302
# dealing with runtime assertions
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright (c) 2021, Niklas Hauser
3+
*
4+
* This file is part of the modm project.
5+
*
6+
* This Source Code Form is subject to the terms of the Mozilla Public
7+
* License, v. 2.0. If a copy of the MPL was not distributed with this
8+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
// ----------------------------------------------------------------------------
11+
12+
#pragma once
13+
14+
#include <stdint.h>
15+
#include <modm/architecture/utils.hpp>
16+
#include <string_view>
17+
18+
extern "C"
19+
{
20+
21+
void Reset_Handler(void);
22+
void NMI_Handler(void);
23+
void HardFault_Handler(void);
24+
%% for pos in range(4 - 16, highest_irq + 1)
25+
%% if pos in vector_table
26+
void {{vector_table[pos]}}(void);
27+
%% endif
28+
%% endfor
29+
30+
}
31+
32+
namespace modm::platform::detail
33+
{
34+
35+
constexpr std::string_view vectorNames[] =
36+
{
37+
"__main_stack_top",
38+
"Reset",
39+
"NMI",
40+
"HardFault",
41+
%% for pos in range(4 - 16, highest_irq)
42+
%% if pos in vector_table
43+
"{{vector_table[pos] | replace('_Handler', '') | replace('_IRQHandler', '')}}",
44+
%% else
45+
"Undefined",
46+
%% endif
47+
%% endfor
48+
};
49+
50+
51+
#ifndef MODM_ISR_DISABLE_VALIDATION
52+
#define MODM_ISR_VALIDATE(vector_str, vector) \
53+
static_assert(::modm::platform::detail::validateIrqName(vector_str), \
54+
"'" vector_str "' is not a valid IRQ name!\n" \
55+
" Hint: You do not need to add '_IRQHandler' to the name.\n" \
56+
" Hint: Here are all the IRQs on this device:\n" \
57+
%% for pos in range(0, highest_irq)
58+
%% if pos in vector_table
59+
" - {{vector_table[pos] | replace('_Handler', '') | replace('_IRQHandler', '')}}\n" \
60+
%% endif
61+
%% endfor
62+
)
63+
#else
64+
#define MODM_ISR_VALIDATE(...)
65+
#endif
66+
67+
constexpr int getIrqPosition(std::string_view name)
68+
{
69+
for (int pos = 0; pos < {{highest_irq+16}}; pos++)
70+
if (vectorNames[pos] == name) return pos;
71+
return -1;
72+
}
73+
74+
constexpr bool validateIrqName(std::string_view name)
75+
{
76+
return getIrqPosition(name) != -1;
77+
}
78+
79+
} // namespace modm::platform::detail

0 commit comments

Comments
 (0)