Skip to content

Commit

Permalink
[dma] Adapt STM32 implementation for F4 and F7 series
Browse files Browse the repository at this point in the history
  • Loading branch information
rleh committed Oct 28, 2021
1 parent 47a97dc commit 32f426a
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 87 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,8 @@ 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>
<td align="center">✅</td>
<td align="center">○</td>
Expand Down
3 changes: 2 additions & 1 deletion examples/nucleo_g474re/dac_dma/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ void setupDac4()
});

Dma1::Channel1::enableInterruptVector();
Dma1::Channel1::enableInterrupt(Dma1::Interrupt::TransferComplete | Dma1::Interrupt::Error);
Dma1::Channel1::enableInterrupt(Dma1::InterruptEnable::TransferComplete |
Dma1::InterruptEnable::TransferError);

// DAC4 channel 1 output via opamp 4 in follower mode connected to output B12
GpioOutputB12::setAnalogInput();
Expand Down
63 changes: 55 additions & 8 deletions src/modm/platform/dma/stm32/dma.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,10 @@ public:
static void
start()
{
ControlHal::clearInterruptFlags(uint32_t(Interrupt::Global) << (uint32_t(ChannelID) * 4));
ControlHal::clearInterruptFlags(InterruptFlags::All, ChannelID);
ChannelHal::start();
}

/**
* Stop a DMA channel transfer
*/
Expand Down Expand Up @@ -271,6 +272,9 @@ public:

auto* channel = DMAMUX1_Channel0 + muxChannel;
channel->CCR = (channel->CCR & DMAMUX_CxCR_DMAREQ_ID) | uint32_t(dmaRequest);
%% elif dmaType in ["stm32-stream-channel"]
DMA_Channel_TypeDef *Channel = reinterpret_cast<DMA_Channel_TypeDef*>(CHANNEL_BASE);
Channel->CR = (Channel->CR & ~DMA_SxCR_CHSEL_Msk) | uint32_t(dmaRequest);
%% else
// Nothing to see here. This controller has no request mux, instead
// all requests are or-ed together.
Expand All @@ -286,12 +290,22 @@ public:
static void
interruptHandler()
{
%% if dmaType in ["stm32-channel-request", "stm32-channel", "stm32-mux"]
static const uint32_t TC_Flag {
uint32_t(Interrupt::TransferComplete) << (uint32_t(ChannelID) * 4)
uint32_t(InterruptFlags::TransferComplete) << (uint32_t(ChannelID) * 4)
};
static const uint32_t TE_Flag {
uint32_t(Interrupt::Error) << (uint32_t(ChannelID) * 4)
uint32_t(InterruptFlags::Error) << (uint32_t(ChannelID) * 4)
};
%% elif dmaType in ["stm32-stream-channel"]
constexpr uint8_t offsetLut[8] = {0, 6, 16, 22, 0+32, 6+32, 16+32, 22+32};
static const uint64_t TC_Flag {
uint64_t(InterruptFlags::TransferComplete) << offsetLut[uint32_t(ChannelID)]
};
static const uint64_t TE_Flag {
uint64_t(InterruptFlags::Error) << offsetLut[uint32_t(ChannelID)]
};
%% endif

auto isr { ControlHal::getInterruptFlags() };
if (isr & TE_Flag) {
Expand All @@ -302,7 +316,7 @@ public:
if ((isr & TC_Flag) and transferComplete)
transferComplete();

ControlHal::clearInterruptFlags(uint32_t(Interrupt::Global) << (uint32_t(ChannelID) * 4));
ControlHal::clearInterruptFlags(InterruptFlags::Global, ChannelID);
}

/**
Expand All @@ -329,15 +343,15 @@ public:
* Enable the specified interrupt of the channel
*/
static void
enableInterrupt(Interrupt_t irq)
enableInterrupt(InterruptEnable_t irq)
{
ChannelHal::enableInterrupt(irq);
}
/**
* Disable the specified interrupt of the channel
*/
static void
disableInterrupt(Interrupt_t irq)
disableInterrupt(InterruptEnable_t irq)
{
ChannelHal::disableInterrupt(irq);
}
Expand Down Expand Up @@ -391,7 +405,7 @@ public:
};

