Skip to content

Commit 23852c6

Browse files
committed
[sam] Add SAMx7x DMA driver
1 parent 5e31491 commit 23852c6

File tree

11 files changed

+1220
-1
lines changed

11 files changed

+1220
-1
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ Please [discover modm's peripheral drivers for your specific device][discover].
245245
<td align="center">○</td>
246246
<td align="center">○</td>
247247
<td align="center">○</td>
248-
<td align="center"></td>
248+
<td align="center"></td>
249249
<td align="center">✕</td>
250250
<td align="center">✅</td>
251251
<td align="center">✕</td>
+298
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
/*
2+
* Copyright (c) 2023, Christopher Durand
3+
*
4+
* This file is part of the modm project.
5+
*
6+
* This Source Code Form is subject to the terms of the Mozilla Public
7+
* License, v. 2.0. If a copy of the MPL was not distributed with this
8+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
// ----------------------------------------------------------------------------
11+
12+
#ifndef MODM_SAMX7X_DMA_BASE_HPP
13+
#define MODM_SAMX7X_DMA_BASE_HPP
14+
15+
#include <array>
16+
#include <cstdint>
17+
#include <modm/architecture/interface/register.hpp>
18+
#include <modm/platform/device.hpp>
19+
20+
namespace modm::platform
21+
{
22+
23+
/**
24+
* Data type for peripheral hardware requests
25+
*
26+
* Use modm::platform::DmaRequests::<Peripheral>::<Signal> to obtain values.
27+
*
28+
* @ingroup modm_platform_dma
29+
*/
30+
enum class DmaRequest : uint32_t
31+
{};
32+
33+
/// @ingroup modm_platform_dma
34+
struct DmaBase
35+
{
36+
static constexpr std::size_t ChannelCount{24};
37+
38+
/// XDMAC interrupt flags
39+
enum class Interrupt : uint32_t
40+
{
41+
EndOfBlock = Bit0,
42+
EndOfLinkedList = Bit1,
43+
EndOfDisable = Bit2,
44+
EndOfFlush = Bit3,
45+
ReadBusError = Bit4,
46+
WriteBusError = Bit5,
47+
RequestOverflowError = Bit6
48+
};
49+
50+
MODM_FLAGS32(Interrupt);
51+
52+
enum class TransferType : uint32_t
53+
{
54+
MemoryToMemory = 0,
55+
Peripheral = XDMAC_CC_TYPE
56+
};
57+
58+
enum class PeripheralDirection : uint32_t
59+
{
60+
PeripheralToMemory = 0,
61+
MemoryToPeripheral = XDMAC_CC_DSYNC
62+
};
63+
64+
enum class RequestSource : uint32_t
65+
{
66+
Hardware = 0,
67+
Software = XDMAC_CC_SWREQ
68+
};
69+
70+
/// Transfer data width (8, 16, 32 bit)
71+
enum class DataWidth : uint32_t
72+
{
73+
Byte = 0,
74+
HalfWord = XDMAC_CC_DWIDTH_HALFWORD,
75+
Word = XDMAC_CC_DWIDTH_WORD
76+
};
77+
78+
/**
79+
* Select DMA AHB interface
80+
*
81+
* The right interface has to be selected for the transfer to succeed:
82+
* Flash: Bus 1
83+
* RAM: Bus 0 or 1
84+
* Peripherals: Bus 1
85+
* Core AHBS, TCM: Bus 0
86+
*/
87+
enum class BusInterface : uint32_t
88+
{
89+
Bus0 = 0,
90+
Bus1 = 1
91+
};
92+
93+
enum class AddressingMode : uint32_t
94+
{
95+
// Do not increment address after transfer
96+
Fixed = 0,
97+
// Increment address after transfer by one data width
98+
Incrementing = 1,
99+
// Increment address after transfer by one data width plus data stride
100+
Strided = 3
101+
};
102+
103+
enum class ChannelConfig : uint32_t
104+
{};
105+
MODM_FLAGS32(ChannelConfig);
106+
107+
using TransferType_t = Configuration<ChannelConfig_t, TransferType, XDMAC_CC_TYPE_Msk>;
108+
using PeripheralDirection_t = Configuration<ChannelConfig_t, PeripheralDirection, XDMAC_CC_DSYNC_Msk>;
109+
using RequestSource_t = Configuration<ChannelConfig_t, RequestSource, XDMAC_CC_SWREQ_Msk>;
110+
using DataWidth_t = Configuration<ChannelConfig_t, DataWidth, XDMAC_CC_DWIDTH_Msk>;
111+
using SourceBusInterface_t = Configuration<ChannelConfig_t, BusInterface, 0b1, XDMAC_CC_SIF_Pos>;
112+
using DestinationBusInterface_t = Configuration<ChannelConfig_t, BusInterface, 0b1, XDMAC_CC_DIF_Pos>;
113+
using SourceAddressingMode_t = Configuration<ChannelConfig_t, AddressingMode, 0b11, XDMAC_CC_SAM_Pos>;
114+
using DestinationAddressingMode_t = Configuration<ChannelConfig_t, AddressingMode, 0b11, XDMAC_CC_DAM_Pos>;
115+
using DmaRequest_t = Configuration<ChannelConfig_t, DmaRequest, 0x7f, XDMAC_CC_PERID_Pos>;
116+
117+
/// Type of linked list mode descriptor
118+
enum class ViewType : uint8_t
119+
{
120+
View0 = XDMAC_CNDC_NDVIEW_NDV0,
121+
View1 = XDMAC_CNDC_NDVIEW_NDV1,
122+
View2 = XDMAC_CNDC_NDVIEW_NDV2,
123+
View3 = XDMAC_CNDC_NDVIEW_NDV3
124+
};
125+
126+
/// Base class for linked list transfer descriptors
127+
class ViewBase
128+
{
129+
public:
130+
constexpr ViewBase(uint32_t* data) : data_{data} {}
131+
132+
constexpr void
133+
setDataLength(std::size_t length);
134+
135+
constexpr std::size_t
136+
dataLength() const;
137+
138+
protected:
139+
uint32_t* data_{};
140+
};
141+
142+
/**
143+
* "View0" linked list transfer descriptor with destination address
144+
*
145+
* Set destination address and data length.
146+
* @warning Can only be used with peripheral-to-memory transfers.
147+
*/
148+
class View0Dst : public ViewBase
149+
{
150+
public:
151+
using ViewBase::ViewBase;
152+
153+
using Data = std::array<uint32_t, 3>;
154+
static constexpr auto Type = ViewType::View0;
155+
156+
constexpr void
157+
setDestinationAddress(uintptr_t address);
158+
159+
constexpr void
160+
setDestinationAddress(volatile void* data);
161+
162+
constexpr uintptr_t
163+
destinationAddress() const;
164+
};
165+
166+
/**
167+
* "View0" linked list transfer descriptor with source address
168+
*
169+
* Set source address and data length.
170+
* @warning Can only be used with memory-to-peripheral transfers.
171+
*/
172+
class View0Src : public ViewBase
173+
{
174+
public:
175+
using ViewBase::ViewBase;
176+
177+
using Data = std::array<uint32_t, 3>;
178+
static constexpr auto Type = ViewType::View0;
179+
180+
constexpr void
181+
setSourceAddress(uintptr_t address);
182+
183+
constexpr void
184+
setSourceAddress(const volatile void* data);
185+
186+
constexpr uintptr_t
187+
sourceAddress() const;
188+
};
189+
190+
/**
191+
* "View1" linked list transfer descriptor
192+
*
193+
* Set source address, destination address and data length.
194+
*/
195+
class View1 : public View0Src
196+
{
197+
public:
198+
using View0Src::View0Src;
199+
200+
using Data = std::array<uint32_t, 4>;
201+
static constexpr auto Type = ViewType::View1;
202+
203+
constexpr void
204+
setDestinationAddress(uintptr_t address);
205+
206+
constexpr void
207+
setDestinationAddress(volatile void* data);
208+
209+
constexpr uintptr_t
210+
destinationAddress() const;
211+
};
212+
213+
/**
214+
* "View2" linked list transfer descriptor
215+
*
216+
* Set source address, destination address, data length and transfer
217+
* configuration.
218+
*/
219+
class View2 : public View1
220+
{
221+
public:
222+
using View1::View1;
223+
224+
using Data = std::array<uint32_t, 5>;
225+
static constexpr auto Type = ViewType::View2;
226+
227+
constexpr void
228+
setConfiguration(ChannelConfig_t configuration);
229+
230+
constexpr ChannelConfig_t
231+
configuration() const;
232+
233+
};
234+
235+
/**
236+
* "View3" linked list transfer descriptor
237+
*
238+
* Set source address, destination address, data length, transfer
239+
* configuration and data stride offsets.
240+
*/
241+
class View3 : public View2
242+
{
243+
public:
244+
using View2::View2;
245+
246+
using Data = std::array<uint32_t, 9>;
247+
static constexpr auto Type = ViewType::View3;
248+
249+
constexpr int16_t
250+
sourceDataStride() const;
251+
252+
constexpr void
253+
setSourceDataStride(int16_t stride);
254+
255+
constexpr int16_t
256+
destinationDataStride() const;
257+
258+
constexpr void
259+
setDestinationDataStride(int16_t stride);
260+
};
261+
};
262+
263+
namespace DmaRequests
264+
{
265+
%% for peripheral, instances in requests.items()
266+
267+
%% if none in instances
268+
struct {{ peripheral | capitalize }}
269+
{
270+
%% for s in instances[None]
271+
static constexpr auto {{ s["signal"] }} = DmaRequest({{ s["id"] }});
272+
%% endfor
273+
};
274+
275+
%% else
276+
template<std::size_t Instance>
277+
struct {{ peripheral | capitalize }};
278+
279+
%% for i, signals in instances.items()
280+
template<>
281+
struct {{ peripheral | capitalize }}<{{ i }}>
282+
{
283+
%% for s in signals
284+
static constexpr auto {{ s["signal"] }} = DmaRequest({{ s["id"] }});
285+
%% endfor
286+
};
287+
288+
%% endfor
289+
%% endif
290+
291+
%% endfor
292+
}
293+
294+
} // namespace modm::platform
295+
296+
#include "base_impl.hpp"
297+
298+
#endif // MODM_SAMX7X_DMA_BASE_HPP

0 commit comments

Comments
 (0)