1 // 2 // Copyright (c) 2010-2025 Antmicro 3 // Copyright (c) 2022-2025 Silicon Labs 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 9 using System; 10 using System.Collections.Generic; 11 using System.Collections.ObjectModel; 12 using System.Linq; 13 using System.Runtime.InteropServices; 14 using Antmicro.Renode.Core; 15 using Antmicro.Renode.Core.Structure.Registers; 16 using Antmicro.Renode.Exceptions; 17 using Antmicro.Renode.Logging; 18 using Antmicro.Renode.Peripherals.Bus; 19 using Antmicro.Renode.Peripherals.Timers; 20 using Antmicro.Renode.Time; 21 using Antmicro.Renode.Utilities.Packets; 22 23 namespace Antmicro.Renode.Peripherals.DMA 24 { 25 public class EFR32MG24_LDMA : IBusPeripheral, IGPIOReceiver, IKnownSize 26 { EFR32MG24_LDMA(Machine machine)27 public EFR32MG24_LDMA(Machine machine) 28 { 29 this.machine = machine; 30 engine = new DmaEngine(machine.GetSystemBus(this)); 31 signals = new HashSet<int>(); 32 IRQ = new GPIO(); 33 channels = new Channel[NumberOfChannels]; 34 for(var i = 0; i < NumberOfChannels; ++i) 35 { 36 channels[i] = new Channel(this, i); 37 } 38 ldmaRegistersCollection = BuildLdmaRegisters(); 39 ldmaXbarRegistersCollection = BuildLdmaXbarRegisters(); 40 } 41 Reset()42 public void Reset() 43 { 44 signals.Clear(); 45 foreach(var channel in channels) 46 { 47 channel.Reset(); 48 } 49 UpdateInterrupts(); 50 } 51 OnGPIO(int number, bool value)52 public void OnGPIO(int number, bool value) 53 { 54 var signal = (SignalSelect)(number & 0xf); 55 var source = (SourceSelect)((number >> 4) & 0x3f); 56 bool single = ((number >> 12) & 1) != 0; 57 58 if(!value) 59 { 60 signals.Remove(number); 61 return; 62 } 63 signals.Add(number); 64 for(var i = 0; i < NumberOfChannels; ++i) 65 { 66 if(single && channels[i].IgnoreSingleRequests) 67 { 68 continue; 69 } 70 if(channels[i].Signal == signal && channels[i].Source == source) 71 { 72 channels[i].StartFromSignal(); 73 } 74 } 75 } 76 77 public GPIO IRQ { get; } 78 79 public long Size => 0x400; 80 private readonly DoubleWordRegisterCollection ldmaRegistersCollection; 81 private readonly DoubleWordRegisterCollection ldmaXbarRegistersCollection; 82 private readonly Machine machine; 83 84 private uint Read<T>(DoubleWordRegisterCollection registersCollection, string regionName, long offset, bool internal_read = false) 85 where T : struct, IComparable, IFormattable 86 { 87 var result = 0U; 88 long internal_offset = offset; 89 90 // Set, Clear, Toggle registers should only be used for write operations. But just in case we convert here as well. 91 if (offset >= SetRegisterOffset && offset < ClearRegisterOffset) 92 { 93 // Set register 94 internal_offset = offset - SetRegisterOffset; 95 if(!internal_read) 96 { 97 this.Log(LogLevel.Noisy, "SET Operation on {0}, offset=0x{1:X}, internal_offset=0x{2:X}", Enum.Format(typeof(T), internal_offset, "G"), offset, internal_offset); 98 } 99 } else if (offset >= ClearRegisterOffset && offset < ToggleRegisterOffset) 100 { 101 // Clear register 102 internal_offset = offset - ClearRegisterOffset; 103 if(!internal_read) 104 { 105 this.Log(LogLevel.Noisy, "CLEAR Operation on {0}, offset=0x{1:X}, internal_offset=0x{2:X}", Enum.Format(typeof(T), internal_offset, "G"), offset, internal_offset); 106 } 107 } else if (offset >= ToggleRegisterOffset) 108 { 109 // Toggle register 110 internal_offset = offset - ToggleRegisterOffset; 111 if(!internal_read) 112 { 113 this.Log(LogLevel.Noisy, "TOGGLE Operation on {0}, offset=0x{1:X}, internal_offset=0x{2:X}", Enum.Format(typeof(T), internal_offset, "G"), offset, internal_offset); 114 } 115 } 116 117 if(!registersCollection.TryRead(internal_offset, out result)) 118 { 119 if(!internal_read) 120 { 121 this.Log(LogLevel.Noisy, "Unhandled read from {0} at offset 0x{1:X} ({2}).", regionName, internal_offset, Enum.Format(typeof(T), internal_offset, "G")); 122 } 123 } 124 else 125 { 126 if(!internal_read) 127 { 128 this.Log(LogLevel.Noisy, "{0}: Read from {1} at offset 0x{2:X} ({3}), returned 0x{4:X}", 129 this.GetTime(), regionName, internal_offset, Enum.Format(typeof(T), internal_offset, "G"), result); 130 } 131 } 132 133 return result; 134 } 135 136 private void Write<T>(DoubleWordRegisterCollection registersCollection, string regionName, long offset, uint value) 137 where T : struct, IComparable, IFormattable 138 { machine.ClockSource.ExecuteInLockAntmicro.Renode.Peripherals.DMA.EFR32MG24_LDMA.IFormattable139 machine.ClockSource.ExecuteInLock(delegate { 140 long internal_offset = offset; 141 uint internal_value = value; 142 143 if (offset >= SetRegisterOffset && offset < ClearRegisterOffset) 144 { 145 // Set register 146 internal_offset = offset - SetRegisterOffset; 147 uint old_value = Read<T>(registersCollection, regionName, internal_offset, true); 148 internal_value = old_value | value; 149 this.Log(LogLevel.Noisy, "SET Operation on {0}, offset=0x{1:X}, internal_offset=0x{2:X}, SET_value=0x{3:X}, old_value=0x{4:X}, new_value=0x{5:X}", Enum.Format(typeof(T), internal_offset, "G"), offset, internal_offset, value, old_value, internal_value); 150 } else if (offset >= ClearRegisterOffset && offset < ToggleRegisterOffset) 151 { 152 // Clear register 153 internal_offset = offset - ClearRegisterOffset; 154 uint old_value = Read<T>(registersCollection, regionName, internal_offset, true); 155 internal_value = old_value & ~value; 156 this.Log(LogLevel.Noisy, "CLEAR Operation on {0}, offset=0x{1:X}, internal_offset=0x{2:X}, CLEAR_value=0x{3:X}, old_value=0x{4:X}, new_value=0x{5:X}", Enum.Format(typeof(T), internal_offset, "G"), offset, internal_offset, value, old_value, internal_value); 157 } else if (offset >= ToggleRegisterOffset) 158 { 159 // Toggle register 160 internal_offset = offset - ToggleRegisterOffset; 161 uint old_value = Read<T>(registersCollection, regionName, internal_offset, true); 162 internal_value = old_value ^ value; 163 this.Log(LogLevel.Noisy, "TOGGLE Operation on {0}, offset=0x{1:X}, internal_offset=0x{2:X}, TOGGLE_value=0x{3:X}, old_value=0x{4:X}, new_value=0x{5:X}", Enum.Format(typeof(T), internal_offset, "G"), offset, internal_offset, value, old_value, internal_value); 164 } 165 166 this.Log(LogLevel.Noisy, "{0}: Write to {1} at offset 0x{2:X} ({3}), value 0x{4:X}", 167 this.GetTime(), regionName, internal_offset, Enum.Format(typeof(T), internal_offset, "G"), internal_value); 168 169 if(!registersCollection.TryWrite(internal_offset, internal_value)) 170 { 171 this.Log(LogLevel.Debug, "Unhandled write to {0} at offset 0x{1:X} ({2}), value 0x{3:X}.", regionName, internal_offset, Enum.Format(typeof(T), internal_offset, "G"), internal_value); 172 return; 173 } 174 }); 175 } 176 177 [ConnectionRegionAttribute("ldma")] WriteDoubleWordToLdma(long offset, uint value)178 public void WriteDoubleWordToLdma(long offset, uint value) 179 { 180 Write<LdmaRegisters>(ldmaRegistersCollection, "Ldma", offset, value); 181 } 182 183 [ConnectionRegionAttribute("ldma")] ReadDoubleWordFromLdma(long offset)184 public uint ReadDoubleWordFromLdma(long offset) 185 { 186 return Read<LdmaRegisters>(ldmaRegistersCollection, "Ldma", offset); 187 } 188 189 [ConnectionRegionAttribute("ldmaxbar")] WriteDoubleWordToLdmaXbar(long offset, uint value)190 public void WriteDoubleWordToLdmaXbar(long offset, uint value) 191 { 192 Write<LdmaXbarRegisters>(ldmaXbarRegistersCollection, "LdmaXbar", offset, value); 193 } 194 195 [ConnectionRegionAttribute("ldmaxbar")] ReadDoubleWordFromLdmaXbar(long offset)196 public uint ReadDoubleWordFromLdmaXbar(long offset) 197 { 198 return Read<LdmaXbarRegisters>(ldmaXbarRegistersCollection, "LdmaXbar", offset); 199 } 200 BuildLdmaRegisters()201 private DoubleWordRegisterCollection BuildLdmaRegisters() 202 { 203 DoubleWordRegisterCollection c = new DoubleWordRegisterCollection(this, new Dictionary<long, DoubleWordRegister> 204 { 205 {(long)LdmaRegisters.CTRL, new DoubleWordRegister(this) 206 .WithReservedBits(0, 24) 207 .WithTag("NUMFIXED", 24, 5) 208 .WithReservedBits(29, 2) 209 .WithTaggedFlag("CORERST", 31) 210 }, 211 {(long)LdmaRegisters.STATUS, new DoubleWordRegister(this) 212 .WithTaggedFlag("ANYBUSY", 0) 213 .WithTaggedFlag("ANYREQ", 1) 214 .WithReservedBits(2, 1) 215 .WithTag("CHGRANT", 3, 5) 216 .WithTag("CHERROR", 8, 5) 217 .WithReservedBits(13, 3) 218 .WithTag("FIFOLEVEL", 16, 5) 219 .WithReservedBits(21, 3) 220 .WithTag("CHNUM", 24, 5) 221 .WithReservedBits(29, 3) 222 }, 223 {(long)LdmaRegisters.CHEN, new DoubleWordRegister(this) 224 .WithFlags(0, 31, writeCallback: (i, _, value) => { if (value) channels[i].Enabled = true; }, name: "CHEN") 225 .WithReservedBits(31, 1) 226 }, 227 {(long)LdmaRegisters.CHDIS, new DoubleWordRegister(this) 228 .WithFlags(0, 31, writeCallback: (i, _, value) => { if (value) channels[i].Enabled = false; }, name: "CHDIS") 229 .WithReservedBits(31, 1) 230 }, 231 {(long)LdmaRegisters.CHBUSY, new DoubleWordRegister(this) 232 .WithFlags(0, 31, FieldMode.Read, valueProviderCallback: (i, _) => channels[i].Busy, name: "CHBUSY") 233 .WithReservedBits(31, 1) 234 }, 235 {(long)LdmaRegisters.CHSTATUS, new DoubleWordRegister(this) 236 .WithFlags(0, 31, FieldMode.Read, valueProviderCallback: (i, _) => channels[i].Enabled, name: "CHSTATUS") 237 .WithReservedBits(31, 1) 238 }, 239 {(long)LdmaRegisters.CHDONE, new DoubleWordRegister(this) 240 .WithFlags(0, 31, writeCallback: (i, _, value) => channels[i].Done = value, valueProviderCallback: (i, _) => channels[i].Done, name: "CHDONE") 241 .WithReservedBits(31, 1) 242 }, 243 {(long)LdmaRegisters.DBGHALT, new DoubleWordRegister(this) 244 .WithTag("DBGHALT", 0, 31) 245 .WithReservedBits(31, 1) 246 }, 247 {(long)LdmaRegisters.SWREQ, new DoubleWordRegister(this) 248 .WithFlags(0, 31, FieldMode.Set, writeCallback: (i, _, value) => { if(value) channels[i].StartTransfer(); }, name: "SWREQ") 249 .WithReservedBits(31, 1) 250 }, 251 {(long)LdmaRegisters.REQDIS, new DoubleWordRegister(this) 252 .WithFlags(0, 31, writeCallback: (i, _, value) => channels[i].RequestDisable = value, valueProviderCallback: (i, _) => channels[i].RequestDisable, name: "REQDIS") 253 .WithReservedBits(31, 1) 254 }, 255 {(long)LdmaRegisters.REQPEND, new DoubleWordRegister(this) 256 .WithTag("REQPEND", 0, 31) 257 .WithReservedBits(31, 1) 258 }, 259 {(long)LdmaRegisters.LINKLOAD, new DoubleWordRegister(this) 260 .WithFlags(0, 31, FieldMode.Set, writeCallback: (i, _, value) => { if(value) channels[i].LinkLoad(); }, name: "LINKLOAD") 261 .WithReservedBits(31, 1) 262 }, 263 {(long)LdmaRegisters.REQCLEAR, new DoubleWordRegister(this) 264 .WithTag("REQCLEAR", 0, 31) 265 .WithReservedBits(31, 1) 266 }, 267 {(long)LdmaRegisters.IF, new DoubleWordRegister(this) 268 .WithFlags(0, 31, writeCallback: (i, _, value) => channels[i].DoneInterrupt = value, valueProviderCallback: (i, _) => channels[i].DoneInterrupt, name: "IF") 269 .WithTaggedFlag("ERROR", 31) 270 .WithWriteCallback((_, __) => UpdateInterrupts()) 271 }, 272 {(long)LdmaRegisters.IEN, new DoubleWordRegister(this) 273 .WithFlags(0, 31, writeCallback: (i, _, value) => channels[i].DoneInterruptEnable = value, valueProviderCallback: (i, _) => channels[i].DoneInterruptEnable, name: "IEN") 274 .WithTaggedFlag("ERROR", 31) 275 .WithWriteCallback((_, __) => UpdateInterrupts()) 276 }, 277 }); 278 279 var channelDelta = (uint)((long)LdmaRegisters.CH1_CFG - (long)LdmaRegisters.CH0_CFG); 280 BindRegisters(LdmaRegisters.CH0_CFG, c, NumberOfChannels, i => channels[i].ConfigurationRegister, channelDelta); 281 BindRegisters(LdmaRegisters.CH0_LOOP, c, NumberOfChannels, i => channels[i].LoopCounterRegister, channelDelta); 282 BindRegisters(LdmaRegisters.CH0_CTRL, c, NumberOfChannels, i => channels[i].DescriptorControlWordRegister, channelDelta); 283 BindRegisters(LdmaRegisters.CH0_SRC, c, NumberOfChannels, i => channels[i].DescriptorSourceDataAddressRegister, channelDelta); 284 BindRegisters(LdmaRegisters.CH0_DST, c, NumberOfChannels, i => channels[i].DescriptorDestinationDataAddressRegister, channelDelta); 285 BindRegisters(LdmaRegisters.CH0_LINK, c, NumberOfChannels, i => channels[i].DescriptorLinkStructureAddressRegister, channelDelta); 286 287 return c; 288 } 289 BuildLdmaXbarRegisters()290 private DoubleWordRegisterCollection BuildLdmaXbarRegisters() 291 { 292 DoubleWordRegisterCollection c = new DoubleWordRegisterCollection(this, new Dictionary<long, DoubleWordRegister>()); 293 294 var channelDelta = (uint)((long)LdmaXbarRegisters.XBAR_CH1_REQSEL - (long)LdmaXbarRegisters.XBAR_CH0_REQSEL); 295 BindRegisters(LdmaXbarRegisters.XBAR_CH0_REQSEL, c, NumberOfChannels, i => channels[i].PeripheralRequestSelectRegister, channelDelta); 296 297 return c; 298 } 299 BindRegisters(IConvertible o, DoubleWordRegisterCollection c, uint count, Func<int, DoubleWordRegister> setup, uint stepInBytes = 4)300 private void BindRegisters(IConvertible o, DoubleWordRegisterCollection c, uint count, Func<int, DoubleWordRegister> setup, uint stepInBytes = 4) 301 { 302 if(!o.GetType().IsEnum) 303 { 304 throw new ArgumentException("This method should be called on enumerated type"); 305 } 306 307 var baseAddress = Convert.ToInt64(o); 308 for(var i = 0; i < count; i++) 309 { 310 var register = setup(i); 311 c.AddRegister(baseAddress + i * stepInBytes, register); 312 } 313 } 314 UpdateInterrupts()315 private void UpdateInterrupts() 316 { 317 this.Log(LogLevel.Debug, "Interrupt set for channels: {0}", String.Join(", ", 318 channels 319 .Where(channel => channel.IRQ) 320 .Select(channel => channel.Index) 321 )); 322 IRQ.Set(channels.Any(channel => channel.IRQ)); 323 } 324 GetTime()325 private TimeInterval GetTime() => machine.LocalTimeSource.ElapsedVirtualTime; 326 327 private readonly DmaEngine engine; 328 private readonly HashSet<int> signals; 329 private readonly Channel[] channels; 330 private const uint SetRegisterOffset = 0x1000; 331 private const uint ClearRegisterOffset = 0x2000; 332 private const uint ToggleRegisterOffset = 0x3000; 333 private const int NumberOfChannels = 31; 334 335 private enum SignalSelect 336 { 337 // if SOURCESEL is LDMAXBAR 338 LDMAXBAR_DMA_PRSREQ0 = 0x0, 339 LDMAXBAR_DMA_PRSREQ1 = 0x1, 340 // if SOURCESEL is TIMER0 341 TIMER0_DMA_CC0 = 0x0, 342 TIMER0_DMA_CC1 = 0x1, 343 TIMER0_DMA_CC2 = 0x2, 344 TIMER0_DMA_UFOF = 0x3, 345 // if SOURCESEL is TIMER1 346 TIMER1_DMA_CC0 = 0x0, 347 TIMER1_DMA_CC1 = 0x1, 348 TIMER1_DMA_CC2 = 0x2, 349 TIMER1_DMA_UFOF = 0x3, 350 // if SOURCESEL is USART0 351 USART0_DMA_RXDATAV = 0x0, 352 USART0_DMA_RXDATAVRIGHT = 0x1, 353 USART0_DMA_TXBL = 0x2, 354 USART0_DMA_TXBLRIGHT = 0x3, 355 USART0_DMA_TXEMPTY = 0x4, 356 // if SOURCESEL is I2C0 357 I2C0_DMA_RXDATAV = 0x0, 358 I2C0_DMA_TXBL = 0x1, 359 // if SOURCESEL is I2C1 360 I2C1_DMA_RXDATAV = 0x0, 361 I2C1_DMA_TXBL = 0x1, 362 // if SOURCESEL is IADC0 363 IADC0_DMA_IADC_SCAN = 0x0, 364 IADC0_DMA_IADC_SINGLE = 0x1, 365 // if SOURCESEL is MSB 366 MSC_DMA_WDATA = 0x0, 367 // if SOURCESEL is TIMER2 368 TIMER2_DMA_CC0 = 0x0, 369 TIMER2_DMA_CC1 = 0x1, 370 TIMER2_DMA_CC2 = 0x2, 371 TIMER2_DMA_UFOF = 0x3, 372 // if SOURCESEL is TIMER3 373 TIMER3_DMA_CC0 = 0x0, 374 TIMER3_DMA_CC1 = 0x1, 375 TIMER3_DMA_CC2 = 0x2, 376 TIMER3_DMA_UFOF = 0x3, 377 // if SOURCESEL is TIMER4 378 TIMER4_DMA_CC0 = 0x0, 379 TIMER4_DMA_CC1 = 0x1, 380 TIMER4_DMA_CC2 = 0x2, 381 TIMER4_DMA_UFOF = 0x3, 382 // if SOURCESEL is EUSART0 383 EUSART0_DMA_RXFL = 0x0, 384 EUSART0_DMA_TXFL = 0x1, 385 // if SOURCESEL is EUSART1 386 EUSART1_DMA_RXFL = 0x0, 387 EUSART1_DMA_TXFL = 0x1, 388 // if VDAC0 389 VDAC0_DMA_CH0_REQ = 0x0, 390 VDAC0_DMA_CH1_REQ = 0x1, 391 // if VDAC1 392 VDAC1_DMA_CH0_REQ = 0x0, 393 VDAC1_DMA_CH1_REQ = 0x1, 394 } 395 396 private enum SourceSelect 397 { 398 None = 0x0, 399 LDMAXBAR = 0x1, 400 TIMER0 = 0x2, 401 TIMER1 = 0x3, 402 USART0 = 0x4, 403 I2C0 = 0x5, 404 I2C1 = 0x6, 405 IADC0 = 0xA, 406 MSC = 0xB, 407 TIMER2 = 0xC, 408 TIMER3 = 0xD, 409 TIMER4 = 0xE, 410 EUSART0 = 0xF, 411 EUSART1 = 0x10, 412 VDAC0 = 0x11, 413 VDAC1 = 0x12, 414 } 415 416 private enum LdmaRegisters : long 417 { 418 IPVERSION = 0x0000, 419 EN = 0x0004, 420 CTRL = 0x0008, 421 STATUS = 0x000C, 422 SYNCSWSET = 0x0010, 423 SYNCSWCLR = 0x0014, 424 SYNCHWEN = 0x0018, 425 SYNCHWSEL = 0x001C, 426 SYNCSTATUS = 0x0020, 427 CHEN = 0x0024, 428 CHDIS = 0x0028, 429 CHSTATUS = 0x002C, 430 CHBUSY = 0x0030, 431 CHDONE = 0x0034, 432 DBGHALT = 0x0038, 433 SWREQ = 0x003C, 434 REQDIS = 0x0040, 435 REQPEND = 0x0044, 436 LINKLOAD = 0x0048, 437 REQCLEAR = 0x004C, 438 IF = 0x0050, 439 IEN = 0x0054, 440 CH0_CFG = 0x005C, 441 CH0_LOOP = 0x0060, 442 CH0_CTRL = 0x0064, 443 CH0_SRC = 0x0068, 444 CH0_DST = 0x006C, 445 CH0_LINK = 0x0070, 446 CH1_CFG = 0x008C, 447 CH1_LOOP = 0x0090, 448 CH1_CTRL = 0x0094, 449 CH1_SRC = 0x0098, 450 CH1_DST = 0x009C, 451 CH1_LINK = 0x00A0, 452 CH2_CFG = 0x00BC, 453 CH2_LOOP = 0x00C0, 454 CH2_CTRL = 0x00C4, 455 CH2_SRC = 0x00C8, 456 CH2_DST = 0x00CC, 457 CH2_LINK = 0x00D0, 458 CH3_CFG = 0x00EC, 459 CH3_LOOP = 0x00F0, 460 CH3_CTRL = 0x00F4, 461 CH3_SRC = 0x00F8, 462 CH3_DST = 0x00FC, 463 CH3_LINK = 0x0100, 464 CH4_CFG = 0x011C, 465 CH4_LOOP = 0x0120, 466 CH4_CTRL = 0x0124, 467 CH4_SRC = 0x0128, 468 CH4_DST = 0x012C, 469 CH4_LINK = 0x0130, 470 CH5_CFG = 0x014C, 471 CH5_LOOP = 0x0150, 472 CH5_CTRL = 0x0154, 473 CH5_SRC = 0x0158, 474 CH5_DST = 0x015C, 475 CH5_LINK = 0x0160, 476 CH6_CFG = 0x017C, 477 CH6_LOOP = 0x0180, 478 CH6_CTRL = 0x0184, 479 CH6_SRC = 0x0188, 480 CH6_DST = 0x018C, 481 CH6_LINK = 0x0190, 482 CH7_CFG = 0x01AC, 483 CH7_LOOP = 0x01B0, 484 CH7_CTRL = 0x01B4, 485 CH7_SRC = 0x01B8, 486 CH7_DST = 0x01BC, 487 CH7_LINK = 0x01C0, 488 CH8_CFG = 0x01DC, 489 CH8_LOOP = 0x01E0, 490 CH8_CTRL = 0x01E4, 491 CH8_SRC = 0x01E8, 492 CH8_DST = 0x01EC, 493 CH8_LINK = 0x01F0, 494 CH9_CFG = 0x020C, 495 CH9_LOOP = 0x0210, 496 CH9_CTRL = 0x0214, 497 CH9_SRC = 0x0218, 498 CH9_DST = 0x021C, 499 CH9_LINK = 0x0220, 500 CH10_CFG = 0x023C, 501 CH10_LOOP = 0x0240, 502 CH10_CTRL = 0x0244, 503 CH10_SRC = 0x0248, 504 CH10_DST = 0x024C, 505 CH10_LINK = 0x0250, 506 CH11_CFG = 0x026C, 507 CH11_LOOP = 0x0270, 508 CH11_CTRL = 0x0274, 509 CH11_SRC = 0x0278, 510 CH11_DST = 0x027C, 511 CH11_LINK = 0x0280, 512 CH12_CFG = 0x029C, 513 CH12_LOOP = 0x02A0, 514 CH12_CTRL = 0x02A4, 515 CH12_SRC = 0x02A8, 516 CH12_DST = 0x02AC, 517 CH12_LINK = 0x02B0, 518 CH13_CFG = 0x02CC, 519 CH13_LOOP = 0x02D0, 520 CH13_CTRL = 0x02D4, 521 CH13_SRC = 0x02D8, 522 CH13_DST = 0x02DC, 523 CH13_LINK = 0x02E0, 524 CH14_CFG = 0x02FC, 525 CH14_LOOP = 0x0300, 526 CH14_CTRL = 0x0304, 527 CH14_SRC = 0x0308, 528 CH14_DST = 0x030C, 529 CH14_LINK = 0x0310, 530 CH15_CFG = 0x032C, 531 CH15_LOOP = 0x0330, 532 CH15_CTRL = 0x0334, 533 CH15_SRC = 0x0338, 534 CH15_DST = 0x033C, 535 CH15_LINK = 0x0340, 536 CH16_CFG = 0x035C, 537 CH16_LOOP = 0x0360, 538 CH16_CTRL = 0x0364, 539 CH16_SRC = 0x0368, 540 CH16_DST = 0x036C, 541 CH16_LINK = 0x0370, 542 CH17_CFG = 0x038C, 543 CH17_LOOP = 0x0390, 544 CH17_CTRL = 0x0394, 545 CH17_SRC = 0x0398, 546 CH17_DST = 0x039C, 547 CH17_LINK = 0x03A0, 548 CH18_CFG = 0x03BC, 549 CH18_LOOP = 0x03C0, 550 CH18_CTRL = 0x03C4, 551 CH18_SRC = 0x03C8, 552 CH18_DST = 0x03CC, 553 CH18_LINK = 0x03D0, 554 CH19_CFG = 0x03EC, 555 CH19_LOOP = 0x03F0, 556 CH19_CTRL = 0x03F4, 557 CH19_SRC = 0x03F8, 558 CH19_DST = 0x03FC, 559 CH19_LINK = 0x0400, 560 CH20_CFG = 0x041C, 561 CH20_LOOP = 0x0420, 562 CH20_CTRL = 0x0424, 563 CH20_SRC = 0x0428, 564 CH20_DST = 0x042C, 565 CH20_LINK = 0x0430, 566 CH21_CFG = 0x044C, 567 CH21_LOOP = 0x0450, 568 CH21_CTRL = 0x0454, 569 CH21_SRC = 0x0458, 570 CH21_DST = 0x045C, 571 CH21_LINK = 0x0460, 572 CH22_CFG = 0x047C, 573 CH22_LOOP = 0x0480, 574 CH22_CTRL = 0x0484, 575 CH22_SRC = 0x0488, 576 CH22_DST = 0x048C, 577 CH22_LINK = 0x0490, 578 CH23_CFG = 0x04AC, 579 CH23_LOOP = 0x04B0, 580 CH23_CTRL = 0x04B4, 581 CH23_SRC = 0x04B8, 582 CH23_DST = 0x04BC, 583 CH23_LINK = 0x04C0, 584 CH24_CFG = 0x04DC, 585 CH24_LOOP = 0x04E0, 586 CH24_CTRL = 0x04E4, 587 CH24_SRC = 0x04E8, 588 CH24_DST = 0x04EC, 589 CH24_LINK = 0x04F0, 590 CH25_CFG = 0x050C, 591 CH25_LOOP = 0x0510, 592 CH25_CTRL = 0x0514, 593 CH25_SRC = 0x0518, 594 CH25_DST = 0x051C, 595 CH25_LINK = 0x0520, 596 CH26_CFG = 0x053C, 597 CH26_LOOP = 0x0540, 598 CH26_CTRL = 0x0544, 599 CH26_SRC = 0x0548, 600 CH26_DST = 0x054C, 601 CH26_LINK = 0x0550, 602 CH27_CFG = 0x056C, 603 CH27_LOOP = 0x0570, 604 CH27_CTRL = 0x0574, 605 CH27_SRC = 0x0578, 606 CH27_DST = 0x057C, 607 CH27_LINK = 0x0580, 608 CH28_CFG = 0x059C, 609 CH28_LOOP = 0x05A0, 610 CH28_CTRL = 0x05A4, 611 CH28_SRC = 0x05A8, 612 CH28_DST = 0x05AC, 613 CH28_LINK = 0x05B0, 614 CH29_CFG = 0x05CC, 615 CH29_LOOP = 0x05D0, 616 CH29_CTRL = 0x05D4, 617 CH29_SRC = 0x05D8, 618 CH29_DST = 0x05DC, 619 CH29_LINK = 0x05E0, 620 CH30_CFG = 0x05FC, 621 CH30_LOOP = 0x0600, 622 CH30_CTRL = 0x0604, 623 CH30_SRC = 0x0608, 624 CH30_DST = 0x060C, 625 CH30_LINK = 0x0610, 626 // Set registers 627 IPVERSION_Set = 0x1000, 628 EN_Set = 0x1004, 629 CTRL_Set = 0x1008, 630 STATUS_Set = 0x100C, 631 SYNCSWSET_Set = 0x1010, 632 SYNCSWCLR_Set = 0x1014, 633 SYNCHWEN_Set = 0x1018, 634 SYNCHWSEL_Set = 0x101C, 635 SYNCSTATUS_Set = 0x1020, 636 CHEN_Set = 0x1024, 637 CHDIS_Set = 0x1028, 638 CHSTATUS_Set = 0x102C, 639 CHBUSY_Set = 0x1030, 640 CHDONE_Set = 0x1034, 641 DBGHALT_Set = 0x1038, 642 SWREQ_Set = 0x103C, 643 REQDIS_Set = 0x1040, 644 REQPEND_Set = 0x1044, 645 LINKLOAD_Set = 0x1048, 646 REQCLEAR_Set = 0x104C, 647 IF_Set = 0x1050, 648 IEN_Set = 0x1054, 649 CH0_CFG_Set = 0x105C, 650 CH0_LOOP_Set = 0x1060, 651 CH0_CTRL_Set = 0x1064, 652 CH0_SRC_Set = 0x1068, 653 CH0_DST_Set = 0x106C, 654 CH0_LINK_Set = 0x1070, 655 CH1_CFG_Set = 0x108C, 656 CH1_LOOP_Set = 0x1090, 657 CH1_CTRL_Set = 0x1094, 658 CH1_SRC_Set = 0x1098, 659 CH1_DST_Set = 0x109C, 660 CH1_LINK_Set = 0x10A0, 661 CH2_CFG_Set = 0x10BC, 662 CH2_LOOP_Set = 0x10C0, 663 CH2_CTRL_Set = 0x10C4, 664 CH2_SRC_Set = 0x10C8, 665 CH2_DST_Set = 0x10CC, 666 CH2_LINK_Set = 0x10D0, 667 CH3_CFG_Set = 0x10EC, 668 CH3_LOOP_Set = 0x10F0, 669 CH3_CTRL_Set = 0x10F4, 670 CH3_SRC_Set = 0x10F8, 671 CH3_DST_Set = 0x10FC, 672 CH3_LINK_Set = 0x1100, 673 CH4_CFG_Set = 0x111C, 674 CH4_LOOP_Set = 0x1120, 675 CH4_CTRL_Set = 0x1124, 676 CH4_SRC_Set = 0x1128, 677 CH4_DST_Set = 0x112C, 678 CH4_LINK_Set = 0x1130, 679 CH5_CFG_Set = 0x114C, 680 CH5_LOOP_Set = 0x1150, 681 CH5_CTRL_Set = 0x1154, 682 CH5_SRC_Set = 0x1158, 683 CH5_DST_Set = 0x115C, 684 CH5_LINK_Set = 0x1160, 685 CH6_CFG_Set = 0x117C, 686 CH6_LOOP_Set = 0x1180, 687 CH6_CTRL_Set = 0x1184, 688 CH6_SRC_Set = 0x1188, 689 CH6_DST_Set = 0x118C, 690 CH6_LINK_Set = 0x1190, 691 CH7_CFG_Set = 0x11AC, 692 CH7_LOOP_Set = 0x11B0, 693 CH7_CTRL_Set = 0x11B4, 694 CH7_SRC_Set = 0x11B8, 695 CH7_DST_Set = 0x11BC, 696 CH7_LINK_Set = 0x11C0, 697 CH8_CFG_Set = 0x11DC, 698 CH8_LOOP_Set = 0x11E0, 699 CH8_CTRL_Set = 0x11E4, 700 CH8_SRC_Set = 0x11E8, 701 CH8_DST_Set = 0x11EC, 702 CH8_LINK_Set = 0x11F0, 703 CH9_CFG_Set = 0x120C, 704 CH9_LOOP_Set = 0x1210, 705 CH9_CTRL_Set = 0x1214, 706 CH9_SRC_Set = 0x1218, 707 CH9_DST_Set = 0x121C, 708 CH9_LINK_Set = 0x1220, 709 CH10_CFG_Set = 0x123C, 710 CH10_LOOP_Set = 0x1240, 711 CH10_CTRL_Set = 0x1244, 712 CH10_SRC_Set = 0x1248, 713 CH10_DST_Set = 0x124C, 714 CH10_LINK_Set = 0x1250, 715 CH11_CFG_Set = 0x126C, 716 CH11_LOOP_Set = 0x1270, 717 CH11_CTRL_Set = 0x1274, 718 CH11_SRC_Set = 0x1278, 719 CH11_DST_Set = 0x127C, 720 CH11_LINK_Set = 0x1280, 721 CH12_CFG_Set = 0x129C, 722 CH12_LOOP_Set = 0x12A0, 723 CH12_CTRL_Set = 0x12A4, 724 CH12_SRC_Set = 0x12A8, 725 CH12_DST_Set = 0x12AC, 726 CH12_LINK_Set = 0x12B0, 727 CH13_CFG_Set = 0x12CC, 728 CH13_LOOP_Set = 0x12D0, 729 CH13_CTRL_Set = 0x12D4, 730 CH13_SRC_Set = 0x12D8, 731 CH13_DST_Set = 0x12DC, 732 CH13_LINK_Set = 0x12E0, 733 CH14_CFG_Set = 0x12FC, 734 CH14_LOOP_Set = 0x1300, 735 CH14_CTRL_Set = 0x1304, 736 CH14_SRC_Set = 0x1308, 737 CH14_DST_Set = 0x130C, 738 CH14_LINK_Set = 0x1310, 739 CH15_CFG_Set = 0x132C, 740 CH15_LOOP_Set = 0x1330, 741 CH15_CTRL_Set = 0x1334, 742 CH15_SRC_Set = 0x1338, 743 CH15_DST_Set = 0x133C, 744 CH15_LINK_Set = 0x1340, 745 CH16_CFG_Set = 0x135C, 746 CH16_LOOP_Set = 0x1360, 747 CH16_CTRL_Set = 0x1364, 748 CH16_SRC_Set = 0x1368, 749 CH16_DST_Set = 0x136C, 750 CH16_LINK_Set = 0x1370, 751 CH17_CFG_Set = 0x138C, 752 CH17_LOOP_Set = 0x1390, 753 CH17_CTRL_Set = 0x1394, 754 CH17_SRC_Set = 0x1398, 755 CH17_DST_Set = 0x139C, 756 CH17_LINK_Set = 0x13A0, 757 CH18_CFG_Set = 0x13BC, 758 CH18_LOOP_Set = 0x13C0, 759 CH18_CTRL_Set = 0x13C4, 760 CH18_SRC_Set = 0x13C8, 761 CH18_DST_Set = 0x13CC, 762 CH18_LINK_Set = 0x13D0, 763 CH19_CFG_Set = 0x13EC, 764 CH19_LOOP_Set = 0x13F0, 765 CH19_CTRL_Set = 0x13F4, 766 CH19_SRC_Set = 0x13F8, 767 CH19_DST_Set = 0x13FC, 768 CH19_LINK_Set = 0x1400, 769 CH20_CFG_Set = 0x141C, 770 CH20_LOOP_Set = 0x1420, 771 CH20_CTRL_Set = 0x1424, 772 CH20_SRC_Set = 0x1428, 773 CH20_DST_Set = 0x142C, 774 CH20_LINK_Set = 0x1430, 775 CH21_CFG_Set = 0x144C, 776 CH21_LOOP_Set = 0x1450, 777 CH21_CTRL_Set = 0x1454, 778 CH21_SRC_Set = 0x1458, 779 CH21_DST_Set = 0x145C, 780 CH21_LINK_Set = 0x1460, 781 CH22_CFG_Set = 0x147C, 782 CH22_LOOP_Set = 0x1480, 783 CH22_CTRL_Set = 0x1484, 784 CH22_SRC_Set = 0x1488, 785 CH22_DST_Set = 0x148C, 786 CH22_LINK_Set = 0x1490, 787 CH23_CFG_Set = 0x14AC, 788 CH23_LOOP_Set = 0x14B0, 789 CH23_CTRL_Set = 0x14B4, 790 CH23_SRC_Set = 0x14B8, 791 CH23_DST_Set = 0x14BC, 792 CH23_LINK_Set = 0x14C0, 793 CH24_CFG_Set = 0x14DC, 794 CH24_LOOP_Set = 0x14E0, 795 CH24_CTRL_Set = 0x14E4, 796 CH24_SRC_Set = 0x14E8, 797 CH24_DST_Set = 0x14EC, 798 CH24_LINK_Set = 0x14F0, 799 CH25_CFG_Set = 0x150C, 800 CH25_LOOP_Set = 0x1510, 801 CH25_CTRL_Set = 0x1514, 802 CH25_SRC_Set = 0x1518, 803 CH25_DST_Set = 0x151C, 804 CH25_LINK_Set = 0x1520, 805 CH26_CFG_Set = 0x153C, 806 CH26_LOOP_Set = 0x1540, 807 CH26_CTRL_Set = 0x1544, 808 CH26_SRC_Set = 0x1548, 809 CH26_DST_Set = 0x154C, 810 CH26_LINK_Set = 0x1550, 811 CH27_CFG_Set = 0x156C, 812 CH27_LOOP_Set = 0x1570, 813 CH27_CTRL_Set = 0x1574, 814 CH27_SRC_Set = 0x1578, 815 CH27_DST_Set = 0x157C, 816 CH27_LINK_Set = 0x1580, 817 CH28_CFG_Set = 0x159C, 818 CH28_LOOP_Set = 0x15A0, 819 CH28_CTRL_Set = 0x15A4, 820 CH28_SRC_Set = 0x15A8, 821 CH28_DST_Set = 0x15AC, 822 CH28_LINK_Set = 0x15B0, 823 CH29_CFG_Set = 0x15CC, 824 CH29_LOOP_Set = 0x15D0, 825 CH29_CTRL_Set = 0x15D4, 826 CH29_SRC_Set = 0x15D8, 827 CH29_DST_Set = 0x15DC, 828 CH29_LINK_Set = 0x15E0, 829 CH30_CFG_Set = 0x15FC, 830 CH30_LOOP_Set = 0x1600, 831 CH30_CTRL_Set = 0x1604, 832 CH30_SRC_Set = 0x1608, 833 CH30_DST_Set = 0x160C, 834 CH30_LINK_Set = 0x1610, 835 // Clear registers 836 IPVERSION_Clr = 0x2000, 837 EN_Clr = 0x2004, 838 CTRL_Clr = 0x2008, 839 STATUS_Clr = 0x200C, 840 SYNCSWSET_Clr = 0x2010, 841 SYNCSWCLR_Clr = 0x2014, 842 SYNCHWEN_Clr = 0x2018, 843 SYNCHWSEL_Clr = 0x201C, 844 SYNCSTATUS_Clr = 0x2020, 845 CHEN_Clr = 0x2024, 846 CHDIS_Clr = 0x2028, 847 CHSTATUS_Clr = 0x202C, 848 CHBUSY_Clr = 0x2030, 849 CHDONE_Clr = 0x2034, 850 DBGHALT_Clr = 0x2038, 851 SWREQ_Clr = 0x203C, 852 REQDIS_Clr = 0x2040, 853 REQPEND_Clr = 0x2044, 854 LINKLOAD_Clr = 0x2048, 855 REQCLEAR_Clr = 0x204C, 856 IF_Clr = 0x2050, 857 IEN_Clr = 0x2054, 858 CH0_CFG_Clr = 0x205C, 859 CH0_LOOP_Clr = 0x2060, 860 CH0_CTRL_Clr = 0x2064, 861 CH0_SRC_Clr = 0x2068, 862 CH0_DST_Clr = 0x206C, 863 CH0_LINK_Clr = 0x2070, 864 CH1_CFG_Clr = 0x208C, 865 CH1_LOOP_Clr = 0x2090, 866 CH1_CTRL_Clr = 0x2094, 867 CH1_SRC_Clr = 0x2098, 868 CH1_DST_Clr = 0x209C, 869 CH1_LINK_Clr = 0x20A0, 870 CH2_CFG_Clr = 0x20BC, 871 CH2_LOOP_Clr = 0x20C0, 872 CH2_CTRL_Clr = 0x20C4, 873 CH2_SRC_Clr = 0x20C8, 874 CH2_DST_Clr = 0x20CC, 875 CH2_LINK_Clr = 0x20D0, 876 CH3_CFG_Clr = 0x20EC, 877 CH3_LOOP_Clr = 0x20F0, 878 CH3_CTRL_Clr = 0x20F4, 879 CH3_SRC_Clr = 0x20F8, 880 CH3_DST_Clr = 0x20FC, 881 CH3_LINK_Clr = 0x2100, 882 CH4_CFG_Clr = 0x211C, 883 CH4_LOOP_Clr = 0x2120, 884 CH4_CTRL_Clr = 0x2124, 885 CH4_SRC_Clr = 0x2128, 886 CH4_DST_Clr = 0x212C, 887 CH4_LINK_Clr = 0x2130, 888 CH5_CFG_Clr = 0x214C, 889 CH5_LOOP_Clr = 0x2150, 890 CH5_CTRL_Clr = 0x2154, 891 CH5_SRC_Clr = 0x2158, 892 CH5_DST_Clr = 0x215C, 893 CH5_LINK_Clr = 0x2160, 894 CH6_CFG_Clr = 0x217C, 895 CH6_LOOP_Clr = 0x2180, 896 CH6_CTRL_Clr = 0x2184, 897 CH6_SRC_Clr = 0x2188, 898 CH6_DST_Clr = 0x218C, 899 CH6_LINK_Clr = 0x2190, 900 CH7_CFG_Clr = 0x21AC, 901 CH7_LOOP_Clr = 0x21B0, 902 CH7_CTRL_Clr = 0x21B4, 903 CH7_SRC_Clr = 0x21B8, 904 CH7_DST_Clr = 0x21BC, 905 CH7_LINK_Clr = 0x21C0, 906 CH8_CFG_Clr = 0x21DC, 907 CH8_LOOP_Clr = 0x21E0, 908 CH8_CTRL_Clr = 0x21E4, 909 CH8_SRC_Clr = 0x21E8, 910 CH8_DST_Clr = 0x21EC, 911 CH8_LINK_Clr = 0x21F0, 912 CH9_CFG_Clr = 0x220C, 913 CH9_LOOP_Clr = 0x2210, 914 CH9_CTRL_Clr = 0x2214, 915 CH9_SRC_Clr = 0x2218, 916 CH9_DST_Clr = 0x221C, 917 CH9_LINK_Clr = 0x2220, 918 CH10_CFG_Clr = 0x223C, 919 CH10_LOOP_Clr = 0x2240, 920 CH10_CTRL_Clr = 0x2244, 921 CH10_SRC_Clr = 0x2248, 922 CH10_DST_Clr = 0x224C, 923 CH10_LINK_Clr = 0x2250, 924 CH11_CFG_Clr = 0x226C, 925 CH11_LOOP_Clr = 0x2270, 926 CH11_CTRL_Clr = 0x2274, 927 CH11_SRC_Clr = 0x2278, 928 CH11_DST_Clr = 0x227C, 929 CH11_LINK_Clr = 0x2280, 930 CH12_CFG_Clr = 0x229C, 931 CH12_LOOP_Clr = 0x22A0, 932 CH12_CTRL_Clr = 0x22A4, 933 CH12_SRC_Clr = 0x22A8, 934 CH12_DST_Clr = 0x22AC, 935 CH12_LINK_Clr = 0x22B0, 936 CH13_CFG_Clr = 0x22CC, 937 CH13_LOOP_Clr = 0x22D0, 938 CH13_CTRL_Clr = 0x22D4, 939 CH13_SRC_Clr = 0x22D8, 940 CH13_DST_Clr = 0x22DC, 941 CH13_LINK_Clr = 0x22E0, 942 CH14_CFG_Clr = 0x22FC, 943 CH14_LOOP_Clr = 0x2300, 944 CH14_CTRL_Clr = 0x2304, 945 CH14_SRC_Clr = 0x2308, 946 CH14_DST_Clr = 0x230C, 947 CH14_LINK_Clr = 0x2310, 948 CH15_CFG_Clr = 0x232C, 949 CH15_LOOP_Clr = 0x2330, 950 CH15_CTRL_Clr = 0x2334, 951 CH15_SRC_Clr = 0x2338, 952 CH15_DST_Clr = 0x233C, 953 CH15_LINK_Clr = 0x2340, 954 CH16_CFG_Clr = 0x235C, 955 CH16_LOOP_Clr = 0x2360, 956 CH16_CTRL_Clr = 0x2364, 957 CH16_SRC_Clr = 0x2368, 958 CH16_DST_Clr = 0x236C, 959 CH16_LINK_Clr = 0x2370, 960 CH17_CFG_Clr = 0x238C, 961 CH17_LOOP_Clr = 0x2390, 962 CH17_CTRL_Clr = 0x2394, 963 CH17_SRC_Clr = 0x2398, 964 CH17_DST_Clr = 0x239C, 965 CH17_LINK_Clr = 0x23A0, 966 CH18_CFG_Clr = 0x23BC, 967 CH18_LOOP_Clr = 0x23C0, 968 CH18_CTRL_Clr = 0x23C4, 969 CH18_SRC_Clr = 0x23C8, 970 CH18_DST_Clr = 0x23CC, 971 CH18_LINK_Clr = 0x23D0, 972 CH19_CFG_Clr = 0x23EC, 973 CH19_LOOP_Clr = 0x23F0, 974 CH19_CTRL_Clr = 0x23F4, 975 CH19_SRC_Clr = 0x23F8, 976 CH19_DST_Clr = 0x23FC, 977 CH19_LINK_Clr = 0x2400, 978 CH20_CFG_Clr = 0x241C, 979 CH20_LOOP_Clr = 0x2420, 980 CH20_CTRL_Clr = 0x2424, 981 CH20_SRC_Clr = 0x2428, 982 CH20_DST_Clr = 0x242C, 983 CH20_LINK_Clr = 0x2430, 984 CH21_CFG_Clr = 0x244C, 985 CH21_LOOP_Clr = 0x2450, 986 CH21_CTRL_Clr = 0x2454, 987 CH21_SRC_Clr = 0x2458, 988 CH21_DST_Clr = 0x245C, 989 CH21_LINK_Clr = 0x2460, 990 CH22_CFG_Clr = 0x247C, 991 CH22_LOOP_Clr = 0x2480, 992 CH22_CTRL_Clr = 0x2484, 993 CH22_SRC_Clr = 0x2488, 994 CH22_DST_Clr = 0x248C, 995 CH22_LINK_Clr = 0x2490, 996 CH23_CFG_Clr = 0x24AC, 997 CH23_LOOP_Clr = 0x24B0, 998 CH23_CTRL_Clr = 0x24B4, 999 CH23_SRC_Clr = 0x24B8, 1000 CH23_DST_Clr = 0x24BC, 1001 CH23_LINK_Clr = 0x24C0, 1002 CH24_CFG_Clr = 0x24DC, 1003 CH24_LOOP_Clr = 0x24E0, 1004 CH24_CTRL_Clr = 0x24E4, 1005 CH24_SRC_Clr = 0x24E8, 1006 CH24_DST_Clr = 0x24EC, 1007 CH24_LINK_Clr = 0x24F0, 1008 CH25_CFG_Clr = 0x250C, 1009 CH25_LOOP_Clr = 0x2510, 1010 CH25_CTRL_Clr = 0x2514, 1011 CH25_SRC_Clr = 0x2518, 1012 CH25_DST_Clr = 0x251C, 1013 CH25_LINK_Clr = 0x2520, 1014 CH26_CFG_Clr = 0x253C, 1015 CH26_LOOP_Clr = 0x2540, 1016 CH26_CTRL_Clr = 0x2544, 1017 CH26_SRC_Clr = 0x2548, 1018 CH26_DST_Clr = 0x254C, 1019 CH26_LINK_Clr = 0x2550, 1020 CH27_CFG_Clr = 0x256C, 1021 CH27_LOOP_Clr = 0x2570, 1022 CH27_CTRL_Clr = 0x2574, 1023 CH27_SRC_Clr = 0x2578, 1024 CH27_DST_Clr = 0x257C, 1025 CH27_LINK_Clr = 0x2580, 1026 CH28_CFG_Clr = 0x259C, 1027 CH28_LOOP_Clr = 0x25A0, 1028 CH28_CTRL_Clr = 0x25A4, 1029 CH28_SRC_Clr = 0x25A8, 1030 CH28_DST_Clr = 0x25AC, 1031 CH28_LINK_Clr = 0x25B0, 1032 CH29_CFG_Clr = 0x25CC, 1033 CH29_LOOP_Clr = 0x25D0, 1034 CH29_CTRL_Clr = 0x25D4, 1035 CH29_SRC_Clr = 0x25D8, 1036 CH29_DST_Clr = 0x25DC, 1037 CH29_LINK_Clr = 0x25E0, 1038 CH30_CFG_Clr = 0x25FC, 1039 CH30_LOOP_Clr = 0x2600, 1040 CH30_CTRL_Clr = 0x2604, 1041 CH30_SRC_Clr = 0x2608, 1042 CH30_DST_Clr = 0x260C, 1043 CH30_LINK_Clr = 0x2610, 1044 // Toggle registers 1045 IPVERSION_Tgl = 0x3000, 1046 EN_Tgl = 0x3004, 1047 CTRL_Tgl = 0x3008, 1048 STATUS_Tgl = 0x300C, 1049 SYNCSWSET_Tgl = 0x3010, 1050 SYNCSWCLR_Tgl = 0x3014, 1051 SYNCHWEN_Tgl = 0x3018, 1052 SYNCHWSEL_Tgl = 0x301C, 1053 SYNCSTATUS_Tgl = 0x3020, 1054 CHEN_Tgl = 0x3024, 1055 CHDIS_Tgl = 0x3028, 1056 CHSTATUS_Tgl = 0x302C, 1057 CHBUSY_Tgl = 0x3030, 1058 CHDONE_Tgl = 0x3034, 1059 DBGHALT_Tgl = 0x3038, 1060 SWREQ_Tgl = 0x303C, 1061 REQDIS_Tgl = 0x3040, 1062 REQPEND_Tgl = 0x3044, 1063 LINKLOAD_Tgl = 0x3048, 1064 REQCLEAR_Tgl = 0x304C, 1065 IF_Tgl = 0x3050, 1066 IEN_Tgl = 0x3054, 1067 CH0_CFG_Tgl = 0x305C, 1068 CH0_LOOP_Tgl = 0x3060, 1069 CH0_CTRL_Tgl = 0x3064, 1070 CH0_SRC_Tgl = 0x3068, 1071 CH0_DST_Tgl = 0x306C, 1072 CH0_LINK_Tgl = 0x3070, 1073 CH1_CFG_Tgl = 0x308C, 1074 CH1_LOOP_Tgl = 0x3090, 1075 CH1_CTRL_Tgl = 0x3094, 1076 CH1_SRC_Tgl = 0x3098, 1077 CH1_DST_Tgl = 0x309C, 1078 CH1_LINK_Tgl = 0x30A0, 1079 CH2_CFG_Tgl = 0x30BC, 1080 CH2_LOOP_Tgl = 0x30C0, 1081 CH2_CTRL_Tgl = 0x30C4, 1082 CH2_SRC_Tgl = 0x30C8, 1083 CH2_DST_Tgl = 0x30CC, 1084 CH2_LINK_Tgl = 0x30D0, 1085 CH3_CFG_Tgl = 0x30EC, 1086 CH3_LOOP_Tgl = 0x30F0, 1087 CH3_CTRL_Tgl = 0x30F4, 1088 CH3_SRC_Tgl = 0x30F8, 1089 CH3_DST_Tgl = 0x30FC, 1090 CH3_LINK_Tgl = 0x3100, 1091 CH4_CFG_Tgl = 0x311C, 1092 CH4_LOOP_Tgl = 0x3120, 1093 CH4_CTRL_Tgl = 0x3124, 1094 CH4_SRC_Tgl = 0x3128, 1095 CH4_DST_Tgl = 0x312C, 1096 CH4_LINK_Tgl = 0x3130, 1097 CH5_CFG_Tgl = 0x314C, 1098 CH5_LOOP_Tgl = 0x3150, 1099 CH5_CTRL_Tgl = 0x3154, 1100 CH5_SRC_Tgl = 0x3158, 1101 CH5_DST_Tgl = 0x315C, 1102 CH5_LINK_Tgl = 0x3160, 1103 CH6_CFG_Tgl = 0x317C, 1104 CH6_LOOP_Tgl = 0x3180, 1105 CH6_CTRL_Tgl = 0x3184, 1106 CH6_SRC_Tgl = 0x3188, 1107 CH6_DST_Tgl = 0x318C, 1108 CH6_LINK_Tgl = 0x3190, 1109 CH7_CFG_Tgl = 0x31AC, 1110 CH7_LOOP_Tgl = 0x31B0, 1111 CH7_CTRL_Tgl = 0x31B4, 1112 CH7_SRC_Tgl = 0x31B8, 1113 CH7_DST_Tgl = 0x31BC, 1114 CH7_LINK_Tgl = 0x31C0, 1115 CH8_CFG_Tgl = 0x31DC, 1116 CH8_LOOP_Tgl = 0x31E0, 1117 CH8_CTRL_Tgl = 0x31E4, 1118 CH8_SRC_Tgl = 0x31E8, 1119 CH8_DST_Tgl = 0x31EC, 1120 CH8_LINK_Tgl = 0x31F0, 1121 CH9_CFG_Tgl = 0x320C, 1122 CH9_LOOP_Tgl = 0x3210, 1123 CH9_CTRL_Tgl = 0x3214, 1124 CH9_SRC_Tgl = 0x3218, 1125 CH9_DST_Tgl = 0x321C, 1126 CH9_LINK_Tgl = 0x3220, 1127 CH10_CFG_Tgl = 0x323C, 1128 CH10_LOOP_Tgl = 0x3240, 1129 CH10_CTRL_Tgl = 0x3244, 1130 CH10_SRC_Tgl = 0x3248, 1131 CH10_DST_Tgl = 0x324C, 1132 CH10_LINK_Tgl = 0x3250, 1133 CH11_CFG_Tgl = 0x326C, 1134 CH11_LOOP_Tgl = 0x3270, 1135 CH11_CTRL_Tgl = 0x3274, 1136 CH11_SRC_Tgl = 0x3278, 1137 CH11_DST_Tgl = 0x327C, 1138 CH11_LINK_Tgl = 0x3280, 1139 CH12_CFG_Tgl = 0x329C, 1140 CH12_LOOP_Tgl = 0x32A0, 1141 CH12_CTRL_Tgl = 0x32A4, 1142 CH12_SRC_Tgl = 0x32A8, 1143 CH12_DST_Tgl = 0x32AC, 1144 CH12_LINK_Tgl = 0x32B0, 1145 CH13_CFG_Tgl = 0x32CC, 1146 CH13_LOOP_Tgl = 0x32D0, 1147 CH13_CTRL_Tgl = 0x32D4, 1148 CH13_SRC_Tgl = 0x32D8, 1149 CH13_DST_Tgl = 0x32DC, 1150 CH13_LINK_Tgl = 0x32E0, 1151 CH14_CFG_Tgl = 0x32FC, 1152 CH14_LOOP_Tgl = 0x3300, 1153 CH14_CTRL_Tgl = 0x3304, 1154 CH14_SRC_Tgl = 0x3308, 1155 CH14_DST_Tgl = 0x330C, 1156 CH14_LINK_Tgl = 0x3310, 1157 CH15_CFG_Tgl = 0x332C, 1158 CH15_LOOP_Tgl = 0x3330, 1159 CH15_CTRL_Tgl = 0x3334, 1160 CH15_SRC_Tgl = 0x3338, 1161 CH15_DST_Tgl = 0x333C, 1162 CH15_LINK_Tgl = 0x3340, 1163 CH16_CFG_Tgl = 0x335C, 1164 CH16_LOOP_Tgl = 0x3360, 1165 CH16_CTRL_Tgl = 0x3364, 1166 CH16_SRC_Tgl = 0x3368, 1167 CH16_DST_Tgl = 0x336C, 1168 CH16_LINK_Tgl = 0x3370, 1169 CH17_CFG_Tgl = 0x338C, 1170 CH17_LOOP_Tgl = 0x3390, 1171 CH17_CTRL_Tgl = 0x3394, 1172 CH17_SRC_Tgl = 0x3398, 1173 CH17_DST_Tgl = 0x339C, 1174 CH17_LINK_Tgl = 0x33A0, 1175 CH18_CFG_Tgl = 0x33BC, 1176 CH18_LOOP_Tgl = 0x33C0, 1177 CH18_CTRL_Tgl = 0x33C4, 1178 CH18_SRC_Tgl = 0x33C8, 1179 CH18_DST_Tgl = 0x33CC, 1180 CH18_LINK_Tgl = 0x33D0, 1181 CH19_CFG_Tgl = 0x33EC, 1182 CH19_LOOP_Tgl = 0x33F0, 1183 CH19_CTRL_Tgl = 0x33F4, 1184 CH19_SRC_Tgl = 0x33F8, 1185 CH19_DST_Tgl = 0x33FC, 1186 CH19_LINK_Tgl = 0x3400, 1187 CH20_CFG_Tgl = 0x341C, 1188 CH20_LOOP_Tgl = 0x3420, 1189 CH20_CTRL_Tgl = 0x3424, 1190 CH20_SRC_Tgl = 0x3428, 1191 CH20_DST_Tgl = 0x342C, 1192 CH20_LINK_Tgl = 0x3430, 1193 CH21_CFG_Tgl = 0x344C, 1194 CH21_LOOP_Tgl = 0x3450, 1195 CH21_CTRL_Tgl = 0x3454, 1196 CH21_SRC_Tgl = 0x3458, 1197 CH21_DST_Tgl = 0x345C, 1198 CH21_LINK_Tgl = 0x3460, 1199 CH22_CFG_Tgl = 0x347C, 1200 CH22_LOOP_Tgl = 0x3480, 1201 CH22_CTRL_Tgl = 0x3484, 1202 CH22_SRC_Tgl = 0x3488, 1203 CH22_DST_Tgl = 0x348C, 1204 CH22_LINK_Tgl = 0x3490, 1205 CH23_CFG_Tgl = 0x34AC, 1206 CH23_LOOP_Tgl = 0x34B0, 1207 CH23_CTRL_Tgl = 0x34B4, 1208 CH23_SRC_Tgl = 0x34B8, 1209 CH23_DST_Tgl = 0x34BC, 1210 CH23_LINK_Tgl = 0x34C0, 1211 CH24_CFG_Tgl = 0x34DC, 1212 CH24_LOOP_Tgl = 0x34E0, 1213 CH24_CTRL_Tgl = 0x34E4, 1214 CH24_SRC_Tgl = 0x34E8, 1215 CH24_DST_Tgl = 0x34EC, 1216 CH24_LINK_Tgl = 0x34F0, 1217 CH25_CFG_Tgl = 0x350C, 1218 CH25_LOOP_Tgl = 0x3510, 1219 CH25_CTRL_Tgl = 0x3514, 1220 CH25_SRC_Tgl = 0x3518, 1221 CH25_DST_Tgl = 0x351C, 1222 CH25_LINK_Tgl = 0x3520, 1223 CH26_CFG_Tgl = 0x353C, 1224 CH26_LOOP_Tgl = 0x3540, 1225 CH26_CTRL_Tgl = 0x3544, 1226 CH26_SRC_Tgl = 0x3548, 1227 CH26_DST_Tgl = 0x354C, 1228 CH26_LINK_Tgl = 0x3550, 1229 CH27_CFG_Tgl = 0x356C, 1230 CH27_LOOP_Tgl = 0x3570, 1231 CH27_CTRL_Tgl = 0x3574, 1232 CH27_SRC_Tgl = 0x3578, 1233 CH27_DST_Tgl = 0x357C, 1234 CH27_LINK_Tgl = 0x3580, 1235 CH28_CFG_Tgl = 0x359C, 1236 CH28_LOOP_Tgl = 0x35A0, 1237 CH28_CTRL_Tgl = 0x35A4, 1238 CH28_SRC_Tgl = 0x35A8, 1239 CH28_DST_Tgl = 0x35AC, 1240 CH28_LINK_Tgl = 0x35B0, 1241 CH29_CFG_Tgl = 0x35CC, 1242 CH29_LOOP_Tgl = 0x35D0, 1243 CH29_CTRL_Tgl = 0x35D4, 1244 CH29_SRC_Tgl = 0x35D8, 1245 CH29_DST_Tgl = 0x35DC, 1246 CH29_LINK_Tgl = 0x35E0, 1247 CH30_CFG_Tgl = 0x35FC, 1248 CH30_LOOP_Tgl = 0x3600, 1249 CH30_CTRL_Tgl = 0x3604, 1250 CH30_SRC_Tgl = 0x3608, 1251 CH30_DST_Tgl = 0x360C, 1252 CH30_LINK_Tgl = 0x3610, 1253 } 1254 1255 private enum LdmaXbarRegisters : long 1256 { 1257 XBAR_IPVERSION = 0x0000, 1258 XBAR_CH0_REQSEL = 0x0004, 1259 XBAR_CH1_REQSEL = 0x0008, 1260 XBAR_CH2_REQSEL = 0x000C, 1261 XBAR_CH3_REQSEL = 0x0010, 1262 XBAR_CH4_REQSEL = 0x0014, 1263 XBAR_CH5_REQSEL = 0x0018, 1264 XBAR_CH6_REQSEL = 0x001C, 1265 XBAR_CH7_REQSEL = 0x0020, 1266 XBAR_CH8_REQSEL = 0x0024, 1267 XBAR_CH9_REQSEL = 0x0028, 1268 XBAR_CH10_REQSEL = 0x002C, 1269 XBAR_CH11_REQSEL = 0x0030, 1270 XBAR_CH12_REQSEL = 0x0034, 1271 XBAR_CH13_REQSEL = 0x0038, 1272 XBAR_CH14_REQSEL = 0x003C, 1273 XBAR_CH15_REQSEL = 0x0040, 1274 XBAR_CH16_REQSEL = 0x0044, 1275 XBAR_CH17_REQSEL = 0x0048, 1276 XBAR_CH18_REQSEL = 0x004C, 1277 XBAR_CH19_REQSEL = 0x0050, 1278 XBAR_CH20_REQSEL = 0x0054, 1279 XBAR_CH21_REQSEL = 0x0058, 1280 XBAR_CH22_REQSEL = 0x005C, 1281 XBAR_CH23_REQSEL = 0x0060, 1282 XBAR_CH24_REQSEL = 0x0064, 1283 XBAR_CH25_REQSEL = 0x0068, 1284 XBAR_CH26_REQSEL = 0x006C, 1285 XBAR_CH27_REQSEL = 0x0070, 1286 XBAR_CH28_REQSEL = 0x0074, 1287 XBAR_CH29_REQSEL = 0x0078, 1288 XBAR_CH30_REQSEL = 0x007C, 1289 // Set registers 1290 XBAR_IPVERSION_Set = 0x1000, 1291 XBAR_CH0_REQSEL_Set = 0x1004, 1292 XBAR_CH1_REQSEL_Set = 0x1008, 1293 XBAR_CH2_REQSEL_Set = 0x100C, 1294 XBAR_CH3_REQSEL_Set = 0x1010, 1295 XBAR_CH4_REQSEL_Set = 0x1014, 1296 XBAR_CH5_REQSEL_Set = 0x1018, 1297 XBAR_CH6_REQSEL_Set = 0x101C, 1298 XBAR_CH7_REQSEL_Set = 0x1020, 1299 XBAR_CH8_REQSEL_Set = 0x1024, 1300 XBAR_CH9_REQSEL_Set = 0x1028, 1301 XBAR_CH10_REQSEL_Set = 0x102C, 1302 XBAR_CH11_REQSEL_Set = 0x1030, 1303 XBAR_CH12_REQSEL_Set = 0x1034, 1304 XBAR_CH13_REQSEL_Set = 0x1038, 1305 XBAR_CH14_REQSEL_Set = 0x103C, 1306 XBAR_CH15_REQSEL_Set = 0x1040, 1307 XBAR_CH16_REQSEL_Set = 0x1044, 1308 XBAR_CH17_REQSEL_Set = 0x1048, 1309 XBAR_CH18_REQSEL_Set = 0x104C, 1310 XBAR_CH19_REQSEL_Set = 0x1050, 1311 XBAR_CH20_REQSEL_Set = 0x1054, 1312 XBAR_CH21_REQSEL_Set = 0x1058, 1313 XBAR_CH22_REQSEL_Set = 0x105C, 1314 XBAR_CH23_REQSEL_Set = 0x1060, 1315 XBAR_CH24_REQSEL_Set = 0x1064, 1316 XBAR_CH25_REQSEL_Set = 0x1068, 1317 XBAR_CH26_REQSEL_Set = 0x106C, 1318 XBAR_CH27_REQSEL_Set = 0x1070, 1319 XBAR_CH28_REQSEL_Set = 0x1074, 1320 XBAR_CH29_REQSEL_Set = 0x1078, 1321 XBAR_CH30_REQSEL_Set = 0x107C, 1322 // Clear registers 1323 XBAR_IPVERSION_Clr = 0x2000, 1324 XBAR_CH0_REQSEL_Clr = 0x2004, 1325 XBAR_CH1_REQSEL_Clr = 0x2008, 1326 XBAR_CH2_REQSEL_Clr = 0x200C, 1327 XBAR_CH3_REQSEL_Clr = 0x2010, 1328 XBAR_CH4_REQSEL_Clr = 0x2014, 1329 XBAR_CH5_REQSEL_Clr = 0x2018, 1330 XBAR_CH6_REQSEL_Clr = 0x201C, 1331 XBAR_CH7_REQSEL_Clr = 0x2020, 1332 XBAR_CH8_REQSEL_Clr = 0x2024, 1333 XBAR_CH9_REQSEL_Clr = 0x2028, 1334 XBAR_CH10_REQSEL_Clr = 0x202C, 1335 XBAR_CH11_REQSEL_Clr = 0x2030, 1336 XBAR_CH12_REQSEL_Clr = 0x2034, 1337 XBAR_CH13_REQSEL_Clr = 0x2038, 1338 XBAR_CH14_REQSEL_Clr = 0x203C, 1339 XBAR_CH15_REQSEL_Clr = 0x2040, 1340 XBAR_CH16_REQSEL_Clr = 0x2044, 1341 XBAR_CH17_REQSEL_Clr = 0x2048, 1342 XBAR_CH18_REQSEL_Clr = 0x204C, 1343 XBAR_CH19_REQSEL_Clr = 0x2050, 1344 XBAR_CH20_REQSEL_Clr = 0x2054, 1345 XBAR_CH21_REQSEL_Clr = 0x2058, 1346 XBAR_CH22_REQSEL_Clr = 0x205C, 1347 XBAR_CH23_REQSEL_Clr = 0x2060, 1348 XBAR_CH24_REQSEL_Clr = 0x2064, 1349 XBAR_CH25_REQSEL_Clr = 0x2068, 1350 XBAR_CH26_REQSEL_Clr = 0x206C, 1351 XBAR_CH27_REQSEL_Clr = 0x2070, 1352 XBAR_CH28_REQSEL_Clr = 0x2074, 1353 XBAR_CH29_REQSEL_Clr = 0x2078, 1354 XBAR_CH30_REQSEL_Clr = 0x207C, 1355 // Toggle registers 1356 XBAR_IPVERSION_Tgl = 0x3000, 1357 XBAR_CH0_REQSEL_Tgl = 0x3004, 1358 XBAR_CH1_REQSEL_Tgl = 0x3008, 1359 XBAR_CH2_REQSEL_Tgl = 0x300C, 1360 XBAR_CH3_REQSEL_Tgl = 0x3010, 1361 XBAR_CH4_REQSEL_Tgl = 0x3014, 1362 XBAR_CH5_REQSEL_Tgl = 0x3018, 1363 XBAR_CH6_REQSEL_Tgl = 0x301C, 1364 XBAR_CH7_REQSEL_Tgl = 0x3020, 1365 XBAR_CH8_REQSEL_Tgl = 0x3024, 1366 XBAR_CH9_REQSEL_Tgl = 0x3028, 1367 XBAR_CH10_REQSEL_Tgl = 0x302C, 1368 XBAR_CH11_REQSEL_Tgl = 0x3030, 1369 XBAR_CH12_REQSEL_Tgl = 0x3034, 1370 XBAR_CH13_REQSEL_Tgl = 0x3038, 1371 XBAR_CH14_REQSEL_Tgl = 0x303C, 1372 XBAR_CH15_REQSEL_Tgl = 0x3040, 1373 XBAR_CH16_REQSEL_Tgl = 0x3044, 1374 XBAR_CH17_REQSEL_Tgl = 0x3048, 1375 XBAR_CH18_REQSEL_Tgl = 0x304C, 1376 XBAR_CH19_REQSEL_Tgl = 0x3050, 1377 XBAR_CH20_REQSEL_Tgl = 0x3054, 1378 XBAR_CH21_REQSEL_Tgl = 0x3058, 1379 XBAR_CH22_REQSEL_Tgl = 0x305C, 1380 XBAR_CH23_REQSEL_Tgl = 0x3060, 1381 XBAR_CH24_REQSEL_Tgl = 0x3064, 1382 XBAR_CH25_REQSEL_Tgl = 0x3068, 1383 XBAR_CH26_REQSEL_Tgl = 0x306C, 1384 XBAR_CH27_REQSEL_Tgl = 0x3070, 1385 XBAR_CH28_REQSEL_Tgl = 0x3074, 1386 XBAR_CH29_REQSEL_Tgl = 0x3078, 1387 XBAR_CH30_REQSEL_Tgl = 0x307C, 1388 } 1389 1390 1391 private class Channel 1392 { Channel(EFR32MG24_LDMA parent, int index)1393 public Channel(EFR32MG24_LDMA parent, int index) 1394 { 1395 this.parent = parent; 1396 Index = index; 1397 descriptor = default(Descriptor); 1398 1399 PeripheralRequestSelectRegister = new DoubleWordRegister(parent) 1400 .WithEnumField<DoubleWordRegister, SignalSelect>(0, 4, out signalSelect, name: "SIGSEL") 1401 .WithReservedBits(4, 12) 1402 .WithEnumField<DoubleWordRegister, SourceSelect>(16, 6, out sourceSelect, name: "SOURCESEL") 1403 .WithReservedBits(22, 10) 1404 ; 1405 ConfigurationRegister = new DoubleWordRegister(parent) 1406 .WithReservedBits(0, 16) 1407 .WithEnumField<DoubleWordRegister, ArbitrationSlotNumberMode>(16, 2, out arbitrationSlotNumberSelect, name: "ARBSLOTS") 1408 .WithReservedBits(18, 2) 1409 .WithEnumField<DoubleWordRegister, Sign>(20, 1, out sourceAddressIncrementSign, name: "SRCINCSIGN") 1410 .WithEnumField<DoubleWordRegister, Sign>(21, 1, out destinationAddressIncrementSign, name: "DSTINCSIGN") 1411 .WithReservedBits(22, 10) 1412 ; 1413 LoopCounterRegister = new DoubleWordRegister(parent) 1414 .WithValueField(0, 8, out loopCounter, name: "LOOPCNT") 1415 .WithReservedBits(8, 24) 1416 ; 1417 DescriptorControlWordRegister = new DoubleWordRegister(parent) 1418 .WithEnumField<DoubleWordRegister, StructureType>(0, 2, FieldMode.Read, 1419 valueProviderCallback: _ => descriptor.structureType, 1420 name: "STRUCTTYPE") 1421 .WithReservedBits(2, 1) 1422 .WithFlag(3, FieldMode.Set, 1423 writeCallback: (_, value) => descriptor.structureTransferRequest = value, 1424 name: "STRUCTREQ") 1425 .WithValueField(4, 11, 1426 writeCallback: (_, value) => descriptor.transferCount = (ushort)value, 1427 valueProviderCallback: _ => descriptor.transferCount, 1428 name: "XFERCNT") 1429 .WithFlag(15, 1430 writeCallback: (_, value) => descriptor.byteSwap = value, 1431 valueProviderCallback: _ => descriptor.byteSwap, 1432 name: "BYTESWAP") 1433 .WithEnumField<DoubleWordRegister, BlockSizeMode>(16, 4, 1434 writeCallback: (_, value) => descriptor.blockSize = value, 1435 valueProviderCallback: _ => descriptor.blockSize, 1436 name: "BLOCKSIZE") 1437 .WithFlag(20, 1438 writeCallback: (_, value) => descriptor.operationDoneInterruptFlagSetEnable = value, 1439 valueProviderCallback: _ => descriptor.operationDoneInterruptFlagSetEnable, 1440 name: "DONEIEN") 1441 .WithEnumField<DoubleWordRegister, RequestTransferMode>(21, 1, 1442 writeCallback: (_, value) => descriptor.requestTransferModeSelect = value, 1443 valueProviderCallback: _ => descriptor.requestTransferModeSelect, 1444 name: "REQMODE") 1445 .WithFlag(22, 1446 writeCallback: (_, value) => descriptor.decrementLoopCount = value, 1447 valueProviderCallback: _ => descriptor.decrementLoopCount, 1448 name: "DECLOOPCNT") 1449 .WithFlag(23, 1450 writeCallback: (_, value) => descriptor.ignoreSingleRequests = value, 1451 valueProviderCallback: _ => descriptor.ignoreSingleRequests, 1452 name: "IGNORESREQ") 1453 .WithEnumField<DoubleWordRegister, IncrementMode>(24, 2, 1454 writeCallback: (_, value) => descriptor.sourceIncrement = value, 1455 valueProviderCallback: _ => descriptor.sourceIncrement, 1456 name: "SRCINC") 1457 .WithEnumField<DoubleWordRegister, SizeMode>(26, 2, 1458 writeCallback: (_, value) => descriptor.size = value, 1459 valueProviderCallback: _ => descriptor.size, 1460 name: "SIZE") 1461 .WithEnumField<DoubleWordRegister, IncrementMode>(28, 2, 1462 writeCallback: (_, value) => descriptor.destinationIncrement = value, 1463 valueProviderCallback: _ => descriptor.destinationIncrement, 1464 name: "DSTINC") 1465 .WithEnumField<DoubleWordRegister, AddressingMode>(30, 1, FieldMode.Read, 1466 valueProviderCallback: _ => descriptor.sourceAddressingMode, 1467 name: "SRCMODE") 1468 .WithEnumField<DoubleWordRegister, AddressingMode>(31, 1, FieldMode.Read, 1469 valueProviderCallback: _ => descriptor.destinationAddressingMode, 1470 name: "DSTMODE") 1471 .WithChangeCallback((_, __) => { if(descriptor.structureTransferRequest) LinkLoad(); }) 1472 ; 1473 DescriptorSourceDataAddressRegister = new DoubleWordRegister(parent) 1474 .WithValueField(0, 32, 1475 writeCallback: (_, value) => descriptor.sourceAddress = (uint)value, 1476 valueProviderCallback: _ => descriptor.sourceAddress, 1477 name: "SRCADDR") 1478 ; 1479 DescriptorDestinationDataAddressRegister = new DoubleWordRegister(parent) 1480 .WithValueField(0, 32, 1481 writeCallback: (_, value) => descriptor.destinationAddress = (uint)value, 1482 valueProviderCallback: _ => descriptor.destinationAddress, 1483 name: "DSTADDR") 1484 ; 1485 DescriptorLinkStructureAddressRegister = new DoubleWordRegister(parent) 1486 .WithEnumField<DoubleWordRegister, AddressingMode>(0, 1, FieldMode.Read, 1487 valueProviderCallback: _ => descriptor.linkMode, 1488 name: "LINKMODE") 1489 .WithFlag(1, 1490 writeCallback: (_, value) => descriptor.link = value, 1491 valueProviderCallback: _ => descriptor.link, 1492 name: "LINK") 1493 .WithValueField(2, 30, 1494 writeCallback: (_, value) => descriptor.linkAddress = (uint)value, 1495 valueProviderCallback: _ => descriptor.linkAddress, 1496 name: "LINKADDR") 1497 ; 1498 1499 pullTimer = new LimitTimer(parent.machine.ClockSource, 1000000, null, $"pullTimer-{Index}", 15, Direction.Ascending, false, WorkMode.Periodic, true, true); 1500 pullTimer.LimitReached += delegate 1501 { 1502 if(!RequestDisable) 1503 { 1504 StartTransferInner(); 1505 } 1506 if(!SignalIsOn || !ShouldPullSignal) 1507 { 1508 pullTimer.Enabled = false; 1509 } 1510 }; 1511 } 1512 StartFromSignal()1513 public void StartFromSignal() 1514 { 1515 if(!RequestDisable) 1516 { 1517 StartTransfer(); 1518 } 1519 } 1520 LinkLoad()1521 public void LinkLoad() 1522 { 1523 LoadDescriptor(); 1524 if(!RequestDisable && (descriptor.structureTransferRequest || SignalIsOn)) 1525 { 1526 StartTransfer(); 1527 } 1528 } 1529 StartTransfer()1530 public void StartTransfer() 1531 { 1532 if(ShouldPullSignal) 1533 { 1534 pullTimer.Enabled = true; 1535 } 1536 else 1537 { 1538 StartTransferInner(); 1539 } 1540 } 1541 Reset()1542 public void Reset() 1543 { 1544 descriptor = default(Descriptor); 1545 pullTimer.Reset(); 1546 DoneInterrupt = false; 1547 DoneInterruptEnable = false; 1548 descriptorAddress = null; 1549 requestDisable = false; 1550 enabled = false; 1551 done = false; 1552 } 1553 1554 public int Index { get; } 1555 1556 public SignalSelect Signal => signalSelect.Value; 1557 public SourceSelect Source => sourceSelect.Value; 1558 public bool IgnoreSingleRequests => descriptor.ignoreSingleRequests; 1559 public bool DoneInterrupt { get; set; } 1560 public bool DoneInterruptEnable { get; set; } 1561 public bool IRQ => DoneInterrupt && DoneInterruptEnable; 1562 1563 public DoubleWordRegister PeripheralRequestSelectRegister { get; } 1564 public DoubleWordRegister ConfigurationRegister { get; } 1565 public DoubleWordRegister LoopCounterRegister { get; } 1566 public DoubleWordRegister DescriptorControlWordRegister { get; } 1567 public DoubleWordRegister DescriptorSourceDataAddressRegister { get; } 1568 public DoubleWordRegister DescriptorDestinationDataAddressRegister { get; } 1569 public DoubleWordRegister DescriptorLinkStructureAddressRegister { get; } 1570 1571 public bool Enabled 1572 { 1573 get 1574 { 1575 return enabled; 1576 } 1577 set 1578 { 1579 if(enabled == value) 1580 { 1581 return; 1582 } 1583 enabled = value; 1584 if(enabled) 1585 { 1586 Done = false; 1587 StartTransfer(); 1588 } 1589 } 1590 } 1591 1592 public bool Done 1593 { 1594 get 1595 { 1596 return done; 1597 } 1598 1599 set 1600 { 1601 if (!done) 1602 { 1603 DoneInterrupt |= value && descriptor.operationDoneInterruptFlagSetEnable; 1604 } 1605 done = value; 1606 } 1607 } 1608 1609 public bool Busy 1610 { 1611 get 1612 { 1613 return isInProgress; 1614 } 1615 } 1616 1617 public bool RequestDisable 1618 { 1619 get 1620 { 1621 return requestDisable; 1622 } 1623 1624 set 1625 { 1626 bool oldValue = requestDisable; 1627 requestDisable = value; 1628 1629 if(oldValue && !value) 1630 { 1631 if(SignalIsOn) 1632 { 1633 StartTransfer(); 1634 } 1635 } 1636 } 1637 } 1638 StartTransferInner()1639 private void StartTransferInner() 1640 { 1641 if(isInProgress || Done) 1642 { 1643 return; 1644 } 1645 1646 isInProgress = true; 1647 var loaded = false; 1648 do 1649 { 1650 loaded = false; 1651 Transfer(); 1652 if(Done && descriptor.link) 1653 { 1654 loaded = true; 1655 LoadDescriptor(); 1656 Done = false; 1657 } 1658 } 1659 while((descriptor.structureTransferRequest && loaded) || (!Done && SignalIsOn)); 1660 1661 isInProgress = false; 1662 if (Done) 1663 { 1664 pullTimer.Enabled = false; 1665 } 1666 } 1667 LoadDescriptor()1668 private void LoadDescriptor() 1669 { 1670 var address = LinkStructureAddress; 1671 if(descriptorAddress.HasValue && descriptor.linkMode == AddressingMode.Relative) 1672 { 1673 address += descriptorAddress.Value; 1674 } 1675 var data = parent.machine.SystemBus.ReadBytes(address, DescriptorSize); 1676 descriptorAddress = address; 1677 descriptor = Packet.Decode<Descriptor>(data); 1678 #if DEBUG 1679 parent.Log(LogLevel.Noisy, "Channel #{0} data {1}", Index, BitConverter.ToString(data)); 1680 parent.Log(LogLevel.Debug, "Channel #{0} Loaded {1}", Index, descriptor.PrettyString); 1681 #endif 1682 } 1683 Transfer()1684 private void Transfer() 1685 { 1686 switch(descriptor.structureType) 1687 { 1688 case StructureType.Transfer: 1689 var request = new Request( 1690 source: new Place(descriptor.sourceAddress), 1691 destination: new Place(descriptor.destinationAddress), 1692 size: Bytes, 1693 readTransferType: SizeAsTransferType, 1694 writeTransferType: SizeAsTransferType, 1695 sourceIncrementStep: SourceIncrement, 1696 destinationIncrementStep: DestinationIncrement 1697 ); 1698 parent.Log(LogLevel.Debug, "Channel #{0} Performing Transfer", Index); 1699 parent.engine.IssueCopy(request); 1700 if(descriptor.requestTransferModeSelect == RequestTransferMode.Block) 1701 { 1702 var blockSizeMultiplier = Math.Min(TransferCount, BlockSizeMultiplier); 1703 parent.Log(LogLevel.Debug, "Channel #{0} TransferCount={1} BlockSizeMultiplier={2}", Index, TransferCount, BlockSizeMultiplier); 1704 if(blockSizeMultiplier == TransferCount) 1705 { 1706 Done = true; 1707 descriptor.transferCount = 0; 1708 } 1709 else 1710 { 1711 descriptor.transferCount -= blockSizeMultiplier; 1712 } 1713 descriptor.sourceAddress += SourceIncrement * blockSizeMultiplier; 1714 descriptor.destinationAddress += DestinationIncrement * blockSizeMultiplier; 1715 } 1716 else 1717 { 1718 Done = true; 1719 } 1720 break; 1721 case StructureType.Synchronize: 1722 parent.Log(LogLevel.Warning, "Channel #{0} Synchronize is not implemented.", Index); 1723 break; 1724 case StructureType.Write: 1725 parent.Log(LogLevel.Warning, "Channel #{0} Write is not implemented.", Index); 1726 break; 1727 default: 1728 parent.Log(LogLevel.Error, "Channel #{0} Invalid structure type value. No action was performed.", Index); 1729 return; 1730 } 1731 parent.UpdateInterrupts(); 1732 } 1733 1734 private bool ShouldPullSignal 1735 { 1736 get 1737 { 1738 // if this returns true for the selected source and signal 1739 // then the signal will be periodically pulled instead of waiting 1740 // for an rising edge 1741 switch(Source) 1742 { 1743 case SourceSelect.None: 1744 return false; 1745 case SourceSelect.LDMAXBAR: 1746 switch(Signal) 1747 { 1748 case SignalSelect.LDMAXBAR_DMA_PRSREQ0: 1749 case SignalSelect.LDMAXBAR_DMA_PRSREQ1: 1750 return false; 1751 default: 1752 goto default; 1753 } 1754 case SourceSelect.IADC0: 1755 switch(Signal) 1756 { 1757 case SignalSelect.IADC0_DMA_IADC_SCAN: 1758 case SignalSelect.IADC0_DMA_IADC_SINGLE: 1759 return false; 1760 default: 1761 goto default; 1762 } 1763 case SourceSelect.VDAC0: 1764 case SourceSelect.VDAC1: 1765 switch(Signal) 1766 { 1767 case SignalSelect.VDAC0_DMA_CH0_REQ: 1768 case SignalSelect.VDAC0_DMA_CH1_REQ: 1769 return false; 1770 default: 1771 goto default; 1772 } 1773 case SourceSelect.USART0: 1774 switch(Signal) 1775 { 1776 case SignalSelect.USART0_DMA_RXDATAV: 1777 return false; 1778 case SignalSelect.USART0_DMA_TXBL: 1779 case SignalSelect.USART0_DMA_TXEMPTY: 1780 return true; 1781 default: 1782 goto default; 1783 } 1784 case SourceSelect.EUSART0: 1785 case SourceSelect.EUSART1: 1786 switch(Signal) 1787 { 1788 case SignalSelect.EUSART0_DMA_RXFL: 1789 return false; 1790 case SignalSelect.EUSART0_DMA_TXFL: 1791 return true; 1792 default: 1793 goto default; 1794 } 1795 case SourceSelect.I2C0: 1796 case SourceSelect.I2C1: 1797 switch(Signal) 1798 { 1799 case SignalSelect.I2C0_DMA_RXDATAV: 1800 return false; 1801 case SignalSelect.I2C0_DMA_TXBL: 1802 return true; 1803 default: 1804 goto default; 1805 } 1806 case SourceSelect.TIMER0: 1807 case SourceSelect.TIMER1: 1808 case SourceSelect.TIMER2: 1809 case SourceSelect.TIMER3: 1810 case SourceSelect.TIMER4: 1811 switch(Signal) 1812 { 1813 case SignalSelect.TIMER0_DMA_CC0: 1814 case SignalSelect.TIMER0_DMA_CC1: 1815 case SignalSelect.TIMER0_DMA_CC2: 1816 case SignalSelect.TIMER0_DMA_UFOF: 1817 return false; 1818 default: 1819 goto default; 1820 } 1821 case SourceSelect.MSC: 1822 switch(Signal) 1823 { 1824 case SignalSelect.MSC_DMA_WDATA: 1825 return false; 1826 default: 1827 goto default; 1828 } 1829 default: 1830 parent.Log(LogLevel.Error, "Channel #{0} Invalid Source (0x{1:X}) and Signal (0x{2:X}) pair.", Index, Source, Signal); 1831 return false; 1832 } 1833 } 1834 } 1835 1836 private uint BlockSizeMultiplier 1837 { 1838 get 1839 { 1840 switch(descriptor.blockSize) 1841 { 1842 case BlockSizeMode.Unit1: 1843 case BlockSizeMode.Unit2: 1844 return 1u << (byte)descriptor.blockSize; 1845 case BlockSizeMode.Unit3: 1846 return 3; 1847 case BlockSizeMode.Unit4: 1848 return 4; 1849 case BlockSizeMode.Unit6: 1850 return 6; 1851 case BlockSizeMode.Unit8: 1852 return 8; 1853 case BlockSizeMode.Unit16: 1854 return 16; 1855 case BlockSizeMode.Unit32: 1856 case BlockSizeMode.Unit64: 1857 case BlockSizeMode.Unit128: 1858 case BlockSizeMode.Unit256: 1859 case BlockSizeMode.Unit512: 1860 case BlockSizeMode.Unit1024: 1861 return 1u << ((byte)descriptor.blockSize - 4); 1862 case BlockSizeMode.All: 1863 return TransferCount; 1864 default: 1865 parent.Log(LogLevel.Warning, "Channel #{0} Invalid Block Size Mode value.", Index); 1866 return 0; 1867 } 1868 } 1869 } 1870 1871 private bool SignalIsOn 1872 { 1873 get 1874 { 1875 var number = ((int)Source << 4) | (int)Signal; 1876 return parent.signals.Contains(number) || (!IgnoreSingleRequests && parent.signals.Contains(number | 1 << 12)); 1877 } 1878 } 1879 1880 private uint TransferCount => (uint)descriptor.transferCount + 1; 1881 private ulong LinkStructureAddress => (ulong)descriptor.linkAddress << 2; 1882 1883 private uint SourceIncrement => descriptor.sourceIncrement == IncrementMode.None ? 0u : ((1u << (byte)descriptor.size) << (byte)descriptor.sourceIncrement); 1884 private uint DestinationIncrement => descriptor.destinationIncrement == IncrementMode.None ? 0u : ((1u << (byte)descriptor.size) << (byte)descriptor.destinationIncrement); 1885 private TransferType SizeAsTransferType => (TransferType)(1 << (byte)descriptor.size); 1886 private int Bytes => (int)(descriptor.requestTransferModeSelect == RequestTransferMode.All ? TransferCount : Math.Min(TransferCount, BlockSizeMultiplier)) << (byte)descriptor.size; 1887 1888 private Descriptor descriptor; 1889 private ulong? descriptorAddress; 1890 private bool requestDisable; 1891 private bool enabled; 1892 private bool done; 1893 1894 // Accesses to sysubs may cause changes in signals, but we should ignore those during active transaction 1895 private bool isInProgress; 1896 1897 private IEnumRegisterField<SignalSelect> signalSelect; 1898 private IEnumRegisterField<SourceSelect> sourceSelect; 1899 private IEnumRegisterField<ArbitrationSlotNumberMode> arbitrationSlotNumberSelect; 1900 private IEnumRegisterField<Sign> sourceAddressIncrementSign; 1901 private IEnumRegisterField<Sign> destinationAddressIncrementSign; 1902 private IValueRegisterField loopCounter; 1903 1904 private readonly EFR32MG24_LDMA parent; 1905 private readonly LimitTimer pullTimer; 1906 1907 protected readonly int DescriptorSize = Packet.CalculateLength<Descriptor>(); 1908 1909 private enum ArbitrationSlotNumberMode 1910 { 1911 One = 0, 1912 Two = 1, 1913 Four = 2, 1914 Eight = 3, 1915 } 1916 1917 private enum Sign 1918 { 1919 Positive = 0, 1920 Negative = 1, 1921 } 1922 1923 protected enum StructureType : uint 1924 { 1925 Transfer = 0, 1926 Synchronize = 1, 1927 Write = 2, 1928 } 1929 1930 protected enum BlockSizeMode : uint 1931 { 1932 Unit1 = 0, 1933 Unit2 = 1, 1934 Unit3 = 2, 1935 Unit4 = 3, 1936 Unit6 = 4, 1937 Unit8 = 5, 1938 Unit16 = 7, 1939 Unit32 = 9, 1940 Unit64 = 10, 1941 Unit128 = 11, 1942 Unit256 = 12, 1943 Unit512 = 13, 1944 Unit1024 = 14, 1945 All = 15, 1946 } 1947 1948 protected enum RequestTransferMode : uint 1949 { 1950 Block = 0, 1951 All = 1, 1952 } 1953 1954 protected enum IncrementMode : uint 1955 { 1956 One = 0, 1957 Two = 1, 1958 Four = 2, 1959 None = 3, 1960 } 1961 1962 protected enum SizeMode : uint 1963 { 1964 Byte = 0, 1965 HalfWord = 1, 1966 Word = 2, 1967 } 1968 1969 protected enum AddressingMode : uint 1970 { 1971 Absolute = 0, 1972 Relative = 1, 1973 } 1974 1975 [LeastSignificantByteFirst] 1976 private struct Descriptor 1977 { 1978 public string PrettyString => $@"Descriptor {{ 1979 structureType: {structureType}, 1980 structureTransferRequest: {structureTransferRequest}, 1981 transferCount: {transferCount + 1}, 1982 byteSwap: {byteSwap}, 1983 blockSize: {blockSize}, 1984 operationDoneInterruptFlagSetEnable: {operationDoneInterruptFlagSetEnable}, 1985 requestTransferModeSelect: {requestTransferModeSelect}, 1986 decrementLoopCount: {decrementLoopCount}, 1987 ignoreSingleRequests: {ignoreSingleRequests}, 1988 sourceIncrement: {sourceIncrement}, 1989 size: {size}, 1990 destinationIncrement: {destinationIncrement}, 1991 sourceAddressingMode: {sourceAddressingMode}, 1992 destinationAddressingMode: {destinationAddressingMode}, 1993 sourceAddress: 0x{sourceAddress:X}, 1994 destinationAddress: 0x{destinationAddress:X}, 1995 linkMode: {linkMode}, 1996 link: {link}, 1997 linkAddress: 0x{(linkAddress << 2):X} 1998 }}"; 1999 2000 // Some of this fields are read only via sysbus, but can be loaded from memory 2001 #pragma warning disable 649 2002 [PacketField, Offset(bytes: 0 << 2, bits: 0), Width(2)] 2003 public StructureType structureType; 2004 [PacketField, Offset(bytes: 0 << 2, bits: 3), Width(1)] 2005 public bool structureTransferRequest; 2006 [PacketField, Offset(bytes: 0 << 2, bits: 4), Width(11)] 2007 public uint transferCount; 2008 [PacketField, Offset(bytes: 0 << 2, bits: 15), Width(1)] 2009 public bool byteSwap; 2010 [PacketField, Offset(bytes: 0 << 2, bits: 16), Width(4)] 2011 public BlockSizeMode blockSize; 2012 [PacketField, Offset(bytes: 0 << 2, bits: 20), Width(1)] 2013 public bool operationDoneInterruptFlagSetEnable; 2014 [PacketField, Offset(bytes: 0 << 2, bits: 21), Width(1)] 2015 public RequestTransferMode requestTransferModeSelect; 2016 [PacketField, Offset(bytes: 0 << 2, bits: 22), Width(1)] 2017 public bool decrementLoopCount; 2018 [PacketField, Offset(bytes: 0 << 2, bits: 23), Width(1)] 2019 public bool ignoreSingleRequests; 2020 [PacketField, Offset(bytes: 0 << 2, bits: 24), Width(2)] 2021 public IncrementMode sourceIncrement; 2022 [PacketField, Offset(bytes: 0 << 2, bits: 26), Width(2)] 2023 public SizeMode size; 2024 [PacketField, Offset(bytes: 0 << 2, bits: 28), Width(2)] 2025 public IncrementMode destinationIncrement; 2026 [PacketField, Offset(bytes: 0 << 2, bits: 30), Width(1)] 2027 public AddressingMode sourceAddressingMode; 2028 [PacketField, Offset(bytes: 0 << 2, bits: 31), Width(1)] 2029 public AddressingMode destinationAddressingMode; 2030 [PacketField, Offset(bytes: 1 << 2, bits: 0), Width(32)] 2031 public uint sourceAddress; 2032 [PacketField, Offset(bytes: 2 << 2, bits: 0), Width(32)] 2033 public uint destinationAddress; 2034 [PacketField, Offset(bytes: 3 << 2, bits: 0), Width(1)] 2035 public AddressingMode linkMode; 2036 [PacketField, Offset(bytes: 3 << 2, bits: 1), Width(1)] 2037 public bool link; 2038 [PacketField, Offset(bytes: 3 << 2, bits: 2), Width(30)] 2039 public uint linkAddress; 2040 #pragma warning restore 649 2041 } 2042 } 2043 } 2044 }