1 //
2 // Copyright (c) 2010-2024 Antmicro
3 //
4 // This file is licensed under the MIT License.
5 // Full license text is available in 'licenses/MIT.txt'.
6 //
7 
8 using System;
9 using System.Linq;
10 using System.Collections.Generic;
11 using System.Collections.ObjectModel;
12 using Antmicro.Renode.Core;
13 using Antmicro.Renode.Core.Structure.Registers;
14 using Antmicro.Renode.Logging;
15 using Antmicro.Renode.Peripherals.Bus;
16 
17 namespace Antmicro.Renode.Peripherals.DMA
18 {
19     public class STM32WBA55_GPDMA : IDoubleWordPeripheral, IKnownSize, IGPIOReceiver, INumberedGPIOOutput
20     {
STM32WBA55_GPDMA(IMachine machine, int numberOfChannels)21         public STM32WBA55_GPDMA(IMachine machine, int numberOfChannels)
22         {
23             this.machine = machine;
24             engine = new DmaEngine(machine.GetSystemBus(this));
25             channels = new Channel[numberOfChannels];
26             var innerConnections = new Dictionary<int, IGPIO>();
27 
28             for(var i = 0; i < channels.Length; ++i)
29             {
30                 var gpio = new GPIO();
31                 channels[i] = new Channel(this, gpio, i);
32                 innerConnections[i] = gpio;
33             }
34             Connections = new ReadOnlyDictionary<int, IGPIO>(innerConnections);
35 
36             var nonsecureMaskedInteruptStatus = new DoubleWordRegister(this)
37                 .WithFlags(0, channels.Length, FieldMode.Read,
38                     valueProviderCallback: (i, _) => channels[i].GlobalInterrupt,
39                     name: $"Masked interrupt status for secure channel (MISn)"
40                 )
41                 .WithReservedBits(channels.Length, 32 - channels.Length);
42 
43             var registerMap = new Dictionary<long, DoubleWordRegister>
44             {
45                 {(long)Registers.NonsecureMaskedInteruptStatus, nonsecureMaskedInteruptStatus},
46             };
47             registers = new DoubleWordRegisterCollection(this, registerMap);
48         }
49 
Reset()50         public void Reset()
51         {
52             registers.Reset();
53             foreach(var channel in channels)
54             {
55                 channel.Reset();
56             }
57         }
58 
ReadDoubleWord(long offset)59         public uint ReadDoubleWord(long offset)
60         {
61             if(registers.TryRead(offset, out var result))
62             {
63                 return result;
64             }
65             if(TryGetChannelBasedOnOffset(offset, out var channel))
66             {
67                 return channel.ReadDoubleWord(offset);
68             }
69             this.LogUnhandledRead(offset);
70             return 0;
71         }
72 
WriteDoubleWord(long offset, uint value)73         public void WriteDoubleWord(long offset, uint value)
74         {
75             if(registers.TryWrite(offset, value))
76             {
77                 return;
78             }
79             if(TryGetChannelBasedOnOffset(offset, out var channel))
80             {
81                 channel.WriteDoubleWord(offset, value);
82                 return;
83             }
84             this.LogUnhandledWrite(offset, value);
85         }
86 
OnGPIO(int number, bool value)87         public void OnGPIO(int number, bool value)
88         {
89             var channel = channels.ElementAtOrDefault(number);
90             if(channel == null)
91             {
92                 this.Log(LogLevel.Warning, "Channel number {0} is out of range, must be in [0; {1}]", number, channels.Length - 1);
93                 return;
94             }
95 
96             if(!value)
97             {
98                 return;
99             }
100 
101             this.Log(LogLevel.Noisy, "DMA peripheral request on channel {0}", number);
102             if(channel.TryTriggerTransfer())
103             {
104                 this.Log(LogLevel.Debug, "DMA peripheral request on channel {0} ignored", number);
105             }
106         }
107 
108         public IReadOnlyDictionary<int, IGPIO> Connections { get; }
109 
110         public long Size => 0x1000;
111 
TryGetChannelBasedOnOffset(long offset, out Channel channel)112         private bool TryGetChannelBasedOnOffset(long offset, out Channel channel)
113         {
114             var shifted = offset - (long)Registers.Channel0LinkedListBaseAddress;
115             var channelNumber = shifted / ShiftBetweenChannels;
116             channel = channels.ElementAtOrDefault((int)channelNumber);
117             return channel != null;
118         }
119 
120         private readonly IMachine machine;
121         private readonly DmaEngine engine;
122         private readonly DoubleWordRegisterCollection registers;
123         private readonly Channel[] channels;
124 
125         private const int ShiftBetweenChannels = 0x80;
126 
127         private class Channel
128         {
Channel(STM32WBA55_GPDMA parent, IGPIO interrupt, int number)129             public Channel(STM32WBA55_GPDMA parent, IGPIO interrupt, int number)
130             {
131                 this.parent = parent;
132                 this.interrupt = interrupt;
133                 channelNumber = number;
134 
135                 var registersMap = new Dictionary<long, DoubleWordRegister>();
136 
137                 registersMap.Add((long)ChannelRegisters.ChannelLinkedListBaseAddress + (number * ShiftBetweenChannels), new DoubleWordRegister(parent)
138                     .WithReservedBits(0, 16)
139                     .WithValueField(16, 16, out linkedListBaseAddress, name: "Linked list base address (LBA)"));
140 
141                 registersMap.Add((long)ChannelRegisters.ChannelFlagClear + (number * ShiftBetweenChannels), new DoubleWordRegister(parent)
142                     .WithReservedBits(0, 8)
143                     .WithFlag(8, FieldMode.Write, name: "Transfer complete flag clear (TCF)",
144                             writeCallback: (_, val) =>
145                             {
146                                 if(val)
147                                 {
148                                     TransferComplete = false;
149                                 }
150                             })
151                     .WithFlag(9, FieldMode.Write, name: "Half transfer flag clear (TCF)",
152                             writeCallback: (_, val) =>
153                             {
154                                 if(val)
155                                 {
156                                     HalfTransfer = false;
157                                 }
158                             })
159                     .WithFlag(10, FieldMode.Write, name: "Data transfer error flag clear (DTEF)",
160                             writeCallback: (_, val) =>
161                             {
162                                 if(val)
163                                 {
164                                     DataTransferError = false;
165                                 }
166                             })
167                     .WithFlag(11, FieldMode.Write, name: "Update link transfer error flag clear (ULEF)",
168                             writeCallback: (_, val) =>
169                             {
170                                 if(val)
171                                 {
172                                     UpdateLinkTransferError = false;
173                                 }
174                             })
175                     .WithFlag(12, FieldMode.Write, name: "User setting error flag clear (USEF)",
176                             writeCallback: (_, val) =>
177                             {
178                                 if(val)
179                                 {
180                                     UserSettingError = false;
181                                 }
182                             })
183                     .WithFlag(13, FieldMode.Write, name: "Completed suspension flag clear (SUSPF)",
184                             writeCallback: (_, val) =>
185                             {
186                                 if(val)
187                                 {
188                                     CompletedSuspension = false;
189                                 }
190                             })
191                     .WithFlag(14, FieldMode.Write, name: "Trigger overrun flag clear (TOF)",
192                             writeCallback: (_, val) =>
193                             {
194                                 if(val)
195                                 {
196                                     TriggerOverrun = false;
197                                 }
198                             })
199                     .WithReservedBits(15, 17)
200                     .WithWriteCallback((_, __) => Update())
201                 );
202 
203                 registersMap.Add((long)ChannelRegisters.ChannelStatus + (number * ShiftBetweenChannels), new DoubleWordRegister(parent)
204                     .WithTag("Idle (IDLEF)", 0, 1)
205                     .WithReservedBits(1, 7)
206                     .WithFlag(8, FieldMode.Read, name: "Transfer complete flag (TCF)",
207                         valueProviderCallback: _ => TransferComplete)
208                     .WithFlag(9, FieldMode.Read, name: "Half transfer flag (HTF)",
209                         valueProviderCallback: _ => HalfTransfer)
210                     .WithFlag(10, FieldMode.Read, name: "Data transfer error flag (DTEF)",
211                         valueProviderCallback: _ => DataTransferError)
212                     .WithFlag(11, FieldMode.Read, name: "Update link transfer error flag (ULEF)",
213                         valueProviderCallback: _ => UpdateLinkTransferError)
214                     .WithFlag(12, FieldMode.Read, name: "User setting error flag (USEF)",
215                         valueProviderCallback: _ => UserSettingError)
216                     .WithFlag(13, FieldMode.Read, name: "Completed suspension flag (SUSPF)",
217                         valueProviderCallback: _ => CompletedSuspension)
218                     .WithFlag(14, FieldMode.Read, name: "Trigger overrun flag (TOF)",
219                         valueProviderCallback: _ => TriggerOverrun)
220                     .WithReservedBits(15, 1)
221                     .WithValueField(16, 8, out monitoredFIFOlevel, name: "Monitored FIFO level (FIFOL)")   //TODO
222                     .WithReservedBits(24, 8)
223                     .WithWriteCallback((_, __) => Update()));
224 
225                 registersMap.Add((long)ChannelRegisters.ChannelControl + (number * ShiftBetweenChannels), new DoubleWordRegister(parent)
226                     .WithFlag(0, out channelEnable,
227                         writeCallback: (_, val) =>
228                         {
229                             if(val)
230                             {
231                                 DoTransfer();
232                             }
233                         },
234                         valueProviderCallback: _ => false, name: "Enable (EN)")
235                       .WithFlag(1, out channelReset,
236                         writeCallback: (_, val) =>
237                         {
238                             if(val)
239                             {
240                                 //TODO: check GPDMA_CxBR1,GPDMA_CxSAR, and GPDMA_CxDAR
241                                 channelEnable.Value = false;
242                                 channelSuspend.Value = false;
243                             }
244                         },
245                         valueProviderCallback: _ => false, name: "RESET (RESET)")
246                       .WithFlag(2, out channelSuspend,
247                         writeCallback: (_, val) =>
248                         {
249                             if(val)
250                             {
251                                 // TODO
252                             }
253                         }, name: "SUSPEND (SUSP)")
254                     .WithReservedBits(3, 5)
255                     .WithFlag(8, out transferCompleteInterruptEnable, name: "Transfer complete interrupt enable (TCIE)")
256                     .WithFlag(9, out halfTransferInterruptEnable, name: "Half transfer interrupt enable (HTIE)")
257                     .WithFlag(10, out dataTransferErrorInterruptEnable, name: "Data transfer error interrupt enable (DTEIE)")
258                     .WithFlag(11, out updateLinkTransferErrorInterruptEnable, name: "Update link transfer error interrupt enable (ULEIE)")
259                     .WithFlag(12, out userSettingErrorInterruptEnable, name: "User setting error interrupt enable (USEIE)")
260                     .WithFlag(13, out completedSuspensionInterruptEnable, name: "Completed suspension interrupt enable (SUSPIE)")
261                     .WithFlag(14, out triggerOverrunInterruptEnable, name: "Trigger overrun interrupt enable (TOIE)")
262                     .WithReservedBits(15, 1)
263                     .WithTag("Link step mode (LSM)", 16, 1)
264                     .WithTag("Linked list allocated port (LAP)", 17, 1)
265                     .WithReservedBits(18, 4)
266                     .WithEnumField(22, 2, out priorityLevel, name: "Priority level (PRIO)")
267                     .WithReservedBits(24, 8)
268                     .WithWriteCallback((_, __) => Update()));
269 
270                 registersMap.Add((long)ChannelRegisters.ChannelTransfer1 + (number * ShiftBetweenChannels), new DoubleWordRegister(parent)
271                     .WithEnumField(0, 2, out sourceDataWidth, name: "Binary logarithm source data width (SDW_LOG2)")
272                     .WithReservedBits(2, 1)
273                     .WithFlag(3, out sourceIncrementingBurst, name: "Source incrementing burst (SINC)")
274                     .WithValueField(4, 5, out sourceBurstLength, name: "Source burst length (SBL_1)")  //TODO
275                     .WithReservedBits(10, 1)
276                     .WithTag("Padding alignment mode (PAM)", 11, 2)
277                     .WithTag("Source byte exchange (SBX)", 13, 1)
278                     .WithTag("Source allocated port (SAP)", 14, 1)
279                     .WithTag("Security attribute source (SSEC)", 15, 1)
280                     .WithEnumField(16, 2, out destinationDataWith, name: "Binary logarithm destination data with (DDW_LOG2)")
281                     .WithReservedBits(18, 1)
282                     .WithFlag(19, out destinationIncrementingBurst, name: "Destination incrementing burst (DINC)")
283                     .WithValueField(20, 6, out destinationBurstLength, name: "Destination burst length (DBL_1)")   //TODO
284                     .WithTag("Destination byte exchange (DBX)", 26, 1)
285                     .WithTag("Destination half-word exchange (DHX)", 27, 1)
286                     .WithReservedBits(28, 2)
287                     .WithTag("Destination allocated port (DAP)", 30, 1)
288                     .WithTag("Security attribute destination (DSEC)", 31, 1));
289 
290                 registersMap.Add((long)ChannelRegisters.ChannelTransfer2 + (number * ShiftBetweenChannels), new DoubleWordRegister(parent)
291                     .WithEnumField(0, 5, out hardwareRequestSelection, name: "Hardware request selection (REQSEL)")
292                     .WithReservedBits(6, 3)
293                     .WithFlag(9, out softwareRequest, name: "Software request (SWREQ)")
294                     .WithTag("Destination hardware request (DREQ)", 10, 1)
295                     .WithFlag(11, out blockHardwareRequest, name: "Block hardware request (BREQ)") //TODO: implement block/burst transfer
296                     .WithReservedBits(12, 2)
297                     .WithTag("Trigger mode (TRIGM)", 14, 2)
298                     .WithEnumField(16, 5, out triggerEventInputSelection, name: "Trigger event input selection (TRIGSEL)")
299                     .WithReservedBits(21, 3)
300                     .WithTag("Trigger event polarity (TRIGPOL)", 24, 2)
301                     .WithReservedBits(26, 4)
302                     .WithValueField(30, 2, out transferCompleteEventMode, name: "Transfer complete event mode (TCEM)")   //TODO
303                     );
304 
305                 //TODO: implement registers & callbacks
306                 registersMap.Add((long)ChannelRegisters.ChannelBlock1 + (number * ShiftBetweenChannels), new DoubleWordRegister(parent)
307                     /* TODO: Block size transferred from the source. When the channel is enabled, this field becomes
308                     read-only and is decremented, indicating the remaining number of data items in the current
309                     source block to be transferred. BNDT[15:0] is programmed in number of bytes, maximum
310                     source block size is 64 Kbytes -1. Once the last data transfer is completed (BNDT[15:0] = 0)*/
311                     .WithValueField(0, 16, out blockNumberDataBytesFromSource, name: "Block number data bytes from source (BNDT)",
312                         writeCallback: (_, val) => originalBlockNumberDataBytesFromSource = val));
313                         registersMap.Add((long)ChannelRegisters.ChannelSourceAddress + (number * ShiftBetweenChannels), new DoubleWordRegister(parent)
314                     .WithValueField(0, 32, out sourceAddress, name: "Source address (SA)",
315                         writeCallback: (_, val) => currentSourceAddress = val));
316 
317                 registersMap.Add((long)ChannelRegisters.ChannelDestinationAddress + (number * ShiftBetweenChannels), new DoubleWordRegister(parent)
318                     .WithValueField(0, 32, out destinationAddress, name: "Destination address (DA)",
319                         writeCallback: (_, val) => currentDestinationAddress = val));
320 
321                 registersMap.Add((long)ChannelRegisters.ChannelLinkedListAddress + (number * ShiftBetweenChannels), new DoubleWordRegister(parent)
322                     .WithReservedBits(0, 2)
323                     /*TODO: If UT1 = UT2 = UB1 = USA = UDA = ULL = 0 and if LA[15:2] = 0, the current LLI is the last
324                     one. The channel transfer is completed without any update of the linked-list GPDMA register
325                     file. Else, this field is the pointer to the memory address offset from which the next linked-list data
326                     structure is automatically fetched from, once the data transfer is completed, in order to
327                     conditionally update the linked-list GPDMA internal register file (GPDMA_CxTR1,
328                     GPDMA_CxTR2, GPDMA_CxBR1, GPDMA_CxSAR, GPDMA_CxDAR, and
329                     GPDMA_CxLLR*/
330                     .WithValueField(2, 14, out lowSignificantAddress, name: "Low-significant address (LA)")
331                     .WithFlag(16, out updateLLRfromMemory, name: "Update CxLLR register from memory (ULL)")
332                     .WithReservedBits(17, 10)
333                     .WithFlag(27, out updateDARfromMemory, name: "Update CxDAR register from memory (UDA)")
334                     .WithFlag(28, out updateSARfromMemory, name: "Update CxSAR register from memory (USA)")
335                     .WithFlag(29, out updateBR1fromMemory, name: "Update CxBR1 register from memory (UB1)")
336                     .WithFlag(30, out updateTR2fromMemory, name: "Update CxTR2 register from memory (UT2)")
337                     .WithFlag(31, out updateTR1fromMemory, name: "Update CxTR1 register from memory (UT1)"));
338 
339                 registers = new DoubleWordRegisterCollection(parent, registersMap);
340             }
341 
ReadDoubleWord(long offset)342             public uint ReadDoubleWord(long offset)
343             {
344                 return registers.Read(offset);
345             }
346 
WriteDoubleWord(long offset, uint value)347             public void WriteDoubleWord(long offset, uint value)
348             {
349                 registers.Write(offset, value);
350             }
351 
Reset()352             public void Reset()
353             {
354                 registers.Reset();
355                 TransferComplete = false;
356                 HalfTransfer = false;
357             }
358 
TryTriggerTransfer()359             public bool TryTriggerTransfer()
360             {
361                 if(!Enabled || monitoredFIFOlevel.Value == 0)
362                 {
363                     return false;
364                 }
365                 DoTransfer();
366                 Update();
367                 return true;
368             }
369 
Update()370             private void Update()
371             {
372                 var result = (TransferComplete && TransferCompleteInterruptEnable)
373                         || (HalfTransfer && HalfTransferInterruptEnable)
374                         || (DataTransferError && DataTransferErrorInterruptEnable)
375                         || (UpdateLinkTransferError && UpdateLinkTransferErrorInterruptEnable)
376                         || (UserSettingError && UserSettingErrorInterruptEnable)
377                         || (CompletedSuspension && CompletedSuspensionInterruptEnable)
378                         || (TriggerOverrun && TriggerOverrunInterruptEnable);
379                 interrupt.Set(result);
380 
381                 parent.Log(LogLevel.Noisy, "Update of channel {0} triggered. Interrupt set: {1}", channelNumber, result);
382             }
383 
384             public bool GlobalInterrupt => HalfTransfer || TransferComplete || DataTransferError || UpdateLinkTransferError || UserSettingError || CompletedSuspension || TriggerOverrun;
385 
386             public bool Enabled => channelEnable.Value;
387 
388             public bool HalfTransfer { get; set; }
389             public bool TransferComplete { get; set; }
390             public bool DataTransferError { get; set; }
391             public bool UpdateLinkTransferError { get; set; }
392             public bool UserSettingError { get; set; }
393             public bool CompletedSuspension { get; set; }
394             public bool TriggerOverrun { get; set; }
395 
396             public bool HalfTransferInterruptEnable => halfTransferInterruptEnable.Value;
397             public bool TransferCompleteInterruptEnable => transferCompleteInterruptEnable.Value;
398             public bool DataTransferErrorInterruptEnable => dataTransferErrorInterruptEnable.Value;
399             public bool UpdateLinkTransferErrorInterruptEnable => updateLinkTransferErrorInterruptEnable.Value;
400             public bool UserSettingErrorInterruptEnable => userSettingErrorInterruptEnable.Value;
401             public bool CompletedSuspensionInterruptEnable => completedSuspensionInterruptEnable.Value;
402             public bool TriggerOverrunInterruptEnable => triggerOverrunInterruptEnable.Value;
403 
DoTransfer()404             private void DoTransfer()
405             {
406                 //TODO: implement linked list mode
407                 //TODO: implement to copy whole block if source = destination = memory
408 
409                 //get the size of a data unit (data beat) to copy
410                 var toCopy = Math.Max((uint)SizeToType(sourceDataWidth.Value), (uint)SizeToType(destinationDataWith.Value));
411 
412                 while(blockNumberDataBytesFromSource.Value > 0)
413                 {
414                     var response = IssueCopy(currentSourceAddress, currentDestinationAddress, toCopy,
415                         sourceIncrementingBurst.Value, destinationIncrementingBurst.Value, sourceDataWidth.Value,
416                         destinationDataWith.Value);
417 
418                     sourceAddress.Value = response.ReadAddress.Value;
419                     currentSourceAddress = response.ReadAddress.Value;
420                     destinationAddress.Value = response.WriteAddress.Value;
421                     currentDestinationAddress = response.WriteAddress.Value;
422 
423                     blockNumberDataBytesFromSource.Value -= 1;
424                     HalfTransfer = blockNumberDataBytesFromSource.Value <= originalBlockNumberDataBytesFromSource / 2;
425                     TransferComplete = blockNumberDataBytesFromSource.Value == 0;
426                     Update();
427                 }
428             }
429 
IssueCopy(ulong sourceAddress, ulong destinationAddress, uint size, bool incrementReadAddress, bool incrementWriteAddress, TransferSize sourceDataWidth, TransferSize destinationDataWith)430             private Response IssueCopy(ulong sourceAddress, ulong destinationAddress, uint size,
431                 bool incrementReadAddress, bool incrementWriteAddress, TransferSize sourceDataWidth,
432                 TransferSize destinationDataWith)
433             {
434                 var request = new Request(
435                     sourceAddress,
436                     destinationAddress,
437                     (int)size,
438                     SizeToType(sourceDataWidth),
439                     SizeToType(destinationDataWith),
440                     incrementReadAddress,
441                     incrementWriteAddress
442                 );
443                 return parent.engine.IssueCopy(request);
444             }
445 
SizeToType(TransferSize size)446             private TransferType SizeToType(TransferSize size)
447             {
448                 switch(size)
449                 {
450                     case TransferSize.Bits32:
451                         return TransferType.DoubleWord;
452                     case TransferSize.Bits16:
453                         return TransferType.Word;
454                     case TransferSize.Bits8:
455                     default:
456                         return TransferType.Byte;
457                 }
458             }
459 
460             private IValueRegisterField monitoredFIFOlevel;
461 
462             //Channel Control CxCR
463             private IFlagRegisterField channelEnable;
464             private IFlagRegisterField channelReset;
465             private IFlagRegisterField channelSuspend;
466             private IFlagRegisterField transferCompleteInterruptEnable;
467             private IFlagRegisterField halfTransferInterruptEnable;
468             private IFlagRegisterField dataTransferErrorInterruptEnable;
469             private IFlagRegisterField updateLinkTransferErrorInterruptEnable;
470             private IFlagRegisterField userSettingErrorInterruptEnable;
471             private IFlagRegisterField completedSuspensionInterruptEnable;
472             private IFlagRegisterField triggerOverrunInterruptEnable;
473             private IEnumRegisterField<Priority> priorityLevel;
474 
475             private IValueRegisterField linkedListBaseAddress;
476 
477             //Transfer Register CxTR 1&2
478             private IFlagRegisterField sourceIncrementingBurst;
479             private IFlagRegisterField destinationIncrementingBurst;
480             private IValueRegisterField sourceBurstLength;
481             private IValueRegisterField destinationBurstLength;
482             private IEnumRegisterField<TransferSize> sourceDataWidth;
483             private IEnumRegisterField<TransferSize> destinationDataWith;
484             private IEnumRegisterField<HardwareRequestSelection> hardwareRequestSelection;
485             private IFlagRegisterField softwareRequest;
486             private IFlagRegisterField blockHardwareRequest;
487             private IEnumRegisterField<TriggerEventInputSelection> triggerEventInputSelection;
488             private IValueRegisterField transferCompleteEventMode;
489 
490             private IValueRegisterField blockNumberDataBytesFromSource;
491             private IValueRegisterField sourceAddress;
492             private IValueRegisterField destinationAddress;
493 
494             // Linked list address
495             private IValueRegisterField lowSignificantAddress;
496             private IFlagRegisterField updateLLRfromMemory;
497             private IFlagRegisterField updateDARfromMemory;
498             private IFlagRegisterField updateSARfromMemory;
499             private IFlagRegisterField updateBR1fromMemory;
500             private IFlagRegisterField updateTR2fromMemory;
501             private IFlagRegisterField updateTR1fromMemory;
502 
503             private ulong currentSourceAddress;
504             private ulong currentDestinationAddress;
505             private ulong originalBlockNumberDataBytesFromSource;
506 
507             private readonly DoubleWordRegisterCollection registers;
508             private readonly STM32WBA55_GPDMA parent;
509             private readonly int channelNumber;
510             private readonly IGPIO interrupt;
511 
512             private enum Priority
513             {
514                 LowPrioLowWeight = 0,
515                 LowPrioMidWeight = 1,
516                 LowPrioHighWeigt = 2,
517                 HighPrio = 3
518             }
519 
520             private enum TransferSize
521             {
522                 Bits8 = 0, //byte
523                 Bits16 = 1, // half-word (2bytes)
524                 Bits32 = 2, // word (4bytes)
525                 UserSettingError = 3
526             }
527 
528             private enum HardwareRequestSelection
529             {
530                 Adc4_dma = 0,
531                 Spi1_rx_dma = 1,
532                 Spi1_tx_dma = 2,
533                 Spi3_rx_dma = 3,
534                 Spi3_tx_dma = 4,
535                 I2c1_rx_dma = 5,
536                 I2c1_tx_dma = 6,
537                 I2c1_evc_dma = 7,
538                 I2c3_rx_dma = 8,
539                 I2c3_tx_dma = 9,
540                 I2c3_evc_dma = 10,
541                 Usart1_rx_dma = 11,
542                 Usart1_tx_dma = 12,
543                 Usart2_rx_dma = 13,
544                 Usart2_tx_dma = 14,
545                 Lpuart1_rx_dma = 15,
546                 Lpuart1_tx_dma = 16,
547                 Sai_a_dma = 17,
548                 Sai_b_dma = 18,
549                 Tim1_cc1_dma = 19,
550                 Tim1_cc2_dma = 20,
551                 Tim1_cc3_dma = 21,
552                 Tim1_cc4_dma = 22,
553                 Tim1_upd_dma = 23,
554                 Tim1_trg_dma = 24,
555                 Tim1_com_dma = 25,
556                 Tim2_cc1_dma = 26,
557                 Tim2_cc2_dma = 27,
558                 Tim2_cc3_dma = 28,
559                 Tim2_cc4_dma = 29,
560                 Tim2_upd_dma = 30,
561                 Tim3_cc1_dma = 31,
562                 Tim3_cc2_dma = 32,
563                 Tim3_cc3_dma = 33,
564                 Tim3_cc4_dma = 34,
565                 Tim3_upd_dma = 35,
566                 Tim3_trg_dma = 36,
567                 Tim16_cc1_dma = 37,
568                 Tim16_upd_dma = 38,
569                 Tim17_cc1_dma = 39,
570                 Tim17_upd_dma = 40,
571                 Aes_in_dma = 41,
572                 Aes_out_dma = 42,
573                 Hash_in_dma = 43,
574                 Saes_in_dma = 44,
575                 Saes_out_dma = 45,
576                 Lptim1_ic1_dma = 46,
577                 Lptim1_ic2_dma = 47,
578                 Lptim1_ue_dma = 48,
579                 Lptim2_ic1_dma = 49,
580                 Lptim2_ic2_dma = 50,
581                 Lptim2_ue_dma = 51,
582             }
583 
584             private enum TriggerEventInputSelection
585             {
586                 Exti0 = 0,
587                 Exti1 = 1,
588                 Exti2 = 2,
589                 Exti3 = 3,
590                 Exti4 = 4,
591                 Exti5 = 5,
592                 Exti6 = 6,
593                 Exti7 = 7,
594                 Tamp_trg1 = 8,
595                 Tamp_trg2 = 9,
596                 Tamp_trg3 = 10,
597                 Lptim1_ch1 = 11,
598                 Lptim1_ch2 = 12,
599                 Lptim2_ch1 = 13,
600                 Lptim2_ch2 = 14,
601                 Comp1_out = 15,
602                 Comp2_out = 16,
603                 Rtc_alra_trg = 17,
604                 Rtc_alrb_trg = 18,
605                 Rtc_wut_trg = 19,
606                 Gpdma1_ch0_tc = 20,
607                 Gpdma1_ch1_tc = 21,
608                 Gpdma1_ch2_tc = 22,
609                 Gpdma1_ch3_tc = 23,
610                 Gpdma1_ch4_tc = 24,
611                 Gpdma1_ch5_tc = 25,
612                 Gpdma1_ch6_tc = 26,
613                 Gpdma1_ch7_tc = 27,
614                 Tim2_trgo = 28,
615                 Adc4_awd1 = 29,
616             }
617 
618             private enum ChannelRegisters
619             {
620                 ChannelLinkedListBaseAddress = 0x50,
621                 ChannelFlagClear = 0x5C,
622                 ChannelStatus = 0x60,
623                 ChannelControl = 0x64,
624                 ChannelTransfer1 = 0x90,
625                 ChannelTransfer2 = 0x94,
626                 ChannelBlock1 = 0x98,
627                 ChannelSourceAddress = 0x9C,
628                 ChannelDestinationAddress = 0xA0,
629                 ChannelLinkedListAddress = 0xCC,
630             }
631         }
632 
633         private enum Registers : long
634         {
635             SecureConfiguration = 0x00, //SECCFGR
636             PrivilegedConfiguration = 0x04, //PRIVCFGR
637             ConfigurationLock = 0x08, //RCFGLOCKR
638             NonsecureMaskedInteruptStatus = 0x0C, //MISR
639             SecureMaskedInteruptStatus = 0x10, //SMISR
640 
641             Channel0LinkedListBaseAddress = 0x50, //CxLBAR
642             Channel0FlagClear = 0x5C, //CxFCR
643             Channel0Status = 0x60, //CxSR
644             Channel0Control = 0x64, //CxCR
645             Channel0Transfer1 = 0x90, //CxTR1
646             Channel0Transfer2 = 0x94, //CxTR2
647             Channel0Block1 = 0x98, //CxBR1
648             Channel0SourceAddress = 0x9C, //CxSAR
649             Channel0DestinationAddress = 0xA0, //CxDAR
650             Channel0LinkedListAddress = 0xCC, //CxLLR
651 
652             //needed for proper log output when accessed
653             Channel1LinkedListBaseAddress = 0xD0,
654             Channel1FlagClear = 0xDC,
655             Channel1Status = 0xE0,
656             Channel1Control = 0xE4,
657             Channel1Transfer1 = 0x110,
658             Channel1Transfer2 = 0x114,
659             Channel1Block1 = 0x118,
660             Channel1SourceAddress = 0x11C,
661             Channel1DestinationAddress = 0x120,
662             Channel1LinkedListAddress = 0x14C,
663 
664             Channel2LinkedListBaseAddress = 0x150,
665             Channel2FlagClear = 0x15C,
666             Channel2Status = 0x160,
667             Channel2Control = 0x164,
668             Channel2Transfer1 = 0x190,
669             Channel2Transfer2 = 0x194,
670             Channel2Block1 = 0x198,
671             Channel2SourceAddress = 0x19C,
672             Channel2DestinationAddress = 0x1A0,
673             Channel2LinkedListAddress = 0x1CC,
674 
675             Channel3LinkedListBaseAddress = 0x1D0,
676             Channel3FlagClear = 0x1DC,
677             Channel3Status = 0x1E0,
678             Channel3Control = 0x1E4,
679             Channel3Transfer1 = 0x210,
680             Channel3Transfer2 = 0x214,
681             Channel3Block1 = 0x218,
682             Channel3SourceAddress = 0x21C,
683             Channel3DestinationAddress = 0x220,
684             Channel3LinkedListAddress = 0x24C,
685 
686             Channel4LinkedListBaseAddress = 0x250,
687             Channel4FlagClear = 0x25C,
688             Channel4Status = 0x260,
689             Channel4Control = 0x264,
690             Channel4Transfer1 = 0x290,
691             Channel4Transfer2 = 0x294,
692             Channel4Block1 = 0x298,
693             Channel4SourceAddress = 0x29C,
694             Channel4DestinationAddress = 0x2A0,
695             Channel4LinkedListAddress = 0x2CC,
696 
697             Channel5LinkedListBaseAddress = 0x2D0,
698             Channel5FlagClear = 0x2DC,
699             Channel5Status = 0x2E0,
700             Channel5Control = 0x2E4,
701             Channel5Transfer1 = 0x310,
702             Channel5Transfer2 = 0x314,
703             Channel5Block1 = 0x318,
704             Channel5SourceAddress = 0x31C,
705             Channel5DestinationAddress = 0x320,
706             Channel5LinkedListAddress = 0x34C,
707 
708             Channel6LinkedListBaseAddress = 0x350,
709             Channel6FlagClear = 0x35C,
710             Channel6Status = 0x360,
711             Channel6Control = 0x364,
712             Channel6Transfer1 = 0x390,
713             Channel6Transfer2 = 0x394,
714             Channel6Block1 = 0x398,
715             Channel6SourceAddress = 0x39C,
716             Channel6DestinationAddress = 0x3A0,
717             Channel6LinkedListAddress = 0x3CC,
718 
719             Channel7LinkedListBaseAddress = 0x3D0,
720             Channel7FlagClear = 0x3DC,
721             Channel7Status = 0x3E0,
722             Channel7Control = 0x3E4,
723             Channel7Transfer1 = 0x410,
724             Channel7Transfer2 = 0x414,
725             Channel7Block1 = 0x418,
726             Channel7SourceAddress = 0x41C,
727             Channel7DestinationAddress = 0x420,
728             Channel7LinkedListAddress = 0x44C,
729         }
730     }
731 }
732