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

DMA for more STM32 controllers #608

Merged
merged 5 commits into from
Apr 14, 2021
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
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,16 +185,16 @@ Please [discover modm's peripheral drivers for your specific device][discover].
<td align="center">✗</td>
</tr><tr>
<td align="left">DMA</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>
<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>
<td align="center">✅</td>
<td align="center">○</td>
<td align="center">✗</td>
Expand Down
43 changes: 43 additions & 0 deletions examples/nucleo_f042k6/spi_dma/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2020, Mike Wolfram
* Copyright (c) 2021, Raphael Lehmann
*
* 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 <modm/board.hpp>

using Mosi = GpioOutputB5;
using Miso = GpioInputB4;
using Sck = GpioOutputB3;
using DmaRx = Dma1::Channel2;
using DmaTx = Dma1::Channel3;
using Spi = SpiMaster1_Dma<DmaRx, DmaTx>;

int main()
{
Board::initialize();

Dma1::enable();
Spi::connect<Mosi::Mosi, Miso::Miso, Sck::Sck>();
Spi::initialize<Board::SystemClock, 12_MHz>();

while (true)
{
uint8_t sendBuffer[13] { "data to send" };
uint8_t receiveBuffer[13];

// send out 12 bytes, don't care about response
Spi::transferBlocking(sendBuffer, nullptr, 12);

// send out 12 bytes, read in 12 bytes
Spi::transferBlocking(sendBuffer, receiveBuffer, 12);
}

return 0;
}
12 changes: 12 additions & 0 deletions examples/nucleo_f042k6/spi_dma/project.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<library>
<extends>modm:nucleo-f042k6</extends>
<options>
<option name="modm:build:build.path">../../../build/nucleo_f042k6/spi_dma</option>
</options>
<modules>
<module>modm:platform:gpio</module>
<module>modm:platform:dma</module>
<module>modm:platform:spi:1</module>
<module>modm:build:scons</module>
</modules>
</library>
43 changes: 43 additions & 0 deletions examples/nucleo_f303re/spi_dma/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2020, Mike Wolfram
* Copyright (c) 2021, Raphael Lehmann
*
* 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 <modm/board.hpp>

using Mosi = GpioOutputB5;
using Miso = GpioInputB4;
using Sck = GpioOutputB3;
using DmaRx = Dma1::Channel2;
using DmaTx = Dma1::Channel3;
using Spi = SpiMaster1_Dma<DmaRx, DmaTx>;

int main()
{
Board::initialize();

Dma1::enable();
Spi::connect<Mosi::Mosi, Miso::Miso, Sck::Sck>();
Spi::initialize<Board::SystemClock, 8_MHz>();

while (true)
{
uint8_t sendBuffer[13] { "data to send" };
uint8_t receiveBuffer[13];

// send out 12 bytes, don't care about response
Spi::transferBlocking(sendBuffer, nullptr, 12);

// send out 12 bytes, read in 12 bytes
Spi::transferBlocking(sendBuffer, receiveBuffer, 12);
}

return 0;
}
12 changes: 12 additions & 0 deletions examples/nucleo_f303re/spi_dma/project.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<library>
<extends>modm:nucleo-f303re</extends>
<options>
<option name="modm:build:build.path">../../../build/nucleo_f303re/spi_dma</option>
</options>
<modules>
<module>modm:platform:gpio</module>
<module>modm:platform:dma</module>
<module>modm:platform:spi:1</module>
<module>modm:build:scons</module>
</modules>
</library>
15 changes: 9 additions & 6 deletions src/modm/platform/dma/stm32/dma.cpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,19 @@

#include "dma.hpp"

%% for channels in dma["channels"]
using namespace modm::platform;

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

MODM_ISR(DMA{{ channels.instance }}_Channel{{ channel.position }})
MODM_ISR(DMA{{ instance }}_Channel{{ channels | join("_") }})
{
using namespace modm::platform;
Dma{{ channels.instance }}::Channel<DmaBase::Channel::Channel{{ channel.position }}>::interruptHandler();
%% for channel in channels
Dma{{ instance }}::Channel<DmaBase::Channel::Channel{{ channel }}>::interruptHandler();
%% endfor
}

%% endfor
Expand Down
40 changes: 39 additions & 1 deletion src/modm/platform/dma/stm32/dma.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Copyright (c) 2014, Kevin Läufer
* Copyright (c) 2014-2017, Niklas Hauser
* Copyright (c) 2020, Mike Wolfram
* Copyright (c) 2021, Raphael Lehmann
*
* This file is part of the modm project.
*
Expand Down Expand Up @@ -46,8 +47,10 @@ public:
{
if constexpr (ID == 1)
Rcc::enable<Peripheral::Dma1>();
%% if (dma.instance | length) > 1
else
Rcc::enable<Peripheral::Dma2>();
%% endif
}
/**
* Disable the DMA controller in the RCC
Expand All @@ -57,8 +60,10 @@ public:
{
if constexpr (ID == 1)
Rcc::disable<Peripheral::Dma1>();
%% if (dma.instance | length) > 1
else
Rcc::disable<Peripheral::Dma2>();
%% endif
}

/**
Expand Down Expand Up @@ -225,16 +230,22 @@ public:
{
transferComplete = irqHandler;
}

/**
* Set the peripheral that operates the channel
*/
template <DmaBase::Request dmaRequest>
static void
setPeripheralRequest()
{
%% if dmaType in ["stm32-channel-request"]
DMA_Request_TypeDef *DMA_REQ = reinterpret_cast<DMA_Request_TypeDef *>(ControlHal::DMA_CSEL);
DMA_REQ->CSELR &= ~(0x0f << (uint32_t(ChannelID) * 4));
DMA_REQ->CSELR |= uint32_t(dmaRequest) << (uint32_t(ChannelID) * 4);
%% else
// Nothing to see here. This controller has no request mux, instead
// all requests are or-ed together.
%% endif
}

/**
Expand Down Expand Up @@ -349,6 +360,7 @@ public:
* ...
* };
*/
%% if dmaType in ["stm32-channel-request"]
%% for channels in dma["channels"]
%% for channel in channels.channel
%% for request in channel.request
Expand All @@ -357,7 +369,7 @@ public:
%% if signal.instance is defined
%% set peripheral = peripheral ~ signal.instance
%% else
%% if peripheral not in ["Quadspi", "Aes", "Dcmi"]
%% if peripheral in ["Dac", "Lpuart", "Swpmi"] and target["family"] not in ["f1", "f3", "l0", "l1"]
%% set peripheral = peripheral ~ 1
%% endif
%% endif
Expand All @@ -375,6 +387,32 @@ struct DmaController<{{ channels.instance }}>::Channel<DmaBase::Channel::Channel
%% endfor
%% endfor

%%else
%% for channels in dma["channels"]
%% for channel in channels.channel
%% for signal in channel.signal
%% set peripheral = signal.driver.capitalize()
%% 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"]
%% set peripheral = peripheral ~ 1
%% endif
rleh marked this conversation as resolved.
Show resolved Hide resolved
%% endif
template <>
template <>
template <>
struct DmaController<{{ channels.instance }}>::Channel<DmaBase::Channel::Channel{{ channel.position }}>::RequestMapping<Peripheral::{{ peripheral }}{% if signal.name is defined %}, DmaBase::Signal::{{ signal.name.capitalize() }}{% endif %}>
{
using Channel = DmaController<{{ channels.instance }}>::Channel<DmaBase::Channel::Channel{{ channel.position }}>;
static constexpr DmaBase::Request Request = DmaBase::Request::Any;
};

%% endfor
%% endfor
%% endfor

%%endif
} // namespace platform

} // namespace modm
Expand Down
31 changes: 22 additions & 9 deletions src/modm/platform/dma/stm32/dma_base.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Copyright (c) 2014, Kevin Läufer
* Copyright (c) 2014-2017, Niklas Hauser
* Copyright (c) 2020, Mike Wolfram
* Copyright (c) 2021, Raphael Lehmann
*
* This file is part of the modm project.
*
Expand All @@ -15,6 +16,8 @@
#define MODM_STM32_DMA_BASE_HPP

