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