diff --git a/README.md b/README.md
index eed411dfd4..9f63a5fcbc 100644
--- a/README.md
+++ b/README.md
@@ -82,9 +82,9 @@ git clone --recurse-submodules --jobs 8 https://github.com/modm-io/modm.git
## Microcontrollers
-modm can create a HAL for 3628 devices of these vendors:
+modm can create a HAL for 3715 devices of these vendors:
-- STMicroelectronics STM32: 2823 devices.
+- STMicroelectronics STM32: 2910 devices.
- Microchip SAM: 416 devices.
- Microchip AVR: 388 devices.
- Raspberry Pi: 1 device.
@@ -164,7 +164,7 @@ Please [discover modm's peripheral drivers for your specific device][discover].
✅ |
✅ |
✅ |
-✕ |
+○ |
✅ |
○ |
✕ |
diff --git a/ext/modm-devices b/ext/modm-devices
index 2f3262b77d..e540dc9d44 160000
--- a/ext/modm-devices
+++ b/ext/modm-devices
@@ -1 +1 @@
-Subproject commit 2f3262b77d21acd2c89cc70bbd3d87e03fb361d1
+Subproject commit e540dc9d4430749fe0cbc20b536d71136b6f25e4
diff --git a/src/modm/platform/can/stm32-fdcan/module.lb b/src/modm/platform/can/stm32-fdcan/module.lb
index b82a363aeb..6bcc460042 100644
--- a/src/modm/platform/can/stm32-fdcan/module.lb
+++ b/src/modm/platform/can/stm32-fdcan/module.lb
@@ -64,6 +64,11 @@ 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",
diff --git a/src/modm/platform/core/stm32/startup_platform.c.in b/src/modm/platform/core/stm32/startup_platform.c.in
index d6238bd927..5764524b36 100644
--- a/src/modm/platform/core/stm32/startup_platform.c.in
+++ b/src/modm/platform/core/stm32/startup_platform.c.in
@@ -63,7 +63,7 @@ __modm_initialize_platform(void)
%% elif target.family in ["g0", "g4", "l4", "l5"]
%% if target.family in ["l4", "g4"]
RCC->APB1ENR1 |= RCC_APB1ENR1_PWREN;
-%% else
+%% elif target.family != "g0"
#ifdef PWR_CR2_IOSV
RCC->APB1ENR1 |= RCC_APB1ENR1_PWREN;
#endif
diff --git a/src/modm/platform/dma/stm32/module.lb b/src/modm/platform/dma/stm32/module.lb
index 4caaf4e270..0c13840264 100644
--- a/src/modm/platform/dma/stm32/module.lb
+++ b/src/modm/platform/dma/stm32/module.lb
@@ -5,7 +5,7 @@
# Copyright (c) 2017, Fabian Greif
# Copyright (c) 2020, Mike Wolfram
# Copyright (c) 2021, Raphael Lehmann
-# Copyright (c) 2021, Christopher Durand
+# Copyright (c) 2021-2023, Christopher Durand
#
# This file is part of the modm project.
#
@@ -129,11 +129,11 @@ def build(env):
for channel in channels:
instance_channels[channel["dma-instance"]].append(channel["dma-channel"])
for instance in instance_channels:
- channel_list = instance_channels[instance]
+ channel_list = [int(c) for c in instance_channels[instance]]
channel_list.sort()
min_channel = channel_list[0]
max_channel = channel_list[-1]
- controller.append({"instance": int(instance), "min_channel": int(min_channel), "max_channel": int(max_channel)})
+ controller.append({"instance": int(instance), "min_channel": min_channel, "max_channel": max_channel})
elif dma["type"] in ["stm32-stream-channel"]:
for channels in dma["streams"]:
max_channels = 0
diff --git a/src/modm/platform/i2c/stm32-extended/i2c_master.cpp.in b/src/modm/platform/i2c/stm32-extended/i2c_master.cpp.in
index c620cca8db..c8c1e50bb0 100644
--- a/src/modm/platform/i2c/stm32-extended/i2c_master.cpp.in
+++ b/src/modm/platform/i2c/stm32-extended/i2c_master.cpp.in
@@ -2,6 +2,7 @@
/*
* Copyright (c) 2017, Niklas Hauser
* Copyright (c) 2017, Sascha Schade
+ * Copyright (c) 2018, 2023, Christopher Durand
*
* This file is part of the modm project.
*
@@ -53,7 +54,7 @@
#include
#include
-%% if not shared_interrupt
+%% if not single_interrupt
MODM_ISR_DECL(I2C{{ id }}_ER);
%% endif
@@ -323,7 +324,10 @@ namespace
}
// ----------------------------------------------------------------------------
-%% if shared_interrupt
+%% if shared_irq
+void
+modm::platform::I2cMaster{{ id }}::irq()
+%% elif single_interrupt
MODM_ISR(I2C{{ id }})
%% else
MODM_ISR(I2C{{ id }}_EV)
@@ -331,12 +335,24 @@ MODM_ISR(I2C{{ id }}_EV)
{
DEBUG_STREAM("\n=== IRQ ===");
-%% if shared_interrupt
+%% if single_interrupt
handleError();
%% endif
- uint16_t isr = I2C{{ id }}->ISR;
+ const uint16_t isr = I2C{{ id }}->ISR;
+%% if shared_irq
+ const auto cr1 = I2C{{ id }}->CR1;
+ const auto mask = (cr1 & (I2C_CR1_STOPIE | I2C_CR1_RXIE | I2C_CR1_TXIE))
+ | ((cr1 & I2C_CR1_TCIE) ? (I2C_ISR_TCR | I2C_ISR_TC) : 0u);
+
+ static_assert(I2C_CR1_STOPIE == I2C_ISR_STOPF);
+ static_assert(I2C_CR1_TXIE == I2C_ISR_TXIS);
+ static_assert(I2C_CR1_RXIE == I2C_ISR_RXNE);
+ if ((isr & mask) == 0) {
+ return;
+ }
+%% endif
I2C{{ id }}->CR1 &= ~(I2C_CR1_STOPIE | I2C_CR1_TCIE | I2C_CR1_RXIE | I2C_CR1_TXIE);
I2C{{ id }}->ICR = I2C_ICR_STOPCF;
@@ -487,7 +503,7 @@ MODM_ISR(I2C{{ id }}_EV)
}
// ----------------------------------------------------------------------------
-%% if not shared_interrupt
+%% if not single_interrupt
MODM_ISR(I2C{{ id }}_ER)
{
handleError();
@@ -539,7 +555,11 @@ modm::platform::I2cMaster{{ id }}::initializeWithPrescaler(uint32_t timingRegist
// Disable Own Address 2
I2C{{ id }}->OAR2 = 0;
-%% if shared_interrupt
+%% if shared_irq
+ // Enable Interrupt
+ NVIC_SetPriority({{ shared_irq }}_IRQn, 10);
+ NVIC_EnableIRQ({{ shared_irq }}_IRQn);
+%% elif single_interrupt
// Enable Interrupt
NVIC_SetPriority(I2C{{ id }}_IRQn, 10);
NVIC_EnableIRQ(I2C{{ id }}_IRQn);
diff --git a/src/modm/platform/i2c/stm32-extended/i2c_master.hpp.in b/src/modm/platform/i2c/stm32-extended/i2c_master.hpp.in
index d6e61f36b0..1b4b439747 100644
--- a/src/modm/platform/i2c/stm32-extended/i2c_master.hpp.in
+++ b/src/modm/platform/i2c/stm32-extended/i2c_master.hpp.in
@@ -2,6 +2,7 @@
/*
* Copyright (c) 2017, Sascha Schade
* Copyright (c) 2017-2018, Niklas Hauser
+ * Copyright (c) 2018, 2023, Christopher Durand
*
* This file is part of the modm project.
*
@@ -14,6 +15,7 @@
#ifndef MODM_STM32_I2C_{{ id }}_HPP
#define MODM_STM32_I2C_{{ id }}_HPP
+#include
#include
#include
#include
@@ -117,6 +119,13 @@ public:
private:
static void
initializeWithPrescaler(uint32_t timingRegisterValue);
+
+%% if shared_irq
+ friend void ::{{ shared_irq }}_IRQHandler();
+
+ static void
+ irq();
+%% endif
};
diff --git a/src/modm/platform/i2c/stm32-extended/i2c_shared_irqs.cpp.in b/src/modm/platform/i2c/stm32-extended/i2c_shared_irqs.cpp.in
new file mode 100644
index 0000000000..c731ee219d
--- /dev/null
+++ b/src/modm/platform/i2c/stm32-extended/i2c_shared_irqs.cpp.in
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2023, Christopher Durand
+ *
+ * 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/.
+ */
+// ----------------------------------------------------------------------------
+
+%% for ids in shared_irqs.values()
+%% for id in ids | sort
+#include "i2c_master_{{ id }}.hpp"
+%% endfor
+%% endfor
+
+%% for irq,ids in shared_irqs.items()
+MODM_ISR({{ irq }})
+{
+%% for id in ids | sort
+ modm::platform::I2cMaster{{ id }}::irq();
+%% endfor
+}
+%% endfor
diff --git a/src/modm/platform/i2c/stm32-extended/module.lb b/src/modm/platform/i2c/stm32-extended/module.lb
index 6e6b643673..970bc19be7 100644
--- a/src/modm/platform/i2c/stm32-extended/module.lb
+++ b/src/modm/platform/i2c/stm32-extended/module.lb
@@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2016-2018, Niklas Hauser
# Copyright (c) 2017, Fabian Greif
+# Copyright (c) 2023, Christopher Durand
#
# This file is part of the modm project.
#
@@ -10,6 +11,23 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# -----------------------------------------------------------------------------
+from collections import defaultdict
+import re
+
+global_properties = {}
+
+def get_shared_irqs(device):
+ irq_re = re.compile("I2C\d(_\d)+")
+ shared_irqs = [v["name"] for v in device.get_driver("core")["vector"]]
+ shared_irqs = [v for v in shared_irqs if irq_re.fullmatch(v)]
+ shared_irq_map = {}
+ for irq in shared_irqs:
+ instances = tuple(irq[3:].split("_"))
+ for i in instances:
+ shared_irq_map[int(i)] = irq
+ return shared_irq_map
+
+
class Instance(Module):
def __init__(self, instance):
self.instance = instance
@@ -31,13 +49,21 @@ class Instance(Module):
return True
def build(self, env):
+ global global_properties
+
device = env[":target"]
driver = device.get_driver("i2c")
properties = device.properties
properties["target"] = target = device.identifier
properties["id"] = self.instance
- properties["shared_interrupt"] = "0" in target.family
+ properties["single_interrupt"] = "0" in target.family
+ shared_irq = get_shared_irqs(device).get(self.instance)
+ properties["shared_irq"] = shared_irq
+ if shared_irq:
+ global_properties["shared_irqs"][shared_irq].append(self.instance)
+ # shared irq is only supported with a single data and error interrupt
+ assert properties["single_interrupt"] or not shared_irq
env.substitutions = properties
env.outbasepath = "modm/src/modm/platform/i2c"
@@ -64,12 +90,17 @@ def prepare(module, options):
":container",
":platform:gpio")
+ global_properties["shared_irqs"] = defaultdict(list)
+
for instance in listify(device.get_driver("i2c")["instance"]):
module.add_submodule(Instance(int(instance)))
return True
def build(env):
+ env.substitutions.update(global_properties)
env.outbasepath = "modm/src/modm/platform/i2c"
- env.copy("i2c_timing_calculator.hpp")
+ env.copy("i2c_timing_calculator.hpp")
+ if len(global_properties["shared_irqs"]) > 0:
+ env.template("i2c_shared_irqs.cpp.in")
diff --git a/src/modm/platform/spi/stm32/module.lb b/src/modm/platform/spi/stm32/module.lb
index 583335987d..2329a5bc84 100644
--- a/src/modm/platform/spi/stm32/module.lb
+++ b/src/modm/platform/spi/stm32/module.lb
@@ -3,6 +3,7 @@
#
# Copyright (c) 2016-2018, Niklas Hauser
# Copyright (c) 2017, Fabian Greif
+# Copyright (c) 2023, Christopher Durand
#
# This file is part of the modm project.
#
@@ -37,6 +38,13 @@ class Instance(Module):
properties = get_properties(env)
properties["id"] = self.instance
+ device = env[":target"]
+
+ irqs = [v["name"] for v in device.get_driver("core")["vector"]]
+ irqs = [irq for irq in irqs if irq.startswith("SPI") and str(self.instance) in irq]
+ assert len(irqs) == 1
+ properties["irq"] = irqs[0]
+
env.substitutions = properties
env.outbasepath = "modm/src/modm/platform/spi"
diff --git a/src/modm/platform/spi/stm32/spi_hal_impl.hpp.in b/src/modm/platform/spi/stm32/spi_hal_impl.hpp.in
index dbadb970cb..075c18d6fb 100644
--- a/src/modm/platform/spi/stm32/spi_hal_impl.hpp.in
+++ b/src/modm/platform/spi/stm32/spi_hal_impl.hpp.in
@@ -153,12 +153,12 @@ modm::platform::SpiHal{{ id }}::enableInterruptVector(bool enable, uint32_t prio
{
if (enable) {
// Set priority for the interrupt vector
- NVIC_SetPriority(SPI{{ id }}_IRQn, priority);
+ NVIC_SetPriority({{ irq }}_IRQn, priority);
// register IRQ at the NVIC
- NVIC_EnableIRQ(SPI{{ id }}_IRQn);
+ NVIC_EnableIRQ({{ irq }}_IRQn);
}
else {
- NVIC_DisableIRQ(SPI{{ id }}_IRQn);
+ NVIC_DisableIRQ({{ irq }}_IRQn);
}
}
diff --git a/test/all/ignored.txt b/test/all/ignored.txt
index d6ed40b370..f5ee44df96 100644
--- a/test/all/ignored.txt
+++ b/test/all/ignored.txt
@@ -106,10 +106,6 @@ samd21e15c-uf
samd21e15c-uu
samd21e16c-uf
samd21e16c-uu
-# FIXME: Shared IRQs on UART, SPI, I2C
-stm32g0b0
-stm32g0b1
-stm32g0c1
# FIXME: Dual-core devices not supported yet
stm32h745
stm32h755