#include <stdint.h>
#include <cstddef>

#include "../device.hpp"

#include <modm/architecture/interface/assert.hpp>
Expand All @@ -23,7 +26,7 @@

%% if target["family"] == "f4"
%% set reg_prefix = "DMA_SxCR"
%% elif target["family"] in ["f3", "l4"]
%% elif dmaType in ["stm32-channel-request", "stm32-channel"]
%% set reg_prefix = "DMA_CCR"
%% endif

Expand Down Expand Up @@ -81,7 +84,7 @@ public:
Dma = 0,
Peripheral = DMA_SxCR_PFCTRL, ///< the peripheral is the flow controller
};
%% elif target["family"] in ["f3", "l4"]
%% elif dmaType in ["stm32-channel-request", "stm32-channel"]
%% set channel_count = namespace(max_channels = 0)
%% for controller in dmaController
%% if channel_count.max_channels < controller.channels
Expand All @@ -96,7 +99,7 @@ public:
%% endfor
};

%% if target["family"] == "l4"
%% if dmaType in ["stm32-channel-request"]
%% set request_count = namespace(max_requests = 0)
%% for channels in dma["channels"]
%% for channel in channels.channel
Expand All @@ -114,6 +117,14 @@ public:
Request{{ request }}{% if request == 0 %} = 0{% endif %},
%% endfor
};
%% else
enum class
Request
{
// Nothing to see here. This controller has no request mux, instead
// all requests are OR-ed together.
Any
};
%% endif
%% endif

