1 // 2 // Copyright (c) 2010-2023 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using System; 8 using System.Collections.Generic; 9 using System.Collections.ObjectModel; 10 using System.Linq; 11 using System.Runtime.InteropServices; 12 using Antmicro.Renode.Core; 13 using Antmicro.Renode.Core.Structure.Registers; 14 using Antmicro.Renode.Exceptions; 15 using Antmicro.Renode.Logging; 16 using Antmicro.Renode.Peripherals.Bus; 17 using Antmicro.Renode.Peripherals.Timers; 18 using Antmicro.Renode.Time; 19 using Antmicro.Renode.Utilities.Packets; 20 21 namespace Antmicro.Renode.Peripherals.DMA 22 { 23 public class EFR32MG12_LDMA : BasicDoubleWordPeripheral, IGPIOReceiver, IKnownSize 24 { EFR32MG12_LDMA(IMachine machine)25 public EFR32MG12_LDMA(IMachine machine) : base(machine) 26 { 27 engine = new DmaEngine(sysbus); 28 signals = new HashSet<int>(); 29 IRQ = new GPIO(); 30 channels = new Channel[NumberOfChannels]; 31 for(var i = 0; i < NumberOfChannels; ++i) 32 { 33 channels[i] = new Channel(this, i); 34 } 35 BuildRegisters(); 36 } 37 Reset()38 public override void Reset() 39 { 40 signals.Clear(); 41 foreach(var channel in channels) 42 { 43 channel.Reset(); 44 } 45 base.Reset(); 46 UpdateInterrupts(); 47 } 48 OnGPIO(int number, bool value)49 public void OnGPIO(int number, bool value) 50 { 51 var signal = (SignalSelect)(number & 0xf); 52 var source = (SourceSelect)((number >> 4) & 0x3f); 53 bool single = ((number >> 12) & 1) != 0; 54 if(!value) 55 { 56 signals.Remove(number); 57 return; 58 } 59 signals.Add(number); 60 for(var i = 0; i < NumberOfChannels; ++i) 61 { 62 if(single && channels[i].IgnoreSingleRequests) 63 { 64 continue; 65 } 66 if(channels[i].Signal == signal && channels[i].Source == source) 67 { 68 channels[i].StartFromSignal(); 69 } 70 } 71 } 72 73 public GPIO IRQ { get; } 74 75 public long Size => 0x400; 76 BuildRegisters()77 private void BuildRegisters() 78 { 79 Registers.Control.Define(this) 80 .WithTag("SYNCPRSSETEN", 0, 8) 81 .WithTag("SYNCPRSCLREN", 8, 8) 82 .WithReservedBits(16, 8) 83 .WithTag("NUMFIXED", 24, 3) 84 .WithReservedBits(27, 4) 85 .WithTaggedFlag("RESET", 31) 86 ; 87 Registers.Status.Define(this) 88 .WithTaggedFlag("ANYBUSY", 0) 89 .WithTaggedFlag("ANYREQ", 1) 90 .WithReservedBits(2, 1) 91 .WithTag("CHGRANT", 3, 3) 92 .WithReservedBits(6, 2) 93 .WithTag("CHERROR", 8, 3) 94 .WithReservedBits(11, 5) 95 .WithTag("FIFOLEVEL", 16, 5) 96 .WithReservedBits(21, 3) 97 .WithTag("CHNUM", 24, 5) 98 .WithReservedBits(29, 3) 99 ; 100 Registers.SynchronizationTrigger.Define(this) 101 .WithTag("SYNCTRIG", 0, 8) 102 .WithReservedBits(8, 24) 103 ; 104 Registers.ChannelEnable.Define(this) 105 .WithFlags(0, 8, writeCallback: (i, _, value) => channels[i].Enabled = value, valueProviderCallback: (i, _) => channels[i].Enabled, name: "CHEN") 106 .WithReservedBits(8, 24) 107 ; 108 Registers.ChannelBusy.Define(this) 109 .WithTag("BUSY", 0, 8) 110 .WithReservedBits(8, 24) 111 ; 112 Registers.ChannelDone.Define(this) 113 .WithFlags(0, 8, writeCallback: (i, _, value) => channels[i].Done = value, valueProviderCallback: (i, _) => channels[i].Done, name: "CHDONE") 114 .WithReservedBits(8, 24) 115 ; 116 Registers.ChannelDebugHalt.Define(this) 117 .WithTag("DBGHALT", 0, 8) 118 .WithReservedBits(8, 24) 119 ; 120 Registers.ChannelSoftwareTransferRequest.Define(this) 121 .WithFlags(0, 8, FieldMode.Set, writeCallback: (i, _, value) => { if(value) channels[i].StartTransfer(); }, name: "SWREQ") 122 .WithReservedBits(8, 24) 123 ; 124 Registers.ChannelRequestDisable.Define(this) 125 .WithFlags(0, 8, writeCallback: (i, _, value) => channels[i].RequestDisable = value, valueProviderCallback: (i, _) => channels[i].RequestDisable, name: "REQDIS") 126 .WithReservedBits(8, 24) 127 ; 128 Registers.ChannelRequestsPending.Define(this) 129 .WithTag("REQPEND", 0, 8) 130 .WithReservedBits(8, 24) 131 ; 132 Registers.ChannelLinkLoad.Define(this) 133 .WithFlags(0, 8, FieldMode.Set, writeCallback: (i, _, value) => { if(value) channels[i].LinkLoad(); }, name: "LINKLOAD") 134 .WithReservedBits(8, 24) 135 ; 136 Registers.ChannelRequestClear.Define(this) 137 .WithTag("REQCLEAR", 0, 8) 138 .WithReservedBits(8, 24) 139 ; 140 Registers.InterruptFlag.Define(this) 141 .WithFlags(0, 8, FieldMode.Read, valueProviderCallback: (i, _) => channels[i].DoneInterrupt, name: "DONE") 142 .WithReservedBits(8, 23) 143 .WithTaggedFlag("ERROR", 31) 144 .WithWriteCallback((_, __) => UpdateInterrupts()) 145 ; 146 Registers.InterruptFlagSet.Define(this) 147 .WithFlags(0, 8, FieldMode.Set, writeCallback: (i, _, value) => channels[i].DoneInterrupt |= value, name: "DONE") 148 .WithReservedBits(8, 23) 149 .WithTaggedFlag("ERROR", 31) 150 .WithWriteCallback((_, __) => UpdateInterrupts()) 151 ; 152 Registers.InterruptFlagClear.Define(this) 153 .WithFlags(0, 8, FieldMode.WriteOneToClear, writeCallback: (i, _, value) => channels[i].DoneInterrupt &= !value, name: "DONE") 154 .WithReservedBits(8, 23) 155 .WithTaggedFlag("ERROR", 31) 156 .WithWriteCallback((_, __) => UpdateInterrupts()) 157 ; 158 Registers.InterruptEnable.Define(this) 159 .WithFlags(0, 8, writeCallback: (i, _, value) => channels[i].DoneInterruptEnable = value, valueProviderCallback: (i, _) => channels[i].DoneInterruptEnable, name: "DONE") 160 .WithReservedBits(8, 23) 161 .WithTaggedFlag("ERROR", 31) 162 .WithWriteCallback((_, __) => UpdateInterrupts()) 163 ; 164 165 var channelDelta = (uint)((long)Registers.Channel1PeripheralRequestSelect - (long)Registers.Channel0PeripheralRequestSelect); 166 Registers.Channel0PeripheralRequestSelect.BindMany(this, NumberOfChannels, i => channels[i].PeripheralRequestSelectRegister, channelDelta); 167 Registers.Channel0Configuration.BindMany(this, NumberOfChannels, i => channels[i].ConfigurationRegister, channelDelta); 168 Registers.Channel0LoopCounter.BindMany(this, NumberOfChannels, i => channels[i].LoopCounterRegister, channelDelta); 169 Registers.Channel0DescriptorControlWord.BindMany(this, NumberOfChannels, i => channels[i].DescriptorControlWordRegister, channelDelta); 170 Registers.Channel0DescriptorSourceDataAddress.BindMany(this, NumberOfChannels, i => channels[i].DescriptorSourceDataAddressRegister, channelDelta); 171 Registers.Channel0DescriptorDestinationDataAddress.BindMany(this, NumberOfChannels, i => channels[i].DescriptorDestinationDataAddressRegister, channelDelta); 172 Registers.Channel0DescriptorLinkStructureAddress.BindMany(this, NumberOfChannels, i => channels[i].DescriptorLinkStructureAddressRegister, channelDelta); 173 } 174 UpdateInterrupts()175 private void UpdateInterrupts() 176 { 177 this.Log(LogLevel.Debug, "Interrupt set for channels: {0}", String.Join(", ", 178 channels 179 .Where(channel => channel.IRQ) 180 .Select(channel => channel.Index) 181 )); 182 IRQ.Set(channels.Any(channel => channel.IRQ)); 183 } 184 185 private readonly DmaEngine engine; 186 private readonly HashSet<int> signals; 187 private readonly Channel[] channels; 188 189 private const int NumberOfChannels = 8; 190 191 private enum SignalSelect 192 { 193 // if SOURCESEL is None 194 // Off = 0bxxxx, 195 // if SOURCESEL is PRS 196 PRSRequest0 = 0b0000, 197 PRSRequest1 = 0b0001, 198 // if SOURCESEL is ADC0 199 ADC0Single = 0b0000, 200 ADC0Scan = 0b0001, 201 // if SOURCESEL is VDAC0 202 VDAC0CH0 = 0b0000, 203 VDAC0CH1 = 0b0001, 204 // if SOURCESEL is USART0 205 USART0RxDataAvailable = 0b0000, 206 USART0TxBufferLow = 0b0001, 207 USART0TxEmpty = 0b0010, 208 // if SOURCESEL is USART1 209 USART1RxDataAvailable = 0b0000, 210 USART1TxBufferLow = 0b0001, 211 USART1TxEmpty = 0b0010, 212 USART1RxDataAvailableRight = 0b0011, 213 USART1TxBufferLowRight = 0b0100, 214 // if SOURCESEL is USART2 215 USART2RxDataAvailable = 0b0000, 216 USART2TxBufferLow = 0b0001, 217 USART2TxEmpty = 0b0010, 218 // if SOURCESEL is USART3 219 USART3RxDataAvailable = 0b0000, 220 USART3TxBufferLow = 0b0001, 221 USART3TxEmpty = 0b0010, 222 USART3RxDataAvailableRight = 0b0011, 223 USART3TxBufferLowRight = 0b0100, 224 // if SOURCESEL is LEUART0 225 LEUART0RxDataAvailable = 0b0000, 226 LEUART0TxBufferLow = 0b0001, 227 LEUART0TxEmpty = 0b0010, 228 // if SOURCESEL is I2C0 229 I2C0RxDataAvailable = 0b0000, 230 I2C0TxBufferLow = 0b0001, 231 // if SOURCESEL is I2C1 232 I2C1RxDataAvailable = 0b0000, 233 I2C1TxBufferLow = 0b0001, 234 // if SOURCESEL is TIMER0 235 TIMER0UnderflowOverflow = 0b0000, 236 TIMER0CaptureCompare0 = 0b0001, 237 TIMER0CaptureCompare1 = 0b0010, 238 TIMER0CaptureCompare2 = 0b0011, 239 // if SOURCESEL is TIMER1 240 TIMER1UnderflowOverflow = 0b0000, 241 TIMER1CaptureCompare0 = 0b0001, 242 TIMER1CaptureCompare1 = 0b0010, 243 TIMER1CaptureCompare2 = 0b0011, 244 TIMER1CaptureCompare3 = 0b0100, 245 // if SOURCESEL is WTIMER0 246 WTIMER0UnderflowOverflow = 0b0000, 247 WTIMER0CaptureCompare0 = 0b0001, 248 WTIMER0CaptureCompare1 = 0b0010, 249 WTIMER0CaptureCompare2 = 0b0011, 250 // if SOURCESEL is WTIMER1 251 WTIMER1UnderflowOverflow = 0b0000, 252 WTIMER1CaptureCompare0 = 0b0001, 253 WTIMER1CaptureCompare1 = 0b0010, 254 WTIMER1CaptureCompare2 = 0b0011, 255 WTIMER1CaptureCompare3 = 0b0100, 256 // if SOURCESEL is PROTIMER 257 PROTIMERPreCounterOverflow = 0b0000, 258 PROTIMERBaseCounterOverflow = 0b0001, 259 PROTIMERWrapCounterOverflow = 0b0010, 260 PROTIMERCaptureCompare0 = 0b0011, 261 PROTIMERCaptureCompare1 = 0b0100, 262 PROTIMERCaptureCompare2 = 0b0101, 263 PROTIMERCaptureCompare3 = 0b0110, 264 PROTIMERCaptureCompare4 = 0b0111, 265 // if SOURCESEL is MODEM 266 MODEMDebug = 0b0000, 267 // if SOURCESEL is AGC 268 AGCReceivedSignalStrengthIndicator = 0b0000, 269 // if SOURCESEL is MSC 270 MSCWriteDataReady = 0b0000, 271 // if SOURCESEL is CRYPTO0 272 CRYPTO0Data0Write = 0b0000, 273 CRYPTO0Data0XorWrite = 0b0001, 274 CRYPTO0Data0Read = 0b0010, 275 CRYPTO0Data1Write = 0b0011, 276 CRYPTO0Data1Read = 0b0100, 277 // if SOURCESEL is CSEN 278 CSENData = 0b0000, 279 CSENBaseline = 0b0001, 280 // if SOURCESEL is LESENSE 281 LESENSEBufferDataAvailable = 0b0000, 282 // if SOURCESEL is CRYPTO1 283 CRYPTO1Data0Write = 0b0000, 284 CRYPTO1Data0XorWrite = 0b0001, 285 CRYPTO1Data0Read = 0b0010, 286 CRYPTO1Data1Write = 0b0011, 287 CRYPTO1Data1Read = 0b0100, 288 } 289 290 private enum SourceSelect 291 { 292 None = 0b000000, 293 PRS = 0b000001, 294 ADC0 = 0b001000, 295 VDAC0 = 0b001010, 296 USART0 = 0b001100, 297 USART1 = 0b001101, 298 USART2 = 0b001110, 299 USART3 = 0b001111, 300 LEUART0 = 0b010000, 301 I2C0 = 0b010100, 302 I2C1 = 0b010101, 303 TIMER0 = 0b011000, 304 TIMER1 = 0b011001, 305 WTIMER0 = 0b011010, 306 WTIMER1 = 0b011011, 307 PROTIMER = 0b100100, 308 MODEM = 0b100110, 309 AGC = 0b100111, 310 MSC = 0b110000, 311 CRYPTO0 = 0b110001, 312 CSEN = 0b110010, 313 LESENSE = 0b110011, 314 CRYPTO1 = 0b110100, 315 } 316 317 private enum Registers 318 { 319 Control = 0x000, 320 Status = 0x004, 321 SynchronizationTrigger = 0x008, 322 ChannelEnable = 0x020, 323 ChannelBusy = 0x024, 324 ChannelDone = 0x028, 325 ChannelDebugHalt = 0x02C, 326 ChannelSoftwareTransferRequest = 0x030, 327 ChannelRequestDisable = 0x034, 328 ChannelRequestsPending = 0x038, 329 ChannelLinkLoad = 0x03C, 330 ChannelRequestClear = 0x040, 331 InterruptFlag = 0x060, 332 InterruptFlagSet = 0x064, 333 InterruptFlagClear = 0x068, 334 InterruptEnable = 0x06C, 335 Channel0PeripheralRequestSelect = 0x080, 336 Channel0Configuration = 0x084, 337 Channel0LoopCounter = 0x088, 338 Channel0DescriptorControlWord = 0x08C, 339 Channel0DescriptorSourceDataAddress = 0x090, 340 Channel0DescriptorDestinationDataAddress = 0x094, 341 Channel0DescriptorLinkStructureAddress = 0x098, 342 Channel1PeripheralRequestSelect = 0x0B0, 343 Channel1Configuration = 0x0B4, 344 Channel1LoopCounter = 0x0B8, 345 Channel1DescriptorControlWord = 0x0BC, 346 Channel1DescriptorSourceDataAddress = 0x0C0, 347 Channel1DescriptorDestinationDataAddress = 0x0C4, 348 Channel1DescriptorLinkStructureAddress = 0x0C8, 349 Channel2PeripheralRequestSelect = 0x0E0, 350 Channel2Configuration = 0x0E4, 351 Channel2LoopCounter = 0x0E8, 352 Channel2DescriptorControlWord = 0x0EC, 353 Channel2DescriptorSourceDataAddress = 0x0F0, 354 Channel2DescriptorDestinationDataAddress = 0x0F4, 355 Channel2DescriptorLinkStructureAddress = 0x0F8, 356 Channel3PeripheralRequestSelect = 0x110, 357 Channel3Configuration = 0x114, 358 Channel3LoopCounter = 0x118, 359 Channel3DescriptorControlWord = 0x11C, 360 Channel3DescriptorSourceDataAddress = 0x120, 361 Channel3DescriptorDestinationDataAddress = 0x124, 362 Channel3DescriptorLinkStructureAddress = 0x128, 363 Channel4PeripheralRequestSelect = 0x140, 364 Channel4Configuration = 0x144, 365 Channel4LoopCounter = 0x148, 366 Channel4DescriptorControlWord = 0x14C, 367 Channel4DescriptorSourceDataAddress = 0x150, 368 Channel4DescriptorDestinationDataAddress = 0x154, 369 Channel4DescriptorLinkStructureAddress = 0x158, 370 Channel5PeripheralRequestSelect = 0x170, 371 Channel5Configuration = 0x174, 372 Channel5LoopCounter = 0x178, 373 Channel5DescriptorControlWord = 0x17C, 374 Channel5DescriptorSourceDataAddress = 0x180, 375 Channel5DescriptorDestinationDataAddress = 0x184, 376 Channel5DescriptorLinkStructureAddress = 0x188, 377 Channel6PeripheralRequestSelect = 0x1A0, 378 Channel6Configuration = 0x1A4, 379 Channel6LoopCounter = 0x1A8, 380 Channel6DescriptorControlWord = 0x1AC, 381 Channel6DescriptorSourceDataAddress = 0x1B0, 382 Channel6DescriptorDestinationDataAddress = 0x1B4, 383 Channel6DescriptorLinkStructureAddress = 0x1B8, 384 Channel7PeripheralRequestSelect = 0x1D0, 385 Channel7Configuration = 0x1D4, 386 Channel7LoopCounter = 0x1D8, 387 Channel7DescriptorControlWord = 0x1DC, 388 Channel7DescriptorSourceDataAddress = 0x1E0, 389 Channel7DescriptorDestinationDataAddress = 0x1E4, 390 Channel7DescriptorLinkStructureAddress = 0x1E8, 391 } 392 393 private class Channel 394 { Channel(EFR32MG12_LDMA parent, int index)395 public Channel(EFR32MG12_LDMA parent, int index) 396 { 397 this.parent = parent; 398 Index = index; 399 descriptor = default(Descriptor); 400 401 PeripheralRequestSelectRegister = new DoubleWordRegister(parent) 402 .WithEnumField<DoubleWordRegister, SignalSelect>(0, 4, out signalSelect, name: "SIGSEL") 403 .WithReservedBits(4, 12) 404 .WithEnumField<DoubleWordRegister, SourceSelect>(16, 6, out sourceSelect, name: "SOURCESEL") 405 .WithReservedBits(22, 10) 406 .WithWriteCallback((_, __) => 407 { 408 if(ShouldPullSignal) 409 { 410 pullTimer.Enabled = true; 411 } 412 }) 413 ; 414 ConfigurationRegister = new DoubleWordRegister(parent) 415 .WithReservedBits(0, 16) 416 .WithEnumField<DoubleWordRegister, ArbitrationSlotNumberMode>(16, 2, out arbitrationSlotNumberSelect, name: "ARBSLOTS") 417 .WithReservedBits(18, 2) 418 .WithEnumField<DoubleWordRegister, Sign>(20, 1, out sourceAddressIncrementSign, name: "SRCINCSIGN") 419 .WithEnumField<DoubleWordRegister, Sign>(21, 1, out destinationAddressIncrementSign, name: "DSTINCSIGN") 420 .WithReservedBits(22, 10) 421 ; 422 LoopCounterRegister = new DoubleWordRegister(parent) 423 .WithValueField(0, 8, out loopCounter, name: "LOOPCNT") 424 .WithReservedBits(8, 24) 425 ; 426 DescriptorControlWordRegister = new DoubleWordRegister(parent) 427 .WithEnumField<DoubleWordRegister, StructureType>(0, 2, FieldMode.Read, 428 valueProviderCallback: _ => descriptor.structureType, 429 name: "STRUCTTYPE") 430 .WithReservedBits(2, 1) 431 .WithFlag(3, FieldMode.Set, 432 writeCallback: (_, value) => descriptor.structureTransferRequest = value, 433 name: "STRUCTREQ") 434 .WithValueField(4, 11, 435 writeCallback: (_, value) => descriptor.transferCount = (ushort)value, 436 valueProviderCallback: _ => descriptor.transferCount, 437 name: "XFERCNT") 438 .WithFlag(15, 439 writeCallback: (_, value) => descriptor.byteSwap = value, 440 valueProviderCallback: _ => descriptor.byteSwap, 441 name: "BYTESWAP") 442 .WithEnumField<DoubleWordRegister, BlockSizeMode>(16, 4, 443 writeCallback: (_, value) => descriptor.blockSize = value, 444 valueProviderCallback: _ => descriptor.blockSize, 445 name: "BLOCKSIZE") 446 .WithFlag(20, 447 writeCallback: (_, value) => descriptor.operationDoneInterruptFlagSetEnable = value, 448 valueProviderCallback: _ => descriptor.operationDoneInterruptFlagSetEnable, 449 name: "DONEIFSEN") 450 .WithEnumField<DoubleWordRegister, RequestTransferMode>(21, 1, 451 writeCallback: (_, value) => descriptor.requestTransferModeSelect = value, 452 valueProviderCallback: _ => descriptor.requestTransferModeSelect, 453 name: "REQMODE") 454 .WithFlag(22, 455 writeCallback: (_, value) => descriptor.decrementLoopCount = value, 456 valueProviderCallback: _ => descriptor.decrementLoopCount, 457 name: "DECLOOPCNT") 458 .WithFlag(23, 459 writeCallback: (_, value) => descriptor.ignoreSingleRequests = value, 460 valueProviderCallback: _ => descriptor.ignoreSingleRequests, 461 name: "IGNORESREQ") 462 .WithEnumField<DoubleWordRegister, IncrementMode>(24, 2, 463 writeCallback: (_, value) => descriptor.sourceIncrement = value, 464 valueProviderCallback: _ => descriptor.sourceIncrement, 465 name: "SRCINC") 466 .WithEnumField<DoubleWordRegister, SizeMode>(26, 2, 467 writeCallback: (_, value) => descriptor.size = value, 468 valueProviderCallback: _ => descriptor.size, 469 name: "SIZE") 470 .WithEnumField<DoubleWordRegister, IncrementMode>(28, 2, 471 writeCallback: (_, value) => descriptor.destinationIncrement = value, 472 valueProviderCallback: _ => descriptor.destinationIncrement, 473 name: "DSTINC") 474 .WithEnumField<DoubleWordRegister, AddressingMode>(30, 1, FieldMode.Read, 475 valueProviderCallback: _ => descriptor.sourceAddressingMode, 476 name: "SRCMODE") 477 .WithEnumField<DoubleWordRegister, AddressingMode>(31, 1, FieldMode.Read, 478 valueProviderCallback: _ => descriptor.destinationAddressingMode, 479 name: "DSTMODE") 480 .WithChangeCallback((_, __) => { if(descriptor.structureTransferRequest) LinkLoad(); }) 481 ; 482 DescriptorSourceDataAddressRegister = new DoubleWordRegister(parent) 483 .WithValueField(0, 32, 484 writeCallback: (_, value) => descriptor.sourceAddress = (uint)value, 485 valueProviderCallback: _ => descriptor.sourceAddress, 486 name: "SRCADDR") 487 ; 488 DescriptorDestinationDataAddressRegister = new DoubleWordRegister(parent) 489 .WithValueField(0, 32, 490 writeCallback: (_, value) => descriptor.destinationAddress = (uint)value, 491 valueProviderCallback: _ => descriptor.destinationAddress, 492 name: "DSTADDR") 493 ; 494 DescriptorLinkStructureAddressRegister = new DoubleWordRegister(parent) 495 .WithEnumField<DoubleWordRegister, AddressingMode>(0, 1, FieldMode.Read, 496 valueProviderCallback: _ => descriptor.linkMode, 497 name: "LINKMODE") 498 .WithFlag(1, 499 writeCallback: (_, value) => descriptor.link = value, 500 valueProviderCallback: _ => descriptor.link, 501 name: "LINK") 502 .WithValueField(2, 30, 503 writeCallback: (_, value) => descriptor.linkAddress = (uint)value, 504 valueProviderCallback: _ => descriptor.linkAddress, 505 name: "LINKADDR") 506 ; 507 508 pullTimer = new LimitTimer(parent.machine.ClockSource, 1000000, null, $"pullTimer-{Index}", 15, Direction.Ascending, false, WorkMode.Periodic, true, true); 509 pullTimer.LimitReached += delegate 510 { 511 if(!RequestDisable) 512 { 513 StartTransferInner(); 514 } 515 if(!SignalIsOn || !ShouldPullSignal) 516 { 517 pullTimer.Enabled = false; 518 } 519 }; 520 } 521 StartFromSignal()522 public void StartFromSignal() 523 { 524 if(!RequestDisable) 525 { 526 StartTransfer(); 527 } 528 } 529 LinkLoad()530 public void LinkLoad() 531 { 532 LoadDescriptor(); 533 if(descriptor.structureTransferRequest || SignalIsOn) 534 { 535 StartTransfer(); 536 } 537 } 538 StartTransfer()539 public void StartTransfer() 540 { 541 if(ShouldPullSignal) 542 { 543 pullTimer.Enabled = true; 544 } 545 else 546 { 547 StartTransferInner(); 548 } 549 } 550 Reset()551 public void Reset() 552 { 553 descriptor = default(Descriptor); 554 pullTimer.Reset(); 555 DoneInterrupt = false; 556 DoneInterruptEnable = false; 557 descriptorAddress = null; 558 requestDisable = false; 559 enabled = false; 560 done = false; 561 } 562 563 public int Index { get; } 564 565 public SignalSelect Signal => signalSelect.Value; 566 public SourceSelect Source => sourceSelect.Value; 567 public bool IgnoreSingleRequests => descriptor.ignoreSingleRequests; 568 569 public bool DoneInterrupt { get; set; } 570 public bool DoneInterruptEnable { get; set; } 571 public bool IRQ => DoneInterrupt && DoneInterruptEnable; 572 573 public DoubleWordRegister PeripheralRequestSelectRegister { get; } 574 public DoubleWordRegister ConfigurationRegister { get; } 575 public DoubleWordRegister LoopCounterRegister { get; } 576 public DoubleWordRegister DescriptorControlWordRegister { get; } 577 public DoubleWordRegister DescriptorSourceDataAddressRegister { get; } 578 public DoubleWordRegister DescriptorDestinationDataAddressRegister { get; } 579 public DoubleWordRegister DescriptorLinkStructureAddressRegister { get; } 580 581 public bool Enabled 582 { 583 get 584 { 585 return enabled; 586 } 587 set 588 { 589 if(enabled == value) 590 { 591 return; 592 } 593 enabled = value; 594 if(enabled) 595 { 596 Done = false; 597 StartTransfer(); 598 } 599 } 600 } 601 602 public bool Done 603 { 604 get 605 { 606 return done; 607 } 608 609 set 610 { 611 done = value; 612 DoneInterrupt |= done && descriptor.operationDoneInterruptFlagSetEnable; 613 } 614 } 615 616 public bool RequestDisable 617 { 618 get 619 { 620 return requestDisable; 621 } 622 623 set 624 { 625 if(requestDisable && !value) 626 { 627 requestDisable = value; 628 if(SignalIsOn) 629 { 630 StartTransfer(); 631 } 632 } 633 requestDisable = value; 634 } 635 } 636 StartTransferInner()637 private void StartTransferInner() 638 { 639 if(isInProgress || Done) 640 { 641 return; 642 } 643 644 isInProgress = true; 645 var loaded = false; 646 do 647 { 648 loaded = false; 649 Transfer(); 650 if(Done && descriptor.link) 651 { 652 loaded = true; 653 LoadDescriptor(); 654 } 655 } 656 while((descriptor.structureTransferRequest && loaded) || (!Done && SignalIsOn)); 657 isInProgress = false; 658 } 659 LoadDescriptor()660 private void LoadDescriptor() 661 { 662 var address = LinkStructureAddress; 663 if(descriptorAddress.HasValue && descriptor.linkMode == AddressingMode.Relative) 664 { 665 address += descriptorAddress.Value; 666 } 667 var data = parent.sysbus.ReadBytes(address, DescriptorSize); 668 descriptorAddress = address; 669 descriptor = Packet.Decode<Descriptor>(data); 670 #if DEBUG 671 parent.Log(LogLevel.Noisy, "Channel #{0} data {1}", Index, BitConverter.ToString(data)); 672 parent.Log(LogLevel.Debug, "Channel #{0} Loaded {1}", Index, descriptor.PrettyString); 673 #endif 674 } 675 Transfer()676 private void Transfer() 677 { 678 switch(descriptor.structureType) 679 { 680 case StructureType.Transfer: 681 var request = new Request( 682 source: new Place(descriptor.sourceAddress), 683 destination: new Place(descriptor.destinationAddress), 684 size: Bytes, 685 readTransferType: SizeAsTransferType, 686 writeTransferType: SizeAsTransferType, 687 sourceIncrementStep: SourceIncrement, 688 destinationIncrementStep: DestinationIncrement 689 ); 690 parent.Log(LogLevel.Debug, "Channel #{0} Performing Transfer", Index); 691 parent.engine.IssueCopy(request); 692 if(descriptor.requestTransferModeSelect == RequestTransferMode.Block) 693 { 694 var blockSizeMultiplier = Math.Min(TransferCount, BlockSizeMultiplier); 695 if(blockSizeMultiplier == TransferCount) 696 { 697 Done = true; 698 descriptor.transferCount = 0; 699 } 700 else 701 { 702 descriptor.transferCount -= blockSizeMultiplier; 703 } 704 descriptor.sourceAddress += SourceIncrement * blockSizeMultiplier; 705 descriptor.destinationAddress += DestinationIncrement * blockSizeMultiplier; 706 } 707 else 708 { 709 Done = true; 710 } 711 break; 712 case StructureType.Synchronize: 713 parent.Log(LogLevel.Warning, "Channel #{0} Synchronize is not implemented.", Index); 714 break; 715 case StructureType.Write: 716 parent.Log(LogLevel.Warning, "Channel #{0} Write is not implemented.", Index); 717 break; 718 default: 719 parent.Log(LogLevel.Error, "Channel #{0} Invalid structure type value. No action was performed.", Index); 720 return; 721 } 722 parent.UpdateInterrupts(); 723 } 724 725 private bool ShouldPullSignal 726 { 727 get 728 { 729 // if this returns true for the selected source and signal 730 // then the signal will be periodically pulled instead of waiting 731 // for an rising edge 732 switch(Source) 733 { 734 case SourceSelect.None: 735 return false; 736 case SourceSelect.PRS: 737 switch(Signal) 738 { 739 case SignalSelect.PRSRequest0: 740 case SignalSelect.PRSRequest1: 741 return false; 742 default: 743 goto default; 744 } 745 case SourceSelect.ADC0: 746 switch(Signal) 747 { 748 case SignalSelect.ADC0Single: 749 case SignalSelect.ADC0Scan: 750 return false; 751 default: 752 goto default; 753 } 754 case SourceSelect.VDAC0: 755 switch(Signal) 756 { 757 case SignalSelect.VDAC0CH0: 758 case SignalSelect.VDAC0CH1: 759 return false; 760 default: 761 goto default; 762 } 763 case SourceSelect.USART0: 764 case SourceSelect.USART2: 765 case SourceSelect.LEUART0: 766 switch(Signal) 767 { 768 case SignalSelect.USART0RxDataAvailable: 769 return false; 770 case SignalSelect.USART0TxBufferLow: 771 case SignalSelect.USART0TxEmpty: 772 return true; 773 default: 774 goto default; 775 } 776 case SourceSelect.USART1: 777 case SourceSelect.USART3: 778 switch(Signal) 779 { 780 case SignalSelect.USART1RxDataAvailable: 781 case SignalSelect.USART1RxDataAvailableRight: 782 return false; 783 case SignalSelect.USART1TxBufferLow: 784 case SignalSelect.USART1TxEmpty: 785 case SignalSelect.USART1TxBufferLowRight: 786 return true; 787 default: 788 goto default; 789 } 790 case SourceSelect.I2C0: 791 case SourceSelect.I2C1: 792 switch(Signal) 793 { 794 case SignalSelect.I2C0RxDataAvailable: 795 return false; 796 case SignalSelect.I2C0TxBufferLow: 797 return true; 798 default: 799 goto default; 800 } 801 case SourceSelect.TIMER0: 802 case SourceSelect.WTIMER0: 803 switch(Signal) 804 { 805 case SignalSelect.TIMER0UnderflowOverflow: 806 case SignalSelect.TIMER0CaptureCompare0: 807 case SignalSelect.TIMER0CaptureCompare1: 808 case SignalSelect.TIMER0CaptureCompare2: 809 return false; 810 default: 811 goto default; 812 } 813 case SourceSelect.TIMER1: 814 case SourceSelect.WTIMER1: 815 switch(Signal) 816 { 817 case SignalSelect.TIMER1UnderflowOverflow: 818 case SignalSelect.TIMER1CaptureCompare0: 819 case SignalSelect.TIMER1CaptureCompare1: 820 case SignalSelect.TIMER1CaptureCompare2: 821 case SignalSelect.TIMER1CaptureCompare3: 822 return false; 823 default: 824 goto default; 825 } 826 case SourceSelect.PROTIMER: 827 switch(Signal) 828 { 829 case SignalSelect.PROTIMERPreCounterOverflow: 830 case SignalSelect.PROTIMERBaseCounterOverflow: 831 case SignalSelect.PROTIMERWrapCounterOverflow: 832 case SignalSelect.PROTIMERCaptureCompare0: 833 case SignalSelect.PROTIMERCaptureCompare1: 834 case SignalSelect.PROTIMERCaptureCompare2: 835 case SignalSelect.PROTIMERCaptureCompare3: 836 case SignalSelect.PROTIMERCaptureCompare4: 837 return false; 838 default: 839 goto default; 840 } 841 case SourceSelect.MODEM: 842 switch(Signal) 843 { 844 case SignalSelect.MODEMDebug: 845 return false; 846 default: 847 goto default; 848 } 849 case SourceSelect.AGC: 850 switch(Signal) 851 { 852 case SignalSelect.AGCReceivedSignalStrengthIndicator: 853 return false; 854 default: 855 goto default; 856 } 857 case SourceSelect.MSC: 858 switch(Signal) 859 { 860 case SignalSelect.MSCWriteDataReady: 861 return false; 862 default: 863 goto default; 864 } 865 case SourceSelect.CRYPTO0: 866 case SourceSelect.CRYPTO1: 867 switch(Signal) 868 { 869 case SignalSelect.CRYPTO0Data0Write: 870 case SignalSelect.CRYPTO0Data0XorWrite: 871 case SignalSelect.CRYPTO0Data0Read: 872 case SignalSelect.CRYPTO0Data1Write: 873 case SignalSelect.CRYPTO0Data1Read: 874 return false; 875 default: 876 goto default; 877 } 878 case SourceSelect.CSEN: 879 switch(Signal) 880 { 881 case SignalSelect.CSENData: 882 case SignalSelect.CSENBaseline: 883 return false; 884 default: 885 goto default; 886 } 887 case SourceSelect.LESENSE: 888 switch(Signal) 889 { 890 case SignalSelect.LESENSEBufferDataAvailable: 891 return false; 892 default: 893 goto default; 894 } 895 default: 896 parent.Log(LogLevel.Error, "Channel #{0} Invalid Source (0x{1:X}) and Signal (0x{2:X}) pair.", Index, Source, Signal); 897 return false; 898 } 899 } 900 } 901 902 private uint BlockSizeMultiplier 903 { 904 get 905 { 906 switch(descriptor.blockSize) 907 { 908 case BlockSizeMode.Unit1: 909 case BlockSizeMode.Unit2: 910 return 1u << (byte)descriptor.blockSize; 911 case BlockSizeMode.Unit3: 912 return 3; 913 case BlockSizeMode.Unit4: 914 return 4; 915 case BlockSizeMode.Unit6: 916 return 6; 917 case BlockSizeMode.Unit8: 918 return 8; 919 case BlockSizeMode.Unit16: 920 return 16; 921 case BlockSizeMode.Unit32: 922 case BlockSizeMode.Unit64: 923 case BlockSizeMode.Unit128: 924 case BlockSizeMode.Unit256: 925 case BlockSizeMode.Unit512: 926 case BlockSizeMode.Unit1024: 927 return 1u << ((byte)descriptor.blockSize - 4); 928 case BlockSizeMode.All: 929 return TransferCount; 930 default: 931 parent.Log(LogLevel.Warning, "Channel #{0} Invalid Block Size Mode value.", Index); 932 return 0; 933 } 934 } 935 } 936 937 private bool SignalIsOn 938 { 939 get 940 { 941 var number = ((int)Source << 4) | (int)Signal; 942 return parent.signals.Contains(number) || (!IgnoreSingleRequests && parent.signals.Contains(number | 1 << 12)); 943 } 944 } 945 946 private uint TransferCount => (uint)descriptor.transferCount + 1; 947 private ulong LinkStructureAddress => (ulong)descriptor.linkAddress << 2; 948 949 private uint SourceIncrement => descriptor.sourceIncrement == IncrementMode.None ? 0u : ((1u << (byte)descriptor.size) << (byte)descriptor.sourceIncrement); 950 private uint DestinationIncrement => descriptor.destinationIncrement == IncrementMode.None ? 0u : ((1u << (byte)descriptor.size) << (byte)descriptor.destinationIncrement); 951 private TransferType SizeAsTransferType => (TransferType)(1 << (byte)descriptor.size); 952 private int Bytes => (int)(descriptor.requestTransferModeSelect == RequestTransferMode.All ? TransferCount : Math.Min(TransferCount, BlockSizeMultiplier)) << (byte)descriptor.size; 953 954 private Descriptor descriptor; 955 private ulong? descriptorAddress; 956 private bool requestDisable; 957 private bool enabled; 958 private bool done; 959 960 // Accesses to sysubs may cause changes in signals, but we should ignore those during active transaction 961 private bool isInProgress; 962 963 private IEnumRegisterField<SignalSelect> signalSelect; 964 private IEnumRegisterField<SourceSelect> sourceSelect; 965 private IEnumRegisterField<ArbitrationSlotNumberMode> arbitrationSlotNumberSelect; 966 private IEnumRegisterField<Sign> sourceAddressIncrementSign; 967 private IEnumRegisterField<Sign> destinationAddressIncrementSign; 968 private IValueRegisterField loopCounter; 969 970 private readonly EFR32MG12_LDMA parent; 971 private readonly LimitTimer pullTimer; 972 973 protected readonly int DescriptorSize = Packet.CalculateLength<Descriptor>(); 974 975 private enum ArbitrationSlotNumberMode 976 { 977 One = 0, 978 Two = 1, 979 Four = 2, 980 Eight = 3, 981 } 982 983 private enum Sign 984 { 985 Positive = 0, 986 Negative = 1, 987 } 988 989 protected enum StructureType : uint 990 { 991 Transfer = 0, 992 Synchronize = 1, 993 Write = 2, 994 } 995 996 protected enum BlockSizeMode : uint 997 { 998 Unit1 = 0, 999 Unit2 = 1, 1000 Unit3 = 2, 1001 Unit4 = 3, 1002 Unit6 = 4, 1003 Unit8 = 5, 1004 Unit16 = 7, 1005 Unit32 = 9, 1006 Unit64 = 10, 1007 Unit128 = 11, 1008 Unit256 = 12, 1009 Unit512 = 13, 1010 Unit1024 = 14, 1011 All = 15, 1012 } 1013 1014 protected enum RequestTransferMode : uint 1015 { 1016 Block = 0, 1017 All = 1, 1018 } 1019 1020 protected enum IncrementMode : uint 1021 { 1022 One = 0, 1023 Two = 1, 1024 Four = 2, 1025 None = 3, 1026 } 1027 1028 protected enum SizeMode : uint 1029 { 1030 Byte = 0, 1031 HalfWord = 1, 1032 Word = 2, 1033 } 1034 1035 protected enum AddressingMode : uint 1036 { 1037 Absolute = 0, 1038 Relative = 1, 1039 } 1040 1041 [LeastSignificantByteFirst] 1042 private struct Descriptor 1043 { 1044 public string PrettyString => $@"Descriptor {{ 1045 structureType: {structureType}, 1046 structureTransferRequest: {structureTransferRequest}, 1047 transferCount: {transferCount + 1}, 1048 byteSwap: {byteSwap}, 1049 blockSize: {blockSize}, 1050 operationDoneInterruptFlagSetEnable: {operationDoneInterruptFlagSetEnable}, 1051 requestTransferModeSelect: {requestTransferModeSelect}, 1052 decrementLoopCount: {decrementLoopCount}, 1053 ignoreSingleRequests: {ignoreSingleRequests}, 1054 sourceIncrement: {sourceIncrement}, 1055 size: {size}, 1056 destinationIncrement: {destinationIncrement}, 1057 sourceAddressingMode: {sourceAddressingMode}, 1058 destinationAddressingMode: {destinationAddressingMode}, 1059 sourceAddress: 0x{sourceAddress:X}, 1060 destinationAddress: 0x{destinationAddress:X}, 1061 linkMode: {linkMode}, 1062 link: {link}, 1063 linkAddress: 0x{(linkAddress << 2):X} 1064 }}"; 1065 1066 // Some of this fields are read only via sysbus, but can be loaded from memory 1067 #pragma warning disable 649 1068 [PacketField, Offset(doubleWords: 0, bits: 0), Width(2)] 1069 public StructureType structureType; 1070 [PacketField, Offset(doubleWords: 0, bits: 3), Width(1)] 1071 public bool structureTransferRequest; 1072 [PacketField, Offset(doubleWords: 0, bits: 4), Width(11)] 1073 public uint transferCount; 1074 [PacketField, Offset(doubleWords: 0, bits: 15), Width(1)] 1075 public bool byteSwap; 1076 [PacketField, Offset(doubleWords: 0, bits: 16), Width(4)] 1077 public BlockSizeMode blockSize; 1078 [PacketField, Offset(doubleWords: 0, bits: 20), Width(1)] 1079 public bool operationDoneInterruptFlagSetEnable; 1080 [PacketField, Offset(doubleWords: 0, bits: 21), Width(1)] 1081 public RequestTransferMode requestTransferModeSelect; 1082 [PacketField, Offset(doubleWords: 0, bits: 22), Width(1)] 1083 public bool decrementLoopCount; 1084 [PacketField, Offset(doubleWords: 0, bits: 23), Width(1)] 1085 public bool ignoreSingleRequests; 1086 [PacketField, Offset(doubleWords: 0, bits: 24), Width(2)] 1087 public IncrementMode sourceIncrement; 1088 [PacketField, Offset(doubleWords: 0, bits: 26), Width(2)] 1089 public SizeMode size; 1090 [PacketField, Offset(doubleWords: 0, bits: 28), Width(2)] 1091 public IncrementMode destinationIncrement; 1092 [PacketField, Offset(doubleWords: 0, bits: 30), Width(1)] 1093 public AddressingMode sourceAddressingMode; 1094 [PacketField, Offset(doubleWords: 0, bits: 31), Width(1)] 1095 public AddressingMode destinationAddressingMode; 1096 [PacketField, Offset(doubleWords: 1, bits: 0), Width(32)] 1097 public uint sourceAddress; 1098 [PacketField, Offset(doubleWords: 2, bits: 0), Width(32)] 1099 public uint destinationAddress; 1100 [PacketField, Offset(doubleWords: 3, bits: 0), Width(1)] 1101 public AddressingMode linkMode; 1102 [PacketField, Offset(doubleWords: 3, bits: 1), Width(1)] 1103 public bool link; 1104 [PacketField, Offset(doubleWords: 3, bits: 2), Width(30)] 1105 public uint linkAddress; 1106 #pragma warning restore 649 1107 } 1108 } 1109 } 1110 } 1111