diff --git a/src/modm/platform/can/stm32-fdcan/can.cpp.in b/src/modm/platform/can/stm32-fdcan/can.cpp.in index 5fe3c7930a..a45db93930 100644 --- a/src/modm/platform/can/stm32-fdcan/can.cpp.in +++ b/src/modm/platform/can/stm32-fdcan/can.cpp.in @@ -212,7 +212,12 @@ modm::platform::Fdcan{{ id }}::initializeWithPrescaler( // line 0 used as TX and error interrupt // generated on finished frame transmission and error state +%% if shared_irq_it0 +void +modm::platform::Fdcan{{ id }}::irqIT0() +%% else MODM_ISR({{ reg }}_IT0) +%% endif { %% if options["buffer.tx"] > 0 if ({{ reg }}->IR & FDCAN_IR_TC) { @@ -239,7 +244,12 @@ MODM_ISR({{ reg }}_IT0) // line 1 used as RX interrupt // generated on received frame +%% if shared_irq_it1 +void +modm::platform::Fdcan{{ id }}::irqIT1() +%% else MODM_ISR({{ reg }}_IT1) +%% endif { %% if options["buffer.rx"] > 0 int_fast16_t msgRetrieveLimit = rxQueue.getMaxSize() - rxQueue.getSize(); @@ -315,11 +325,21 @@ modm::platform::Fdcan{{ id }}::configureMode(Mode mode) void modm::platform::Fdcan{{ id }}::configureInterrupts(uint32_t interruptPriority) { +%% if shared_irq_it0 + NVIC_SetPriority({{ shared_irq_it0 }}_IRQn, interruptPriority); + NVIC_EnableIRQ({{ shared_irq_it0 }}_IRQn); +%% else NVIC_SetPriority({{ reg }}_IT0_IRQn, interruptPriority); - NVIC_SetPriority({{ reg }}_IT1_IRQn, interruptPriority); - NVIC_EnableIRQ({{ reg }}_IT0_IRQn); +%% endif + +%% if shared_irq_it1 + NVIC_SetPriority({{ shared_irq_it1 }}_IRQn, interruptPriority); + NVIC_EnableIRQ({{ shared_irq_it1 }}_IRQn); +%% else + NVIC_SetPriority({{ reg }}_IT1_IRQn, interruptPriority); NVIC_EnableIRQ({{ reg }}_IT1_IRQn); +%% endif // enable both interrupts lines (0 and 1) {{ reg }}->ILE = FDCAN_ILE_EINT1 | FDCAN_ILE_EINT0; diff --git a/src/modm/platform/can/stm32-fdcan/can.hpp.in b/src/modm/platform/can/stm32-fdcan/can.hpp.in index cece052457..e185516353 100644 --- a/src/modm/platform/can/stm32-fdcan/can.hpp.in +++ b/src/modm/platform/can/stm32-fdcan/can.hpp.in @@ -358,8 +358,21 @@ private: EnterInitMode(const EnterInitMode&) = delete; EnterInitMode& operator=(const EnterInitMode&) = delete; }; -}; +%% if shared_irq_it0 + friend void ::{{ shared_irq_it0 }}_IRQHandler(); + + static void + irqIT0(); +%% endif + +%% if shared_irq_it0 + friend void ::{{ shared_irq_it1 }}_IRQHandler(); + + static void + irqIT1(); +%% endif +}; } // namespace modm::platform #endif // MODM_STM32_FDCAN{{ id }}_HPP diff --git a/src/modm/platform/can/stm32-fdcan/can_shared_irqs.cpp.in b/src/modm/platform/can/stm32-fdcan/can_shared_irqs.cpp.in new file mode 100644 index 0000000000..3187823f64 --- /dev/null +++ b/src/modm/platform/can/stm32-fdcan/can_shared_irqs.cpp.in @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023, Klaus Schnass (Zuehlke Engineering) + * + * 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/. + */ +// ---------------------------------------------------------------------------- +#include +#include +#include + +%% for instances in shared_irqs.values() +%% for instance in instances | sort +#include "can_{{ instance[0] }}.hpp" +%% endfor +%% endfor + +%% for irq,instances in shared_irqs.items() +MODM_ISR({{ irq }}) +{ +%% for id,line in instances | sort + modm::platform::Fdcan{{ id }}::irq{{ line }}(); +%% endfor +} +%% endfor diff --git a/src/modm/platform/can/stm32-fdcan/module.lb b/src/modm/platform/can/stm32-fdcan/module.lb index 6bcc460042..548aa40567 100644 --- a/src/modm/platform/can/stm32-fdcan/module.lb +++ b/src/modm/platform/can/stm32-fdcan/module.lb @@ -12,6 +12,10 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # ----------------------------------------------------------------------------- +from collections import defaultdict + +global_properties = {} + def load_options(module): module.add_option( NumericOption( @@ -26,6 +30,13 @@ def load_options(module): minimum=1, maximum="64Ki-2", default=32)) +def get_shared_irq(device, irq): + irqs = [v["name"] for v in device.get_driver("core")["vector"]] + irqs = [v for v in irqs if irq in v] + assert(len(irqs) == 1) + + return irqs[0] + class Instance(Module): def __init__(self, instance): self.instance = instance @@ -39,6 +50,7 @@ class Instance(Module): return True def build(self, env): + global global_properties device = env[":target"] driver = device.get_driver("fdcan") @@ -47,6 +59,16 @@ class Instance(Module): properties["driver"] = driver properties["id"] = self.instance properties["reg"] = 'FDCAN{}'.format(self.instance) + properties["shared_irq_it0"] = False + properties["shared_irq_it1"] = False + + if device.identifier.family == "g0": + shared_irq_it0 = get_shared_irq(device, "FDCAN_IT0") + properties["shared_irq_it0"] = shared_irq_it0 + global_properties["shared_irqs"][shared_irq_it0].append([self.instance, "IT0"]) + shared_irq_it1 = get_shared_irq(device, "FDCAN_IT1") + properties["shared_irq_it1"] = shared_irq_it1 + global_properties["shared_irqs"][shared_irq_it1].append([self.instance, "IT1"]) env.substitutions = properties env.outbasepath = "modm/src/modm/platform/can" @@ -64,11 +86,6 @@ def prepare(module, options): if not device.has_driver("fdcan:stm32"): return False - # STM32G0 devices are currently unsupported due to shared interrupt handler - # TODO: fix driver - if device.identifier.family == "g0": - return False - module.depends( ":architecture:assert", ":architecture:atomic", @@ -83,6 +100,8 @@ def prepare(module, options): ":platform:rcc", ":utils") + global_properties["shared_irqs"] = defaultdict(list) + driver = device.get_driver("fdcan") for instance in listify(driver["instance"]): @@ -91,5 +110,9 @@ def prepare(module, options): return True def build(env): + env.substitutions.update(global_properties) env.outbasepath = "modm/src/modm/platform/can" + env.copy("message_ram.hpp") + if len(global_properties["shared_irqs"]) > 0: + env.template("can_shared_irqs.cpp.in")