@@ -39,9 +39,14 @@ DMAClass::~DMAClass()
39
39
void DMAClass::begin ()
40
40
{
41
41
if (_beginCount == 0 ) {
42
+
43
+ #if defined(__SAMD51__)
44
+ MCLK->AHBMASK .bit .DMAC_ = 1 ;
45
+ #else
42
46
// enable the DMA interface
43
47
PM->AHBMASK .bit .DMAC_ = 1 ;
44
48
PM->APBBMASK .bit .DMAC_ = 1 ;
49
+ #endif
45
50
46
51
// perform a reset
47
52
DMAC->CTRL .bit .SWRST = 1 ;
@@ -57,9 +62,35 @@ void DMAClass::begin()
57
62
DMAC->CTRL .bit .LVLEN3 = 1 ;
58
63
DMAC->CTRL .bit .DMAENABLE = 1 ;
59
64
60
- // enable the interrupt at lowest priority
65
+ #if defined(__SAMD51__)
66
+ NVIC_DisableIRQ (DMAC_0_IRQn);
67
+ NVIC_ClearPendingIRQ (DMAC_0_IRQn);
68
+ NVIC_EnableIRQ (DMAC_0_IRQn);
69
+ NVIC_SetPriority (DMAC_0_IRQn, (1 << __NVIC_PRIO_BITS) - 1 );
70
+
71
+ NVIC_DisableIRQ (DMAC_1_IRQn);
72
+ NVIC_ClearPendingIRQ (DMAC_1_IRQn);
73
+ NVIC_EnableIRQ (DMAC_1_IRQn);
74
+ NVIC_SetPriority (DMAC_1_IRQn, (1 << __NVIC_PRIO_BITS) - 1 );
75
+
76
+ NVIC_DisableIRQ (DMAC_2_IRQn);
77
+ NVIC_ClearPendingIRQ (DMAC_2_IRQn);
78
+ NVIC_EnableIRQ (DMAC_2_IRQn);
79
+ NVIC_SetPriority (DMAC_2_IRQn, (1 << __NVIC_PRIO_BITS) - 1 );
80
+
81
+ NVIC_DisableIRQ (DMAC_3_IRQn);
82
+ NVIC_ClearPendingIRQ (DMAC_3_IRQn);
83
+ NVIC_EnableIRQ (DMAC_3_IRQn);
84
+ NVIC_SetPriority (DMAC_3_IRQn, (1 << __NVIC_PRIO_BITS) - 1 );
85
+
86
+ NVIC_DisableIRQ (DMAC_4_IRQn);
87
+ NVIC_ClearPendingIRQ (DMAC_4_IRQn);
88
+ NVIC_EnableIRQ (DMAC_4_IRQn);
89
+ NVIC_SetPriority (DMAC_4_IRQn, (1 << __NVIC_PRIO_BITS) - 1 );
90
+ #else
61
91
NVIC_EnableIRQ (DMAC_IRQn);
62
92
NVIC_SetPriority (DMAC_IRQn, (1 << __NVIC_PRIO_BITS) - 1 );
93
+ #endif
63
94
}
64
95
65
96
_beginCount++;
@@ -71,14 +102,27 @@ void DMAClass::end()
71
102
72
103
if (_beginCount == 0 ) {
73
104
// disable the interrupt
105
+ #if defined(__SAMD51__)
106
+ NVIC_DisableIRQ (DMAC_0_IRQn);
107
+ NVIC_DisableIRQ (DMAC_1_IRQn);
108
+ NVIC_DisableIRQ (DMAC_2_IRQn);
109
+ NVIC_DisableIRQ (DMAC_3_IRQn);
110
+ NVIC_DisableIRQ (DMAC_4_IRQn);
111
+ #else
74
112
NVIC_DisableIRQ (DMAC_IRQn);
113
+ #endif
75
114
76
115
// disable
77
116
DMAC->CTRL .bit .DMAENABLE = 0 ;
78
117
79
118
// disable the DMA interface
80
- PM->APBBMASK .bit .DMAC_ = 0 ;
119
+ #if defined(__SAMD51__)
120
+ MCLK->AHBMASK .bit .DMAC_ = 0 ;
121
+ #else
122
+ // enable the DMA interface
81
123
PM->AHBMASK .bit .DMAC_ = 0 ;
124
+ PM->APBBMASK .bit .DMAC_ = 0 ;
125
+ #endif
82
126
}
83
127
}
84
128
@@ -96,9 +140,14 @@ int DMAClass::allocateChannel()
96
140
memset ((void *)&_descriptors[i], 0x00 , sizeof (_descriptors[i]));
97
141
98
142
// select the channel and reset it
143
+ #if defined(__SAMD51__)
144
+ DMAC->Channel [i].CHCTRLA .bit .ENABLE = 0 ;
145
+ DMAC->Channel [i].CHCTRLA .bit .SWRST = 1 ;
146
+ #else
99
147
DMAC->CHID .bit .ID = i;
100
148
DMAC->CHCTRLA .bit .ENABLE = 0 ;
101
149
DMAC->CHCTRLA .bit .SWRST = 1 ;
150
+ #endif
102
151
103
152
channel = i;
104
153
break ;
@@ -111,21 +160,34 @@ int DMAClass::allocateChannel()
111
160
void DMAClass::freeChannel (int channel)
112
161
{
113
162
// select the channel and disable it
114
- DMAC->CHID .bit .ID = channel;
115
- DMAC->CHCTRLA .bit .ENABLE = 0 ;
163
+ #if defined(__SAMD51__)
164
+ DMAC->Channel [channel].CHCTRLA .bit .ENABLE = 0 ;
165
+ #else
166
+ DMAC->CHID .bit .ID = channel;
167
+ DMAC->CHCTRLA .bit .ENABLE = 0 ;
168
+ #endif
116
169
117
170
_channelMask &= ~(1 << channel);
118
171
}
119
172
120
173
void DMAClass::setPriorityLevel (int channel, int level)
121
174
{
122
175
// select the channel and set priority level
123
- DMAC->CHID .bit .ID = channel;
124
- DMAC->CHCTRLB .bit .LVL = level;
176
+ #if defined(__SAMD51__)
177
+
178
+ DMAC->Channel [channel].CHPRILVL .reg = level;
179
+ #else
180
+ DMAC->CHID .bit .ID = channel;
181
+ DMAC->CHCTRLB .bit .LVL = level;
182
+ #endif
125
183
}
126
184
127
185
void DMAClass::setTriggerSource (int channel, int source)
128
186
{
187
+ #if defined(__SAMD51__)
188
+ DMAC->Channel [channel].CHCTRLA .bit .TRIGSRC = source;
189
+ DMAC->Channel [channel].CHCTRLA .bit .TRIGACT = DMAC_CHCTRLA_TRIGACT_BLOCK_Val;
190
+ #else
129
191
// select the channel and set a trigger source
130
192
DMAC->CHID .bit .ID = channel;
131
193
DMAC->CHCTRLB .bit .TRIGSRC = source;
@@ -136,6 +198,7 @@ void DMAClass::setTriggerSource(int channel, int source)
136
198
} else {
137
199
DMAC->CHCTRLB .bit .TRIGACT = DMAC_CHCTRLB_TRIGACT_BLOCK_Val;
138
200
}
201
+ #endif
139
202
}
140
203
141
204
void DMAClass::setTransferWidth (int channel, int transferWidth)
@@ -178,8 +241,11 @@ int DMAClass::transfer(int channel, void* src, void* dst, uint16_t size)
178
241
return 1 ;
179
242
}
180
243
244
+
245
+ #if !defined(__SAMD51__)
181
246
// select the channel
182
247
DMAC->CHID .bit .ID = channel;
248
+ #endif
183
249
184
250
// disable event output generation and block actions
185
251
_descriptors[channel].BTCTRL .bit .EVOSEL = DMAC_BTCTRL_EVOSEL_DISABLE_Val;
@@ -223,16 +289,26 @@ int DMAClass::transfer(int channel, void* src, void* dst, uint16_t size)
223
289
// validate the descriptor
224
290
_descriptors[channel].BTCTRL .bit .VALID = 1 ;
225
291
292
+ #if defined(__SAMD51__)
293
+ DMAC->Channel [channel].CHINTENSET .bit .TERR = 1 ;
294
+ DMAC->Channel [channel].CHINTENSET .bit .TCMPL = 1 ;
295
+ DMAC->Channel [channel].CHCTRLA .bit .ENABLE = 1 ;
296
+
297
+ if (DMAC->Channel [channel].CHCTRLA .bit .TRIGSRC == 0 ) {
298
+ // uses software trigger, so trigger it
299
+ DMAC->SWTRIGCTRL .reg |= (1 << channel);
300
+ }
301
+ #else
226
302
// enable channel and transfer error + complete interrupts
227
303
DMAC->CHINTENSET .bit .TERR = 1 ;
228
304
DMAC->CHINTENSET .bit .TCMPL = 1 ;
229
305
DMAC->CHCTRLA .bit .ENABLE = 1 ;
230
306
231
-
232
307
if (DMAC->CHCTRLB .bit .TRIGSRC == 0 ) {
233
308
// uses software trigger, so trigger it
234
309
DMAC->SWTRIGCTRL .reg |= (1 << channel);
235
310
}
311
+ #endif
236
312
237
313
return 0 ;
238
314
}
@@ -251,11 +327,32 @@ void DMAClass::onService()
251
327
{
252
328
// get the channel and select it
253
329
int channel = DMAC->INTPEND .bit .ID ;
330
+ #if !defined(__SAMD51__)
254
331
DMAC->CHID .bit .ID = channel;
332
+ #endif
255
333
256
334
// invalidate the channel
257
335
_descriptors[channel].BTCTRL .bit .VALID = 0 ;
258
336
337
+ #if defined(__SAMD51__)
338
+ if (DMAC->Channel [channel].CHINTFLAG .bit .TERR ) {
339
+ // clear the error interrupt and call the error callback if there is one
340
+ DMAC->Channel [channel].CHINTFLAG .bit .TERR = 1 ;
341
+
342
+ if (_transferErrorCallbacks[channel]) {
343
+ _transferErrorCallbacks[channel](channel);
344
+ }
345
+ }
346
+
347
+ if (DMAC->Channel [channel].CHINTFLAG .bit .TCMPL ) {
348
+ // clear the complete interrupt and call the callback if there is one
349
+ DMAC->Channel [channel].CHINTFLAG .bit .TCMPL = 1 ;
350
+
351
+ if (_transferCompleteCallbacks[channel]) {
352
+ _transferCompleteCallbacks[channel](channel);
353
+ }
354
+ }
355
+ #else
259
356
if (DMAC->CHINTFLAG .bit .TERR ) {
260
357
// clear the error interrupt and call the error callback if there is one
261
358
DMAC->CHINTFLAG .bit .TERR = 1 ;
@@ -273,12 +370,55 @@ void DMAClass::onService()
273
370
_transferCompleteCallbacks[channel](channel);
274
371
}
275
372
}
373
+ #endif
276
374
}
277
375
278
376
extern " C" {
377
+ #if defined(__SAMD51__)
378
+ static void _dmac_handler (void )
379
+ {
380
+ DMA.onService ();
381
+ }
382
+ /* *
383
+ * \brief DMAC interrupt handler
384
+ */
385
+ void DMAC_0_Handler (void )
386
+ {
387
+ _dmac_handler ();
388
+ }
389
+ /* *
390
+ * \brief DMAC interrupt handler
391
+ */
392
+ void DMAC_1_Handler (void )
393
+ {
394
+ _dmac_handler ();
395
+ }
396
+ /* *
397
+ * \brief DMAC interrupt handler
398
+ */
399
+ void DMAC_2_Handler (void )
400
+ {
401
+ _dmac_handler ();
402
+ }
403
+ /* *
404
+ * \brief DMAC interrupt handler
405
+ */
406
+ void DMAC_3_Handler (void )
407
+ {
408
+ _dmac_handler ();
409
+ }
410
+ /* *
411
+ * \brief DMAC interrupt handler
412
+ */
413
+ void DMAC_4_Handler (void )
414
+ {
415
+ _dmac_handler ();
416
+ }
417
+ #else
279
418
void DMAC_Handler () {
280
419
DMA.onService ();
281
420
}
421
+ #endif
282
422
}
283
423
284
424
DMAClass DMA;
0 commit comments