Skip to content

Commit

Permalink
shared IRQ handling for fdcan on STM32G0
Browse files Browse the repository at this point in the history
  • Loading branch information
Klaus Schnass committed Jul 21, 2023
1 parent 8012d82 commit a05cc62
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 9 deletions.
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")

0 comments on commit a05cc62

Please sign in to comment.