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

shared IRQ handling for fdcan on STM32G0 #1051

Merged
merged 1 commit into from
Jul 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ Please [discover modm's peripheral drivers for your specific device][discover].
<td align="center">✅</td>
<td align="center">✅</td>
<td align="center">✅</td>
<td align="center"></td>
<td align="center"></td>
<td align="center">✅</td>
<td align="center">○</td>
<td align="center">✕</td>
Expand Down
24 changes: 22 additions & 2 deletions src/modm/platform/can/stm32-fdcan/can.cpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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();
Expand Down Expand Up @@ -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;
Expand Down
15 changes: 14 additions & 1 deletion src/modm/platform/can/stm32-fdcan/can.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
28 changes: 28 additions & 0 deletions src/modm/platform/can/stm32-fdcan/can_shared_irqs.cpp.in
Original file line number Diff line number Diff line change
@@ -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 <cstring>
#include <modm/architecture/interface/delay.hpp>
#include <modm/architecture/interface/interrupt.hpp>

%% 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
33 changes: 28 additions & 5 deletions src/modm/platform/can/stm32-fdcan/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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
Expand All @@ -39,6 +50,7 @@ class Instance(Module):
return True

def build(self, env):
global global_properties
device = env[":target"]
driver = device.get_driver("fdcan")

Expand All @@ -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"
Expand All @@ -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",
Expand All @@ -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"]):
Expand All @@ -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")