%% endfor
%% else
%% elif dmaType in ["stm32-channel-request", "stm32-channel"]
%% for channels in dma["channels"]
class Dma{{ channels.instance }}: public DmaController<{{ channels.instance }}>
{
Expand All @@ -401,6 +415,16 @@ public:
%% endfor
};
%% endfor
%% elif dmaType in ["stm32-stream-channel"]
%% for streams in dma["streams"]
class Dma{{ streams.instance }}: public DmaController<{{ streams.instance }}>
{
public:
%% for stream in streams.stream
using Channel{{ stream.position }} = DmaController<{{ streams.instance }}>::Channel<DmaBase::Channel::Channel{{ stream.position }}>;
%% endfor
};
%% endfor
%% endif

/*
Expand Down Expand Up @@ -477,7 +501,7 @@ namespace dma
%% endfor

}
%% else
%% elif dmaType in ["stm32-channel"]
%% for channels in dma["channels"]
%% for channel in channels.channel
%% for signal in channel.signal
Expand All @@ -502,6 +526,29 @@ struct DmaController<{{ channels.instance }}>::Channel<DmaBase::Channel::Channel
%% endfor
%% endfor

%% elif dmaType in ["stm32-stream-channel"]
%% for channels in dma["streams"]
%% for channel in channels.stream
%% for request in channel.channel
%% for signal in request.signal
%% set peripheral = signal.driver.capitalize()
%% if signal.instance is defined and peripheral not in ["Dac"]
%% set peripheral = peripheral ~ signal.instance
%% 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::Channel{{ request.position }};
};

%% endfor
%% endfor
%% endfor
%% endfor

%%endif
} // namespace platform

Expand Down
133 changes: 82 additions & 51 deletions src/modm/platform/dma/stm32/dma_base.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#include <modm/architecture/interface/interrupt.hpp>
#include <modm/architecture/interface/register.hpp>

%% if target["family"] == "f4"
%% if dmaType in ["stm32-stream-channel"]
%% set reg_prefix = "DMA_SxCR"
%% elif dmaType in ["stm32-channel-request", "stm32-channel", "stm32-mux"]
%% set reg_prefix = "DMA_CCR"
Expand All @@ -47,44 +47,47 @@ class DmaBase
{
public:
// Enums
%% if target["family"] == "f4"
%% if dmaType in ["stm32-stream-channel"]
enum class
Channel : uint32_t
Channel
{
Channel0 = 0,
Channel1 = DMA_SxCR_CHSEL_0,
Channel2 = DMA_SxCR_CHSEL_1,
Channel3 = DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_0,
Channel4 = DMA_SxCR_CHSEL_2,
Channel5 = DMA_SxCR_CHSEL_2 | DMA_SxCR_CHSEL_0,
Channel6 = DMA_SxCR_CHSEL_2 | DMA_SxCR_CHSEL_1,
Channel7 = DMA_SxCR_CHSEL_2 | DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_0,
Stream0 = 0,
Stream1,
Stream2,
Stream3,
Stream4,
Stream5,
Stream6,
Stream7,
Channel0 = Stream0,
Channel1 = Stream1,
Channel2 = Stream2,
Channel3 = Stream3,
Channel4 = Stream4,
Channel5 = Stream5,
Channel6 = Stream6,
Channel7 = Stream7,
};

enum class
MemoryBurstTransfer : uint32_t
{
Single = 0,
Increment4 = DMA_SxCR_MBURST_0,
Increment8 = DMA_SxCR_MBURST_1,
Increment16 = DMA_SxCR_MBURST_1 | DMA_SxCR_MBURST_0,
};
%% set request_count = namespace(max_requests = 0)
%% for streams in dma["channels"]
%% for stream in streams.stream
%% for channel in stream.channel
%% if request_count.max_requests < channel.position | int
%% set request_count.max_requests = channel.position | int
%% endif
%% endfor
%% endfor
%% endfor

enum class
PeripheralBurstTransfer : uint32_t
Request : uint32_t
{
Single = 0,
Increment4 = DMA_SxCR_PBURST_0,
Increment8 = DMA_SxCR_PBURST_1,
Increment16 = DMA_SxCR_PBURST_1 | DMA_SxCR_PBURST_0,
%% for i in range(0, request_count.max_requests + 1)
Channel{{ i }} = ({{ i }} << DMA_SxCR_CHSEL_Pos),
%% endfor
};

enum class
FlowControl : uint32_t
{
Dma = 0,
Peripheral = DMA_SxCR_PFCTRL, ///< the peripheral is the flow controller
};
%% elif dmaType in ["stm32-channel-request", "stm32-channel", "stm32-mux"]
enum class
Channel
Expand Down Expand Up @@ -189,7 +192,7 @@ public:
enum class
DataTransferDirection : uint32_t
{
%% if target["family"] == "f4"
%% if dmaType in ["stm32-stream-channel"]
/// Source: DMA_SxPAR; Sink: DMA_SxM0AR
PeripheralToMemory = 0,
/// Source: DMA_SxM0AR; Sink: DMA_SxPAR
Expand Down Expand Up @@ -217,34 +220,62 @@ public:
%% endfor
};

enum class Interrupt {
Global = 0x01,
TransferComplete = 0x02,
HalfTransferComplete = 0x04,
Error = 0x08,
All = 0x0f,
%% if dmaType in ["stm32-stream-channel"]
enum class InterruptEnable {
DirectModeError = DMA_SxCR_DMEIE,
TransferError = DMA_SxCR_TEIE,
HalfTransfer = DMA_SxCR_HTIE,
TransferComplete = DMA_SxCR_TCIE,
};
MODM_FLAGS32(InterruptEnable);

enum class InterruptFlags {
FifoError = 0b00'0001,
DirectModeError = 0b00'0100,
Error = 0b00'1000,
HalfTransferComplete = 0b01'0000,
TransferComplete = 0b10'0000,
All = 0b11'1101,
Global = All,
};
MODM_FLAGS32(Interrupt);
MODM_FLAGS32(InterruptFlags);
%% elif dmaType in ["stm32-channel-request", "stm32-channel", "stm32-mux"]
enum class InterruptEnable {
TransferComplete = DMA_CCR_TCIE,
HalfTransfer = DMA_CCR_HTIE,
TransferError = DMA_CCR_TEIE,
};
MODM_FLAGS32(InterruptEnable);

enum class InterruptFlags {
Global = 0b0001,
TransferComplete = 0b0010,
HalfTransferComplete = 0b0100,
Error = 0b1000,
All = 0b1111,
};
MODM_FLAGS32(InterruptFlags);
%% endif

using IrqHandler = void (*)(void);

protected:
%% if target["family"] == "f4"
%% if dmaType in ["stm32-stream-channel"]
static constexpr uint32_t memoryMask =
DMA_SxCR_MBURST_1 | DMA_SxCR_MBURST_0 | // MemoryBurstTransfer
DMA_SxCR_MSIZE_0 | DMA_SxCR_MSIZE_1 | // MemoryDataSize
DMA_SxCR_MINC | // MemoryIncrementMode
DMA_SxCR_DIR_0 | DMA_SxCR_DIR_1; // DataTransferDirection
DMA_SxCR_MBURST_Msk | // MemoryBurstTransfer
DMA_SxCR_MSIZE_Msk | // MemoryDataSize
DMA_SxCR_MINC | // MemoryIncrementMode
DMA_SxCR_DIR_Msk; // DataTransferDirection
static constexpr uint32_t peripheralMask =
DMA_SxCR_PBURST_1 | DMA_SxCR_PBURST_0 | // PeripheralBurstTransfer
DMA_SxCR_PSIZE_0 | DMA_SxCR_PSIZE_1 | // PeripheralDataSize
DMA_SxCR_PINC | // PeripheralIncrementMode
DMA_SxCR_DIR_0 | DMA_SxCR_DIR_1; // DataTransferDirection
DMA_SxCR_PBURST_Msk | // PeripheralBurstTransfer
DMA_SxCR_PSIZE_Msk | // PeripheralDataSize
DMA_SxCR_PINC_Msk | // PeripheralIncrementMode
DMA_SxCR_DIR_Msk; // DataTransferDirection
static constexpr uint32_t configmask =
DMA_SxCR_CHSEL_2 | DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_0 | // Channel
DMA_SxCR_PL_1 | DMA_SxCR_PL_0 | // Priority
DMA_SxCR_CIRC | // CircularMode
DMA_SxCR_PFCTRL; // FlowControl
DMA_SxCR_CHSEL_Msk | // Channel
DMA_SxCR_PL_Msk | // Priority
DMA_SxCR_CIRC_Msk | // CircularMode
DMA_SxCR_PFCTRL_Msk; // FlowControl
%% elif dmaType in ["stm32-channel-request", "stm32-channel", "stm32-mux"]
static constexpr uint32_t memoryMask =
DMA_CCR_MSIZE_0 | DMA_CCR_MSIZE_1 | // MemoryDataSize
Expand Down
Loading

0 comments on commit 32f426a

Please sign in to comment.