Skip to content

Commit

Permalink
[stm32] Enable DMA for even more devices
Browse files Browse the repository at this point in the history
  • Loading branch information
chris-durand committed Jun 6, 2021
1 parent 12b2421 commit f3dd039
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 65 deletions.
19 changes: 8 additions & 11 deletions src/modm/platform/dma/stm32/dma.cpp.in
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2020, Mike Wolfram
* Copyright (c) 2021, Christopher Durand
*
* This file is part of the modm project.
*
Expand All @@ -13,18 +14,14 @@

using namespace modm::platform;

%% for instance, irqs in irqList.items()
/*
* IRQ handler for DMA{{ instance }}
*/
%% for channels in irqs

MODM_ISR(DMA{{ instance }}_Channel{{ channels | join("_") }})
%% for irq in irqList
MODM_ISR({{ irq["name"] }})
{
%% for channel in channels
Dma{{ instance }}::Channel<DmaBase::Channel::Channel{{ channel }}>::interruptHandler();
%% endfor
%% for instance in irq["instances"]
%% for channel in instance["channels"]
Dma{{ instance["instance"] }}::Channel<DmaBase::Channel::Channel{{ channel }}>::interruptHandler();
%% endfor
%% endfor
}

%% endfor
%% endfor
4 changes: 2 additions & 2 deletions src/modm/platform/dma/stm32/dma.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ public:
%% if signal.instance is defined
%% set peripheral = peripheral ~ signal.instance
%% else
%% if peripheral in ["Dac", "Lpuart", "Swpmi"] and target["family"] not in ["f1", "f3", "l0", "l1"]
%% if peripheral in ["Dac", "Lpuart", "Swpmi"] and target["family"] not in ["f0", "f1", "f3", "l0", "l1"]
%% set peripheral = peripheral ~ 1
%% endif
%% endif
Expand Down Expand Up @@ -474,7 +474,7 @@ namespace dma
%% if signal.instance is defined
%% set peripheral = peripheral ~ signal.instance
%% else
%% if peripheral in ["Dac", "Lpuart", "Swpmi"] and target["family"] not in ["f1", "f3", "l0", "l1"]
%% if peripheral in ["Dac", "Lpuart", "Swpmi"] and target["family"] not in ["f0", "f1", "f3", "l0", "l1"]
%% set peripheral = peripheral ~ 1
%% endif
%% endif
Expand Down
10 changes: 5 additions & 5 deletions src/modm/platform/dma/stm32/dma_base.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -263,18 +263,18 @@ protected:
struct Nvic;
};

%% for instance, irqs in irqList.items()
%% for controller in dmaController
%% set instance=controller["instance"]
template <>
struct DmaBase::Nvic<{{ instance }}>
{
static constexpr IRQn_Type DmaIrqs[] {
%% for channels in irqs
%% for i in range(channels | length)
DMA{{ instance }}_Channel{{ channels | join("_") }}_IRQn,
%% endfor
%% for channel in range(controller["min_channel"], controller["max_channel"] + 1)
{{ irqMap[instance][channel] }}_IRQn,
%% endfor
};
};

%% endfor

} // namespace platform
Expand Down
101 changes: 54 additions & 47 deletions src/modm/platform/dma/stm32/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
# -----------------------------------------------------------------------------

from collections import defaultdict
import re

def init(module):
module.name = ":platform:dma"
Expand All @@ -39,37 +40,41 @@ def prepare(module, options):
# Enable DMA for all but some devices...

if did["family"] in ["f0"]:
if did["name"] in ["30", "71", "72", "78", "91", "98"]:
# STM32F09x has shared interrupts between DMA1 and DMA2, not supported...
if did["name"] in ["91", "98"] or (did["name"] == "30" and did["size"] == "c"):
# type "stm32-channel-request" incompatible to driver
return False
return True

if did["family"] in ["f1"]:
if did["name"] in ["02", "05", "07"]:
return True
if did["name"] in ["00", "01", "03"] and did["pin"] in ["r", "v", "z"] and did["size"] in ["c", "d", "e", "f", "g"]:
return True
return False

if did["family"] in ["f3"]:
if did["name"] in ["73", "78"]:
return False
if did["name"] in ["02"] and did["pin"] in ["c"] and did["size"] in ["b", "c"]:
return False
if did["family"] in ["f1", "f3", "l0", "l1", "l4", "g0", "g4"]:
return True

if did["family"] in ["l0", "l4"]:
return True
return False