Expand Down Expand Up @@ -181,7 +192,7 @@ public:
MemoryToPeripheral = DMA_SxCR_DIR_0,
/// Source: DMA_SxPAR; Sink: DMA_SxM0AR
MemoryToMemory = DMA_SxCR_DIR_1,
%% elif target["family"] in ["f3", "l4"]
%% elif dmaType in ["stm32-channel-request", "stm32-channel"]
/// Source: DMA_CPARx; Sink: DMA_CMARx
PeripheralToMemory = 0,
/// Source: DMA_CMARx; Sink: DMA_CPARx
Expand Down Expand Up @@ -219,7 +230,7 @@ protected:
DMA_SxCR_PL_1 | DMA_SxCR_PL_0 | // Priority
DMA_SxCR_CIRC | // CircularMode
DMA_SxCR_PFCTRL; // FlowControl
%% elif target["family"] in ["f3", "l4"]
%% elif dmaType in ["stm32-channel-request", "stm32-channel"]
static constexpr uint32_t memoryMask =
DMA_CCR_MSIZE_0 | DMA_CCR_MSIZE_1 | // MemoryDataSize
DMA_CCR_MINC | // MemoryIncrementMode
Expand Down Expand Up @@ -248,13 +259,15 @@ protected:
struct Nvic;
};

%% for channels in dma["channels"]
%% for instance, irqs in irqList.items()
template <>
struct DmaBase::Nvic<{{ channels.instance }}>
struct DmaBase::Nvic<{{ instance }}>
{
static constexpr IRQn_Type DmaIrqs[] {
%% for channel in channels.channel
DMA{{ channels.instance }}_Channel{{ channel.position }}_IRQn,
%% for channels in irqs
%% for i in range(channels | length)
DMA{{ instance }}_Channel{{ channels | join("_") }}_IRQn,
%% endfor
%% endfor
};
};
Expand Down
Loading