Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for custom IRQ Handlers #307

Draft
wants to merge 10 commits into
base: develop
Choose a base branch
from
2 changes: 1 addition & 1 deletion repo.lb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ from os.path import normpath

# Check for miminum required lbuild version
import lbuild
min_lbuild_version = "1.12.1"
min_lbuild_version = "1.13.0"
if StrictVersion(getattr(lbuild, "__version__", "0.1.0")) < StrictVersion(min_lbuild_version):
print("modm requires at least lbuild v{}, please upgrade!\n"
" pip3 install -U lbuild".format(min_lbuild_version))
Expand Down
24 changes: 17 additions & 7 deletions src/modm/platform/can/stm32/can.cpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* Copyright (c) 2014, Georgi Grinshpun
* Copyright (c) 2014, 2016-2018, Niklas Hauser
* Copyright (c) 2018, Christopher Durand
* Copyright (c) 2019, Benjamin Weps
*
* This file is part of the modm project.
*
Expand Down Expand Up @@ -214,13 +215,18 @@ readMailbox(modm::can::Message& message, uint32_t mailboxId, uint8_t* filter_id)
reinterpret_cast<uint32_t *>(data)[1] = mailbox->RDHR;
}


extern "C"
{

// ----------------------------------------------------------------------------
/* Transmit Interrupt
*
* Generated when Transmit Mailbox 0..2 becomes empty.
*/

MODM_ISR({{ reg }}_TX)
void
Can{{ id }}_Tx(void)
{
%% if options["buffer.tx"] > 0
uint32_t mailbox;
Expand Down Expand Up @@ -253,7 +259,8 @@ MODM_ISR({{ reg }}_TX)
* Generated on a new received message, FIFO0 full condition and Overrun
* Condition.
*/
MODM_ISR({{ reg }}_RX0)
void
Can{{ id }}_Rx0(void)
{
if ({{ reg }}->RF0R & CAN_RF0R_FOVR0) {
modm::ErrorReport::report(modm::platform::CAN{{ id }}_FIFO0_OVERFLOW);
Expand All @@ -280,7 +287,8 @@ MODM_ISR({{ reg }}_RX0)
*
* See FIFO0 Interrupt
*/
MODM_ISR({{ reg }}_RX1)
void
Can{{ id }}_Rx1(void)
{
if ({{ reg }}->RF1R & CAN_RF1R_FOVR1) {
modm::ErrorReport::report(modm::platform::CAN{{ id }}_FIFO1_OVERFLOW);
Expand Down Expand Up @@ -308,24 +316,26 @@ MODM_ISR({{ reg }}_RX1)
// the interrupt source and call the correct interrupts function defined above.
// Sources for the different interrupts are specified in the Reference Manual
// in the "bxCAN interrupts" section.
MODM_ISR(CEC_CAN)
void
Can{{ id }}_GenericIsr(void)
{
if({{ reg }}->TSR & (CAN_TSR_RQCP0 | CAN_TSR_RQCP1 | CAN_TSR_RQCP2)) {
MODM_ISR_CALL({{ reg }}_TX);
Can{{ id }}_Tx();
}

if({{ reg }}->RF0R & (CAN_RF0R_FMP0 | CAN_RF0R_FULL0 | CAN_RF0R_FOVR0)) {
MODM_ISR_CALL({{ reg }}_RX0);
Can{{ id }}_Rx0();
}

if({{ reg }}->RF1R & (CAN_RF1R_FMP1 | CAN_RF1R_FULL1 | CAN_RF1R_FOVR1)) {
MODM_ISR_CALL({{ reg }}_RX1);
Can{{ id }}_Rx1();
}

// TODO: we do not handle status changes at the moment.
}
%% endif

}
// ----------------------------------------------------------------------------
void
modm::platform::Can{{ id }}::setMode(Mode mode)
Expand Down
2 changes: 2 additions & 0 deletions src/modm/platform/can/stm32/can.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Copyright (c) 2014-2018, Niklas Hauser
* Copyright (c) 2017, Fabian Greif
* Copyright (c) 2018, Christopher Durand
* Copyright (c) 2019, Benjamin Weps
*
* This file is part of the modm project.
*
Expand Down Expand Up @@ -213,6 +214,7 @@ public:
static void
enableStatusChangeInterrupt(uint32_t interruptEnable,
uint32_t interruptPriority);

};

} // namespace platform
Expand Down
8 changes: 8 additions & 0 deletions src/modm/platform/can/stm32/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ class Instance(Module):
env.template("can.hpp.in", "can_{}.hpp".format(self.instance))
env.template("can.cpp.in", "can_{}.cpp".format(self.instance))

env.collect(":platform:cortex-m:vector_hooks",
"CAN{0}_TX:Can{0}_Tx".format(self.instance),
"CAN{0}_RX0:Can{0}_Rx0".format(self.instance),
"CAN{0}_RX1:Can{0}_Rx1".format(self.instance))

def init(module):
module.name = ":platform:can"
Expand Down Expand Up @@ -179,3 +183,7 @@ def build(env):
if "instance" not in driver:
env.template("can.hpp.in")
env.template("can.cpp.in")

if device.identifier.family == "f0":
env.collect(":platform:cortex-m:vector_hooks",
"CEC_CAN:Can_GenericIsr")
35 changes: 33 additions & 2 deletions src/modm/platform/core/cortex/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
def common_vector_table_location(env):
return env.get(":platform:cortex-m:vector_table_location", "rom")


def common_vector_table(env):
"""
Computes vector table properties:
Expand Down Expand Up @@ -55,12 +54,14 @@ def common_vector_table(env):
for vector in driver["vector"]:
interrupts[int(vector["position"])] = vector["name"] + "_IRQHandler"


properties = {
"core": core,
"vector_table_location": common_vector_table_location(env),
"vector_table": interrupts,
"highest_irq": max(interrupts.keys()) + 1,
}

return properties


Expand Down Expand Up @@ -138,6 +139,12 @@ def common_linkerscript(env):
properties.update(common_memories(env))
return properties

def common_default_vectors(env):
vectors = dict()
for vectorString in env.collector_values(":platform:cortex-m:vector_hooks"):
tokens = vectorString.split(':')
vectors[tokens[0]+"_IRQHandler"]={'name':tokens[0],'call':tokens[1]}
return vectors

def init(module):
module.name = ":platform:cortex-m"
Expand Down Expand Up @@ -222,6 +229,23 @@ def prepare(module, options):
description="Maximum required size of the process stack",
minimum=0))


vectors = [v["name"] for v in options[":target"].get_driver("core")["vector"]]
def validate_vector(value):
if ":" not in value:
raise ValueError("Input must be formatted as 'vector:function[:priority]'!")
name = value.split(":")[0]
if name not in vectors:
from lbuild.exception import _bp, _hl
raise ValueError(_hl("Vector '{}' is unknown!\n".format(name)) +
"Available vectors are:\n\n" + _bp(vectors))

module.add_collector(
StringCollector(
name="vector_hooks",
description="Default interrupt vectors for the enabled peripherals",
validate=validate_vector))

module.add_query(
EnvironmentQuery(name="vector_table", factory=common_vector_table))
module.add_query(
Expand Down Expand Up @@ -260,7 +284,6 @@ def build(env):
# startup script
env.copy("reset_handler.sx")
env.template("startup.c.in")
env.template("vectors.c.in")

# dealing with runtime assertions
env.copy("assert.cpp")
Expand Down Expand Up @@ -301,3 +324,11 @@ def build(env):
if env.has_module(":architecture:unaligned"):
env.template("unaligned.hpp.in")

def post_build(env):
env.substitutions = env.query("vector_table")
env.substitutions["partname"] = env[":target"].partname
env.substitutions["with_fault_storage"] = env.has_module(":platform:fault")
env.substitutions["vector_hooks"] = common_default_vectors(env)
env.outbasepath = "modm/src/modm/platform/core"

env.template("vectors.c.in")
18 changes: 18 additions & 0 deletions src/modm/platform/core/cortex/vectors.c.in
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,20 @@
#include <modm/architecture/utils.hpp>
#include <modm/architecture/interface/assert.h>


// ----------------------------------------------------------------------------
/*
* Default Interrupt Vectors for Peripherals
*/
%% for isr in vector_hooks
extern void {{vector_hooks[isr]['call']}}(void);
void {{vector_hooks[isr]['name']}}_forwarder(void)
{
{{vector_hooks[isr]['call']}}();
}

%% endfor

// ----------------------------------------------------------------------------
extern void modm_undefined_handler(int32_t);
void Undefined_Handler(void)
Expand All @@ -29,7 +43,11 @@ void NMI_Handler(void) __attribute__((weak, alias("Undefined_Handler")));
void HardFault_Handler(void) __attribute__((weak, alias("Undefined_Handler")));
%% for pos in range(4 - 16, highest_irq + 1)
%% if pos in vector_table
%% if vector_table[pos] in vector_hooks
{{ ("void " ~ vector_table[pos] ~ "(void)") | lbuild.pad(47)}}__attribute__((weak, alias("{{vector_hooks[vector_table[pos]]['name']}}_forwarder")));
%% else
{{ ("void " ~ vector_table[pos] ~ "(void)") | lbuild.pad(47)}}__attribute__((weak, alias("Undefined_Handler")));
%% endif
%% endif
%% endfor

Expand Down
9 changes: 6 additions & 3 deletions tools/build_script_generator/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# -----------------------------------------------------------------------------

import os
import os, sys

# import all common code
with open(localpath("common.py")) as common:
Expand All @@ -20,6 +20,8 @@ with open(localpath("common.py")) as common:
def init(module):
module.name = ":build"
module.description = FileReader("module.md")
# Force post-build steps of this submodule tree to be built last
module.order = sys.maxsize


def prepare(module, options):
Expand Down Expand Up @@ -128,6 +130,9 @@ def build(env):
# Append common search paths to metadata
if env.has_collector(":build:path.openocd"):
env.collect(":build:path.openocd", "modm/openocd")
env.outbasepath = "modm"
env.copy("openocd_gdbinit")
env.copy("gdbinit")

# Add compiler flags to metadata
for flag, values in common_compiler_flags("gcc", env[":target"]).items():
Expand Down Expand Up @@ -157,8 +162,6 @@ def post_build(env):
if len(openocd_cfg):
env.substitutions["openocd_user_path"] = env.relative_outpath(openocd_cfg)
env.template("openocd.cfg.in")
env.template("openocd_gdbinit.in")
env.template("gdbinit")


# ============================ Option Descriptions ============================
Expand Down