if did["family"] in ["l1"]:
if did["size"] in ["c"]:
return False
return True

if did["family"] in ["g0", "g4"]:
return True

return False
def get_irq_list(device):
irqs = [v["name"] for v in device.get_driver("core")["vector"]]
irqs = [v for v in irqs if v.startswith("DMA") and v[3].isdigit() and not "DMA2D" in v]

instance_pattern = re.compile("(DMA\d_(Ch|Channel)\d(_\d)*)")
channel_pattern = re.compile("DMA(?P<instance>\d)_(Channel|Ch)(?P<channels>(\d(_\d)*))")
irq_list = []
for irq in irqs:
instances = []
# get channel definitions for each instance, e.g. [DMA1_Ch4_7, DMA2_Ch1_5]
instance_data = [match[0] for match in instance_pattern.findall(irq)]
if len(instance_data) == 0:
raise ValueError("Failed to parse irq '{}'".format(irq))
for channel_list in instance_data:
match = channel_pattern.match(channel_list)
if match is None:
raise ValueError("Failed to parse irq channels: '{}'".format(channel_list))
instance = int(match.group("instance"))
channels = [int(ch) for ch in match.group('channels').split('_')]
if len(channels) == 2:
channels = list(range(channels[0], channels[1] + 1))
instances.append({"instance" : instance, "channels" : channels})
irq_list.append({'name' : irq, 'instances' : instances})
return irq_list


def build(env):
Expand Down Expand Up @@ -124,9 +129,14 @@ def build(env):
controller.append({"instance": int(instance), "min_channel": int(min_channel), "max_channel": int(max_channel)})

did = device.identifier
if (did.family in ['f0'] and did.name == '30' and did.size == 'c') or (did.family in ['f1'] and did.name == '02'):
# FIXME: Bug in modm-deviced data: Dma2 does not exist on device.identifier
if (did.family in ['f0'] and did.name == '30' and did.size == 'c') or \
(did.family in ['f1'] and did.name not in ['05', '07'] and did.size in ['4', '6', '8', 'b']):
# FIXME: Bug in modm-devices data: Dma2 does not exist on device.identifier
properties["dma"]["instance"].remove('2')
controller = list(filter(lambda c: c["instance"] != 2, controller))
for channels in dma["channels"]:
if channels["instance"] == '2':
dma["channels"].remove(channels)

signal_names = sorted(list(set(signal_names)))
properties["dmaType"] = dma["type"]
Expand All @@ -138,29 +148,26 @@ def build(env):
"max" : max(controller, key=lambda c: c["max_channel"])["max_channel"]
}

def irq_list_for_dma_instance(instance):
irqs = [v["name"] for v in device.get_driver("core")["vector"]]
irqs = [v for v in irqs if v.startswith("DMA" + instance) and not "DMA2D" in v]
irq_list = list()
for irq in irqs:
irq_channel_list = []
for c in irq.split("Channel",1)[1]:
if c.isdigit():
irq_channel_list.append(int(c))
irq_list.append(irq_channel_list)
# remove channels not available from irqs
def filter_irqs(irq_list):
max_channel_map = {}
for c in controller:
max_channel_map[c['instance']] = c['max_channel']
for irq in irq_list:
for instance in irq["instances"]:
def predicate(ch):
return ch <= max_channel_map[instance["instance"]]
instance["channels"] = list(filter(predicate, instance["channels"]))
return irq_list

properties["irqList"] = dict()
if dma["type"] in ["stm32-channel-request", "stm32-channel"]:
for channels in dma["channels"]:
irq_list = irq_list_for_dma_instance(channels["instance"])
properties["irqList"][int(channels["instance"])] = irq_list
else: # type is stm32-mux
channels = dma["mux-channels"][0]["mux-channel"]
instances = list(dict.fromkeys(([channel["dma-instance"] for channel in channels])))
for instance in instances:
irq_list = irq_list_for_dma_instance(instance)
properties["irqList"][int(instance)] = irq_list
properties["irqList"] = filter_irqs(get_irq_list(device))

irq_map = defaultdict(dict)
for irq in properties["irqList"]:
for instance in irq["instances"]:
for channel in instance["channels"]:
irq_map[instance["instance"]][channel] = irq["name"]
properties["irqMap"] = irq_map

env.substitutions = properties
env.outbasepath = "modm/src/modm/platform/dma"
Expand Down

0 comments on commit f3dd039

Please sign in to comment.