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.Linq; 9 using System.Collections.Generic; 10 using Antmicro.Renode.Core; 11 using Antmicro.Renode.Core.CAN; 12 using Antmicro.Renode.Core.Structure.Registers; 13 using Antmicro.Renode.Logging; 14 using Antmicro.Renode.Utilities; 15 using Antmicro.Renode.Peripherals.Bus; 16 using Antmicro.Renode.Peripherals.Memory; 17 using Antmicro.Renode.Hooks; 18 using Antmicro.Renode.Utilities.Packets; 19 using Antmicro.Renode.Time; 20 21 namespace Antmicro.Renode.Peripherals.CAN 22 { 23 [AllowedTranslations(AllowedTranslation.ByteToDoubleWord | AllowedTranslation.WordToDoubleWord)] 24 public partial class MCAN : IDoubleWordPeripheral, IKnownSize, ICAN 25 { MCAN(IMachine machine, IMultibyteWritePeripheral messageRAM)26 public MCAN(IMachine machine, IMultibyteWritePeripheral messageRAM) 27 { 28 this.machine = machine; 29 this.messageRAM = messageRAM; 30 Line0 = new GPIO(); 31 Line1 = new GPIO(); 32 Calibration = new GPIO(); 33 BuildRegisterMapView(); 34 registers = new DoubleWordRegisterCollection(this, BuildRegisterMap()); 35 BuildStructuredViews(); 36 UpdateInterrupts(); 37 } 38 OnFrameReceived(CANMessageFrame rxMessage)39 public void OnFrameReceived(CANMessageFrame rxMessage) 40 { 41 HandleRxInner(rxMessage); 42 UpdateInterrupts(); 43 } 44 Reset()45 public void Reset() 46 { 47 registers.Reset(); 48 } 49 ReadDoubleWord(long offset)50 public uint ReadDoubleWord(long offset) 51 { 52 return registers.Read(offset); 53 } 54 WriteDoubleWord(long offset, uint value)55 public void WriteDoubleWord(long offset, uint value) 56 { 57 registers.Write(offset, value); 58 } 59 BuildRegisterMap()60 private Dictionary<long, DoubleWordRegister> BuildRegisterMap() 61 { 62 var registerMap = new Dictionary<long, DoubleWordRegister>(); 63 64 registerMap[(long)Register.CoreReleaseRegister] = new DoubleWordRegister(this, resetValue: 0x33191121) 65 .WithTag("DAY", 0, 8) 66 .WithTag("MON", 8, 8) 67 .WithTag("YEAR", 16, 4) 68 .WithTag("SUBSTEP", 20, 4) 69 .WithTag("STEP", 24, 4) 70 .WithTag("REL", 28, 4); 71 72 registerMap[(long)Register.EndianRegister] = new DoubleWordRegister(this, resetValue: 0x87654321) 73 .WithTag("ETV", 0, 32); 74 75 registerMap[(long)Register.CustomerRegister] = new DoubleWordRegister(this) 76 .WithReservedBits(0, 32); 77 78 registerMap[(long)Register.DataBitTimingAndPrescalerRegister] = new DoubleWordRegister(this, resetValue: 0x00000A33) 79 .WithTag("DSJW", 0, 4) 80 .WithTag("DTSEG", 4, 4) 81 .WithTag("DTSEG1", 8, 5) 82 .WithReservedBits(13, 3) 83 .WithTag("DBRP", 16, 5) 84 .WithReservedBits(21, 2) 85 .WithTaggedFlag("TDC", 23) 86 .WithReservedBits(24, 8); 87 88 registerMap[(long)Register.TestRegister] = new DoubleWordRegister(this) 89 .WithReservedBits(0, 4) 90 .WithFlag(4, out rv.TestRegister.LoopBackMode, writeCallback: (oldVal, newVal) => 91 { 92 if(!IsProtectedWrite && newVal != oldVal) 93 { 94 this.Log(LogLevel.Warning, "Trying to write to protected field. Ignoring."); 95 rv.TestRegister.LoopBackMode.Value = oldVal; 96 return; 97 } 98 }, name: "LBCK") 99 .WithTag("TX", 5, 2) 100 .WithTaggedFlag("RX", 7) 101 .WithValueField(8, 5, out rv.TestRegister.TxBufferNumberPrepared, FieldMode.Read, name: "TXBNP") 102 .WithFlag(13, out rv.TestRegister.PreparedValid, FieldMode.Read, name: "PVAL") 103 .WithReservedBits(14, 2) 104 .WithValueField(16, 5, out rv.TestRegister.TxBufferNumberStarted, FieldMode.Read, name: "TXBNS") 105 .WithFlag(21, out rv.TestRegister.StartedValid, FieldMode.Read, name: "SVAL") 106 .WithReservedBits(22, 10); 107 108 registerMap[(long)Register.RAMWatchdog] = new DoubleWordRegister(this) 109 .WithTag("WDC", 0, 8) 110 .WithTag("WDV", 8, 8) 111 .WithReservedBits(16, 16); 112 113 registerMap[(long)Register.CCControlRegister] = new DoubleWordRegister(this, resetValue: 0x1) 114 .WithFlags(0, 16, out rv.CCControlRegister.ControlFields, writeCallback: (idx, oldVal, newVal) => 115 { 116 // Handle fields that have meaningful side effects from the point of emulation. Other fields are treated as flags. 117 switch((Control)idx) 118 { 119 case Control.Initialization: 120 { 121 if(!newVal) 122 { 123 rv.CCControlRegister.ControlFields[(int)Control.ConfigurationChangeEnable].Value = false; 124 this.Log(LogLevel.Debug, "Software initialization is finished"); 125 } 126 break; 127 } 128 case Control.ConfigurationChangeEnable: 129 { 130 if(!rv.CCControlRegister.ControlFields[(int)Control.Initialization].Value && rv.CCControlRegister.ControlFields[(int)Control.ConfigurationChangeEnable].Value) // oldVal was reset through resetting INIT 131 { 132 rv.CCControlRegister.ControlFields[idx].Value = oldVal; 133 return; 134 } 135 if(newVal) 136 { 137 registerMap[(long)Register.HighPriorityMessageStatus].Reset(); 138 registerMap[(long)Register.RxFIFO0Status].Reset(); 139 registerMap[(long)Register.RxFIFO1Status].Reset(); 140 registerMap[(long)Register.TxFIFOQueueStatus].Reset(); 141 registerMap[(long)Register.TxBufferRequestPending].Reset(); 142 registerMap[(long)Register.TxBufferTransmissionOccurred].Reset(); 143 registerMap[(long)Register.TxBufferCancellationFinished].Reset(); 144 registerMap[(long)Register.TxEventFIFOStatus].Reset(); 145 } 146 break; 147 } 148 case Control.BusMonitoringMode: 149 case Control.TestModeEnable: 150 { 151 if(newVal) 152 { 153 if(!IsProtectedWrite && newVal != oldVal) 154 { 155 this.Log(LogLevel.Warning, "Trying to write to protected field. Ignoring."); 156 rv.CCControlRegister.ControlFields[idx].Value = oldVal; 157 return; 158 } 159 } 160 else 161 { 162 if((Control)idx == Control.TestModeEnable) 163 { 164 registerMap[(long)Register.TestRegister].Reset(); 165 } 166 } 167 break; 168 } 169 case Control.DisableAutomaticRetransmission: 170 { 171 if(!IsProtectedWrite && newVal != oldVal) 172 { 173 this.Log(LogLevel.Warning, "Trying to write to protected field. Ignoring."); 174 rv.CCControlRegister.ControlFields[idx].Value = oldVal; 175 return; 176 } 177 break; 178 } 179 } 180 }) 181 .WithReservedBits(16, 16); 182 183 registerMap[(long)Register.NominalBitTimingAndPrescalerRegister] = new DoubleWordRegister(this, resetValue: 0x06000A03) 184 .WithTag("NTSEG2", 0, 7) 185 .WithReservedBits(7, 1) 186 .WithTag("NTSEG1", 8, 8) 187 .WithTag("NBRP", 16, 9) 188 .WithTag("NSJW", 25, 7); 189 190 registerMap[(long)Register.TimestampCounterConfiguration] = new DoubleWordRegister(this) 191 .WithTag("TSS", 0, 2) 192 .WithReservedBits(2, 14) 193 .WithTag("TCP", 16, 4) 194 .WithReservedBits(20, 12); 195 196 registerMap[(long)Register.TimestampCounterValue] = new DoubleWordRegister(this) 197 .WithTag("TSC", 0, 16) 198 .WithReservedBits(16, 16); 199 200 registerMap[(long)Register.TimeoutCounterConfiguration] = new DoubleWordRegister(this, resetValue: 0xFFFF0000) 201 .WithTaggedFlag("ETOC", 0) 202 .WithTag("TOS", 1, 2) 203 .WithReservedBits(3, 13) 204 .WithTag("TOP", 16, 16); 205 206 registerMap[(long)Register.TimeoutCounterValue] = new DoubleWordRegister(this, resetValue: 0x0000FFFF) 207 .WithTag("TOC", 0, 16) 208 .WithReservedBits(16, 16); 209 210 registerMap[(long)Register.ErrorCounterRegister] = new DoubleWordRegister(this) 211 .WithTag("TEC", 0, 8) 212 .WithTag("REC", 8, 7) 213 .WithTaggedFlag("RP", 15) 214 .WithTag("CEL", 16, 8) 215 .WithReservedBits(24, 8); 216 217 registerMap[(long)Register.ProtocolStatusRegister] = new DoubleWordRegister(this, resetValue: 0x00000707) 218 .WithEnumField(0, 3, out rv.ProtocolStatusRegister.LastErrorCode, readCallback: (_, __) => 219 { 220 rv.ProtocolStatusRegister.LastErrorCode.Value = LastErrorCode.NoChange; // Reset on read 221 }, name: "LEC") 222 .WithEnumField(3, 2, out rv.ProtocolStatusRegister.Activity, name: "ACT") 223 .WithTaggedFlag("EP", 5) 224 .WithTaggedFlag("EW", 6) 225 .WithTaggedFlag("BO", 7) 226 .WithTag("DLEC", 8, 3) 227 .WithTaggedFlag("RESI", 11) 228 .WithTaggedFlag("RBRS", 12) 229 .WithFlag(13, out rv.ProtocolStatusRegister.ReceivedCANFDMessage, readCallback: (_, __) => 230 { 231 rv.ProtocolStatusRegister.ReceivedCANFDMessage.Value = false; // Reset on read 232 }, name: "RFDF") 233 .WithTaggedFlag("PXE", 14) 234 .WithReservedBits(15, 1) 235 .WithTag("TDCV", 16, 7) 236 .WithReservedBits(23, 9); 237 238 registerMap[(long)Register.TransmitterDelayCompensationRegister] = new DoubleWordRegister(this) 239 .WithTag("TDCF", 0, 7) 240 .WithReservedBits(7, 1) 241 .WithTag("TDCO", 8, 7) 242 .WithReservedBits(15, 17); 243 244 registerMap[(long)Register.InterruptRegister] = new DoubleWordRegister(this) 245 .WithFlags(0, 30, out rv.InterruptRegister.InterruptFlags, FieldMode.Read | FieldMode.WriteOneToClear, writeCallback: (idx, oldVal, newVal) => 246 { 247 if(!newVal) 248 { 249 return; 250 } 251 252 switch((Interrupt)idx) 253 { 254 case Interrupt.RxFIFO0MessageLost: 255 { 256 rxFIFO0.MessageLost.Value = false; 257 break; 258 } 259 case Interrupt.RxFIFO1MessageLost: 260 { 261 rxFIFO1.MessageLost.Value = false; 262 break; 263 } 264 case Interrupt.TxEventFIFOElementLost: 265 { 266 txEventFIFO.ElementLost.Value = false; 267 break; 268 } 269 } 270 }) 271 .WithWriteCallback((_, __) => UpdateInterrupts()); 272 273 registerMap[(long)Register.InterruptEnable] = new DoubleWordRegister(this) 274 .WithFlags(0, 30, out rv.InterruptEnable.InterruptEnableFlags) 275 .WithWriteCallback((_, __) => UpdateInterrupts()); 276 277 registerMap[(long)Register.InterruptLineSelect] = new DoubleWordRegister(this) 278 .WithFlags(0, 30, out rv.InterruptLineSelect.InterruptLineSelectFlags) 279 .WithWriteCallback((_, __) => UpdateInterrupts()); 280 281 registerMap[(long)Register.InterruptLineEnable] = new DoubleWordRegister(this) 282 .WithFlag(0, out rv.InterruptLineEnable.EnableInterruptLine0, name: "EINT0") 283 .WithFlag(1, out rv.InterruptLineEnable.EnableInterruptLine1, name: "EINT1") 284 .WithWriteCallback((_, __) => UpdateInterrupts()); 285 286 registerMap[(long)Register.GlobalFilterConfiguration] = new DoubleWordRegister(this) 287 .WithFlag(0, out rv.GlobalFilterConfiguration.RejectRemoteFramesExtended, name: "RRFE") 288 .WithFlag(1, out rv.GlobalFilterConfiguration.RejectRemoteFramesStandard, name: "RRFS") 289 .WithEnumField(2, 2, out rv.GlobalFilterConfiguration.AcceptNonMatchingFramesExtended, name: "ANFE") 290 .WithEnumField(4, 2, out rv.GlobalFilterConfiguration.AcceptNonMatchingFramesStandard, name: "ANFS"); 291 292 registerMap[(long)Register.StandardIDFilterConfiguration] = new DoubleWordRegister(this) 293 .WithReservedBits(0, 2) 294 .WithValueField(2, 14, out rv.StandardIDFilterConfiguration.FilterListStandardStartAddress, name: "FLSSA") 295 .WithValueField(16, 8, out rv.StandardIDFilterConfiguration.ListSizeStandard, name: "LSS") 296 .WithReservedBits(24, 8); 297 298 registerMap[(long)Register.ExtendedIDFilterConfiguration] = new DoubleWordRegister(this) 299 .WithReservedBits(0, 2) 300 .WithValueField(2, 14, out rv.ExtendedIDFilterConfiguration.FilterListExtendedStartAddress, name: "FLESA") 301 .WithValueField(16, 7, out rv.ExtendedIDFilterConfiguration.ListSizeExtended, name: "LSE") 302 .WithReservedBits(23, 9); 303 304 registerMap[(long)Register.ExtendedIdANDMask] = new DoubleWordRegister(this, resetValue: 0x1FFFFFFF) 305 .WithValueField(0, 29, out rv.ExtendedIdANDMask.ExtendedIDANDMask, name: "EIDM") 306 .WithReservedBits(29, 3); 307 308 registerMap[(long)Register.HighPriorityMessageStatus] = new DoubleWordRegister(this) 309 .WithValueField(0, 6, valueField: out rv.HighPriorityMessageStatus.BufferIndex, name: "BIDX") 310 .WithEnumField(6, 2, out rv.HighPriorityMessageStatus.MessageStorageIndicator, name: "MSI") 311 .WithValueField(8, 7, out rv.HighPriorityMessageStatus.FilterIndex, name: "FIDX") 312 .WithFlag(15, out rv.HighPriorityMessageStatus.FilterList, name: "FLST") 313 .WithReservedBits(16, 16); 314 315 registerMap[(long)Register.NewData1] = new DoubleWordRegister(this) 316 .WithFlags(0, 32, out rv.NewData1.NewData1Flags, FieldMode.Read | FieldMode.WriteOneToClear, name: "newData1x"); 317 318 registerMap[(long)Register.NewData2] = new DoubleWordRegister(this) 319 .WithFlags(0, 32, out rv.NewData2.NewData2Flags, FieldMode.Read | FieldMode.WriteOneToClear, name: "newData2x"); 320 321 registerMap[(long)Register.RxFIFO0Configuration] = new DoubleWordRegister(this) 322 .WithReservedBits(0, 2) 323 .WithValueField(2, 14, out rv.RxFIFO0Configuration.RxFIFO0StartAddress, name: "F0SA") 324 .WithValueField(16, 7, out rv.RxFIFO0Configuration.RxFIFO0Size, name: "F0S") 325 .WithReservedBits(23, 1) 326 .WithValueField(24, 7, out rv.RxFIFO0Configuration.RxFIFO0Watermark, name: "F0WM") 327 .WithEnumField(31, 1, out rv.RxFIFO0Configuration.FIFO0OperationMode, name: "F0OM"); 328 329 registerMap[(long)Register.RxFIFO0Status] = new DoubleWordRegister(this) 330 .WithValueField(0, 7, FieldMode.Read, valueProviderCallback: _ => rxFIFO0.RxFIFOFillLevel, name: "F0FL") 331 .WithReservedBits(7, 1) 332 .WithValueField(8, 6, out rv.RxFIFO0Status.RxFIFO0GetIndex, FieldMode.Read, name: "F0GI") 333 .WithReservedBits(14, 2) 334 .WithValueField(16, 6, out rv.RxFIFO0Status.RxFIFO0PutIndex, FieldMode.Read, name: "F0PI") 335 .WithReservedBits(22, 2) 336 .WithFlag(24, out rv.RxFIFO0Status.RxFIFO0Full, FieldMode.Read, name: "F0F") 337 .WithFlag(25, out rv.RxFIFO0Status.RxFIFO0MessageLost, FieldMode.Read, name: "RF0L") 338 .WithReservedBits(26, 6); 339 340 registerMap[(long)Register.RxFIFO0Acknowledge] = new DoubleWordRegister(this) 341 .WithValueField(0, 6, out rv.RxFIFO0Acknowledge.RxFIFO0AcknowledgeIndex, writeCallback: (_, newVal) => 342 { 343 rxFIFO0.RxFIFOGetIndex = newVal + 1; 344 rxFIFO0.Full.Value = false; 345 }, name: "F0AI") 346 .WithReservedBits(6, 26); 347 348 registerMap[(long)Register.RxBufferConfiguration] = new DoubleWordRegister(this) 349 .WithReservedBits(0, 2) 350 .WithValueField(2, 14, out rv.RxBufferConfiguration.RxBufferStartAddress, name: "RBSA") 351 .WithReservedBits(16, 16); 352 353 registerMap[(long)Register.RxFIFO1Configuration] = new DoubleWordRegister(this) 354 .WithReservedBits(0, 2) 355 .WithValueField(2, 14, out rv.RxFIFO1Configuration.RxFIFO1StartAddress, name: "F1SA") 356 .WithValueField(16, 7, out rv.RxFIFO1Configuration.RxFIFO1Size, name: "F1S") 357 .WithReservedBits(23, 1) 358 .WithValueField(24, 7, out rv.RxFIFO1Configuration.RxFIFO1Watermark, name: "F1WM") 359 .WithEnumField(31, 1, out rv.RxFIFO1Configuration.FIFO1OperationMode, name: "F1OM"); 360 361 registerMap[(long)Register.RxFIFO1Status] = new DoubleWordRegister(this) 362 .WithValueField(0, 7, FieldMode.Read, valueProviderCallback: _ => rxFIFO1.RxFIFOFillLevel, name: "F0FL") 363 .WithReservedBits(7, 1) 364 .WithValueField(8, 6, out rv.RxFIFO1Status.RxFIFO1GetIndex, FieldMode.Read, name: "F0GI") 365 .WithReservedBits(14, 2) 366 .WithValueField(16, 6, out rv.RxFIFO1Status.RxFIFO1PutIndex, FieldMode.Read, name: "F0PI") 367 .WithReservedBits(22, 2) 368 .WithFlag(24, out rv.RxFIFO1Status.RxFIFO1Full, FieldMode.Read, name: "F0F") 369 .WithFlag(25, out rv.RxFIFO1Status.RxFIFO1MessageLost, FieldMode.Read, name: "RF0L") 370 .WithReservedBits(26, 4) 371 .WithEnumField(30, 2, out rv.RxFIFO1Status.DebugMessageStatus, FieldMode.Read, name: "DMS"); 372 373 registerMap[(long)Register.RxFIFO1Acknowledge] = new DoubleWordRegister(this) 374 .WithValueField(0, 6, out rv.RxFIFO1Acknowledge.RxFIFO1AcknowledgeIndex, writeCallback: (_, newVal) => 375 { 376 rxFIFO1.RxFIFOGetIndex = newVal + 1; 377 rxFIFO1.Full.Value = false; 378 }, name: "F1AI") 379 .WithReservedBits(6, 26); 380 381 registerMap[(long)Register.RxBufferFIFOElementSizeConfiguration] = new DoubleWordRegister(this) 382 .WithValueField(0, 3, out rv.RxBufferFIFOElementSizeConfiguration.RxFIFO0DataFieldSize, name: "F0DS") 383 .WithReservedBits(3, 1) 384 .WithValueField(4, 3, out rv.RxBufferFIFOElementSizeConfiguration.RxFIFO1DataFieldSize, name: "F1DS") 385 .WithReservedBits(7, 1) 386 .WithValueField(8, 3, out rv.RxBufferFIFOElementSizeConfiguration.RxBufferDataFieldSize, name: "RBDS") 387 .WithReservedBits(11, 21); 388 389 registerMap[(long)Register.TxBufferConfiguration] = new DoubleWordRegister(this) 390 .WithReservedBits(0, 2) 391 .WithValueField(2, 14, out rv.TxBufferConfiguration.TxBuffersStartAddress, name: "TBSA") // start address is aligned to four bytes, hence the lowest two bits of register are reserved 392 .WithValueField(16, 6, out rv.TxBufferConfiguration.NumberOfDedicatedTxBuffers, name: "NDTB") 393 .WithReservedBits(22, 2) 394 .WithValueField(24, 6, out rv.TxBufferConfiguration.TxFIFOQueueSize, name: "TFQS") 395 .WithFlag(30, out rv.TxBufferConfiguration.TxFIFOQueueMode, name: "TFQM") 396 .WithReservedBits(31, 1); 397 398 registerMap[(long)Register.TxFIFOQueueStatus] = new DoubleWordRegister(this) 399 .WithValueField(0, 6, FieldMode.Read, valueProviderCallback: _ => txFIFOQueue.FreeLevel, name: "TFFL") 400 .WithReservedBits(6, 2) 401 .WithValueField(8, 5, out rv.TxFIFOQueueStatus.TxFIFOGetIndex, FieldMode.Read, valueProviderCallback: _ => txFIFOQueue.GetIndex, name: "TFGI") 402 .WithReservedBits(13, 3) 403 .WithValueField(16, 5, out rv.TxFIFOQueueStatus.TxFIFOQueuePutIndex, FieldMode.Read, valueProviderCallback: _ => txFIFOQueue.PutIndex, name: "TFQPI") 404 .WithFlag(21, out rv.TxFIFOQueueStatus.TxFIFOQueueFull, FieldMode.Read, valueProviderCallback: _ => txFIFOQueue.Full, name: "TFQF") 405 .WithReservedBits(22, 10); 406 407 registerMap[(long)Register.TxBufferElementSizeConfiguration] = new DoubleWordRegister(this) 408 .WithValueField(0, 3, out rv.TxBufferElementSizeConfiguration.TxBufferDataFieldSize, name: "TBDS") 409 .WithReservedBits(3, 29); 410 411 registerMap[(long)Register.TxBufferRequestPending] = new DoubleWordRegister(this) 412 .WithFlags(0, 32, out rv.TxBufferRequestPending.TransmissionRequestPendingFlags, FieldMode.Read, name: "TRPx"); 413 414 registerMap[(long)Register.TxBufferAddRequest] = new DoubleWordRegister(this) 415 .WithFlags(0, 32, out rv.TxBufferAddRequest.AddRequestFlags, writeCallback: (idx, oldVal, newVal) => 416 { 417 if(!newVal || rv.CCControlRegister.ControlFields[(int)Control.ConfigurationChangeEnable].Value || idx >= (int)(rv.TxBufferConfiguration.NumberOfDedicatedTxBuffers.Value + rv.TxBufferConfiguration.TxFIFOQueueSize.Value)) 418 { 419 rv.TxBufferAddRequest.AddRequestFlags[idx].Value = oldVal; 420 return; 421 } 422 rv.TxBufferRequestPending.TransmissionRequestPendingFlags[idx].Value = true; 423 rv.TxBufferCancellationFinished.CancellationFinishedFlags[idx].Value = false; 424 rv.TxBufferTransmissionOccurred.TransmissionOccurredFlags[idx].Value = false; 425 426 if(!txFIFOQueue.QueueMode.Value && idx >= (int)txFIFOQueue.Offset.Value) 427 { 428 // Message added Tx FIFO 429 txFIFOQueue.PutIndex++; 430 if(txFIFOQueue.PutIndex == txFIFOQueue.GetIndex) 431 { 432 txFIFOQueue.FullRaw.Value = true; 433 this.Log(LogLevel.Warning, "Tx FIFO is full"); 434 } 435 } 436 }, name: "ARx") 437 .WithWriteCallback((oldVal, newVal) => 438 { 439 TxScan(); 440 }); 441 442 registerMap[(long)Register.TxBufferCancellationRequest] = new DoubleWordRegister(this) 443 .WithFlags(0, 32, out rv.TxBufferCancellationRequest.CancellationRequestFlags, writeCallback: (idx, oldVal, newVal) => 444 { 445 if(!newVal || rv.CCControlRegister.ControlFields[(int)Control.ConfigurationChangeEnable].Value || idx >= (int)(rv.TxBufferConfiguration.NumberOfDedicatedTxBuffers.Value + rv.TxBufferConfiguration.TxFIFOQueueSize.Value)) 446 { 447 rv.TxBufferCancellationRequest.CancellationRequestFlags[idx].Value = oldVal; 448 return; 449 } 450 rv.TxBufferRequestPending.TransmissionRequestPendingFlags[idx].Value = false; 451 rv.TxBufferCancellationRequest.CancellationRequestFlags[idx].Value = false; 452 453 if(!txFIFOQueue.QueueMode.Value && idx == (int)txFIFOQueue.GetIndex) 454 { 455 txFIFOQueue.GetIndex++; 456 txFIFOQueue.FullRaw.Value = false; 457 } 458 459 rv.TxBufferCancellationFinished.CancellationFinishedFlags[idx].Value = true; 460 }, name: "CRx") 461 .WithWriteCallback((oldVal, newVal) => 462 { 463 UpdateInterrupts(); 464 TxScan(); 465 }); 466 467 registerMap[(long)Register.TxBufferTransmissionOccurred] = new DoubleWordRegister(this) 468 .WithFlags(0, 32, out rv.TxBufferTransmissionOccurred.TransmissionOccurredFlags, name: "TOx"); 469 470 registerMap[(long)Register.TxBufferCancellationFinished] = new DoubleWordRegister(this) 471 .WithFlags(0, 32, out rv.TxBufferCancellationFinished.CancellationFinishedFlags, name: "CFx"); 472 473 registerMap[(long)Register.TxBufferTransmissionInterruptEnable] = new DoubleWordRegister(this) 474 .WithFlags(0, 32, out rv.TxBufferTransmissionInterruptEnable.TransmissionInterruptEnableFlags, name: "TIEx"); 475 476 registerMap[(long)Register.TxBufferCancellationFinishedInterruptEnable] = new DoubleWordRegister(this) 477 .WithFlags(0, 32, out rv.TxBufferCancellationFinishedInterruptEnable.CancellationFinishedInterruptEnableFlags, name: "CFIEx"); 478 479 registerMap[(long)Register.TxEventFIFOConfiguration] = new DoubleWordRegister(this) 480 .WithReservedBits(0, 2) 481 .WithValueField(2, 14, out rv.TxEventFIFOConfiguration.EventFIFOStartAddress, name: "EFSA") 482 .WithValueField(16, 6, out rv.TxEventFIFOConfiguration.EventFIFOSize, name: "EFS") 483 .WithReservedBits(22, 2) 484 .WithValueField(24, 6, out rv.TxEventFIFOConfiguration.EventFIFOWatermark, name: "EFWM") 485 .WithReservedBits(30, 2); 486 487 registerMap[(long)Register.TxEventFIFOStatus] = new DoubleWordRegister(this) 488 .WithValueField(0, 6, FieldMode.Read, valueProviderCallback: _ => txEventFIFO.FillLevel, name: "EFFL") 489 .WithReservedBits(6, 2) 490 .WithValueField(8, 5, out rv.TxEventFIFOStatus.EventFIFOGetIndex, FieldMode.Read, name: "EFGI") 491 .WithReservedBits(13, 3) 492 .WithValueField(16, 5, out rv.TxEventFIFOStatus.EventFIFOPutIndex, FieldMode.Read, name: "EFPI") 493 .WithReservedBits(21, 3) 494 .WithFlag(24, out rv.TxEventFIFOStatus.EventFIFOFull, FieldMode.Read, name: "EFF") 495 .WithFlag(25, out rv.TxEventFIFOStatus.TxEventFIFOElementLost, FieldMode.Read, name: "TEFL") 496 .WithReservedBits(26, 6); 497 498 registerMap[(long)Register.TxEventFIFOAcknowledge] = new DoubleWordRegister(this) 499 .WithValueField(0, 5, out rv.TxEventFIFOAcknowledge.EventFIFOAcknowledgeIndex, writeCallback: (_, newVal) => 500 { 501 txEventFIFO.GetIndex = newVal + 1; 502 txEventFIFO.Full.Value = false; 503 if(txEventFIFO.FillLevel == 0) 504 { 505 rv.InterruptRegister.InterruptFlags[(int)Interrupt.TxFIFOEmpty].Value = true; 506 UpdateInterrupts(); 507 } 508 }, name: "EFAI") 509 .WithReservedBits(5, 27); 510 511 return registerMap; 512 } 513 TxScan()514 private void TxScan() 515 { 516 var bufferIdx = FindPrioritizedBuffer(out var messageID); 517 if(bufferIdx == -1) 518 { 519 return; 520 } 521 this.Log(LogLevel.Debug, "Buffer {0} with Message ID {1} will be transmitted", bufferIdx, messageID); 522 TransmitBuffer(bufferIdx); 523 } 524 525 // It scans Tx Buffers section in the Message RAM and returns index of the buffer to be transmitted next according to Tx prioritization rules. FindPrioritizedBuffer(out uint messageID)526 private int FindPrioritizedBuffer(out uint messageID) 527 { 528 var numberOfDedicatedTxBuffers = txBuffers.NumberOfDedicatedTxBuffers.Value; 529 var txFIFOQueueSize = txBuffers.TxFIFOQueueSize.Value; 530 var txFIFOQueueMode = txBuffers.TxFIFOQueueMode.Value; 531 532 var txScanMode = TxScanModeInternal.Dedicated; 533 534 if(txFIFOQueueSize == 0) 535 { 536 txScanMode = TxScanModeInternal.Dedicated; 537 } 538 else if(numberOfDedicatedTxBuffers == 0) 539 { 540 if(txFIFOQueueMode) 541 { 542 txScanMode = TxScanModeInternal.Queue; 543 } 544 else 545 { 546 txScanMode = TxScanModeInternal.FIFO; 547 } 548 } 549 else 550 { 551 if(txFIFOQueueMode) 552 { 553 txScanMode = TxScanModeInternal.MixedDedicatedQueue; 554 } 555 else 556 { 557 txScanMode = TxScanModeInternal.MixedDedicatedFIFO; 558 } 559 } 560 561 messageID = uint.MaxValue; // Message ID of selected buffer 562 var bufferNumber = -1; // Index of selected buffer 563 564 switch(txScanMode) 565 { 566 case TxScanModeInternal.Dedicated: 567 { 568 bufferNumber = ScanDedicatedTxBuffers(out messageID); 569 break; 570 } 571 case TxScanModeInternal.FIFO: 572 { 573 bufferNumber = ScanTxFIFO(out messageID); 574 break; 575 } 576 case TxScanModeInternal.Queue: 577 { 578 bufferNumber = ScanTxQueue(out messageID); 579 break; 580 } 581 case TxScanModeInternal.MixedDedicatedFIFO: 582 { 583 var bufferNumber0 = ScanDedicatedTxBuffers(out var messageID0); 584 var bufferNumber1 = ScanTxFIFO(out var messageID1); 585 messageID = messageID0 <= messageID1 ? messageID0 : messageID1; 586 bufferNumber = messageID0 <= messageID1 ? bufferNumber0 : bufferNumber1; 587 break; 588 } 589 case TxScanModeInternal.MixedDedicatedQueue: 590 { 591 var bufferNumber0 = ScanDedicatedTxBuffers(out var messageID0); 592 var bufferNumber1 = ScanTxQueue(out var messageID1); 593 messageID = messageID0 <= messageID1 ? messageID0 : messageID1; 594 bufferNumber = messageID0 <= messageID1 ? bufferNumber0 : bufferNumber1; 595 break; 596 } 597 } 598 599 return bufferNumber; 600 } 601 ScanDedicatedTxBuffers(out uint messageID)602 private int ScanDedicatedTxBuffers(out uint messageID) 603 { 604 var startAddress = (int)(txBuffers.StartAddress.Value << 2); 605 var dataSizeInBytes = MapDataFieldSizeToDataBytes(txBuffers.DataFieldSize.Value); 606 var bufferSizeInBytes = BufferElementHeaderSizeInBytes + dataSizeInBytes; 607 608 messageID = uint.MaxValue; // Message ID of selected buffer 609 var bufferNumber = -1; // Index of selected buffer 610 611 for(var i = 0; i < (int)txBuffers.NumberOfDedicatedTxBuffers.Value; i++) 612 { 613 if(!rv.TxBufferRequestPending.TransmissionRequestPendingFlags[i].Value) 614 { 615 continue; 616 } 617 618 var offset = startAddress + i * bufferSizeInBytes; 619 byte[] scanBytes = messageRAM.ReadBytes((long)offset, 4); 620 var scanRecord = Packet.Decode<TxScanBufferAndEventFIFOCommonHeader>(scanBytes); 621 622 var id = scanRecord.Identifier; 623 id = scanRecord.ExtendedIdentifier ? id : (id >> 18); 624 625 if(id < messageID || (i == 0 && id == uint.MaxValue)) 626 { 627 // Found a message with higher priority 628 messageID = id; 629 bufferNumber = i; 630 } 631 } 632 633 return bufferNumber; 634 } 635 ScanTxFIFO(out uint messageID)636 private int ScanTxFIFO(out uint messageID) 637 { 638 var startAddress = (int)(txBuffers.StartAddress.Value << 2); 639 var dataSizeInBytes = MapDataFieldSizeToDataBytes(txBuffers.DataFieldSize.Value); 640 var bufferSizeInBytes = BufferElementHeaderSizeInBytes + dataSizeInBytes; 641 642 messageID = uint.MaxValue; // Message ID of selected buffer 643 var bufferNumber = -1; // Index of selected buffer 644 645 var getIndex = (int)txFIFOQueue.GetIndex; 646 647 if(!rv.TxBufferRequestPending.TransmissionRequestPendingFlags[getIndex].Value) 648 { 649 return bufferNumber; 650 } 651 652 var offset = startAddress + getIndex * bufferSizeInBytes; 653 byte[] scanBytes = messageRAM.ReadBytes((long)offset, 4); 654 var scanRecord = Packet.Decode<TxScanBufferAndEventFIFOCommonHeader>(scanBytes); 655 656 var id = scanRecord.Identifier; 657 id = scanRecord.ExtendedIdentifier ? id : (id >> 18); 658 659 messageID = id; 660 bufferNumber = getIndex; 661 662 return bufferNumber; 663 } 664 ScanTxQueue(out uint messageID)665 private int ScanTxQueue(out uint messageID) 666 { 667 var startAddress = (int)(txBuffers.StartAddress.Value << 2); 668 var dataSizeInBytes = MapDataFieldSizeToDataBytes(txBuffers.DataFieldSize.Value); 669 var bufferSizeInBytes = BufferElementHeaderSizeInBytes + dataSizeInBytes; 670 671 messageID = uint.MaxValue; // Message ID of selected buffer 672 var bufferNumber = -1; // Index of selected buffer 673 674 for(var i = (int)txFIFOQueue.Offset.Value; i < (int)(txFIFOQueue.Offset.Value + txFIFOQueue.Size.Value); i++) 675 { 676 if(!rv.TxBufferRequestPending.TransmissionRequestPendingFlags[i].Value) 677 { 678 continue; 679 } 680 681 var offset = startAddress + i * bufferSizeInBytes; 682 byte[] scanBytes = messageRAM.ReadBytes((long)offset, 4); 683 var scanRecord = Packet.Decode<TxScanBufferAndEventFIFOCommonHeader>(scanBytes); 684 685 var id = scanRecord.Identifier; 686 id = scanRecord.ExtendedIdentifier ? id : (id >> 18); 687 688 if(id < messageID || (i == 0 && id == uint.MaxValue)) 689 { 690 // Found a message with higher priority 691 messageID = id; 692 bufferNumber = i; 693 } 694 } 695 696 return bufferNumber; 697 } 698 TransmitBuffer(int i)699 private void TransmitBuffer(int i) 700 { 701 var txBufferDataSize = MapDataFieldSizeToDataBytes(rv.TxBufferElementSizeConfiguration.TxBufferDataFieldSize.Value); 702 var bufferSizeInBytes = BufferElementHeaderSizeInBytes + txBufferDataSize; 703 704 if(!rv.TxBufferRequestPending.TransmissionRequestPendingFlags[i].Value) 705 { 706 return; // it was cancelled 707 } 708 709 var addr = (rv.TxBufferConfiguration.TxBuffersStartAddress.Value << 2) + (ulong)(i * bufferSizeInBytes); 710 var frameBytes = messageRAM.ReadBytes((long)addr, (int)bufferSizeInBytes); 711 var frame = Packet.Decode<TxBufferElementHeader>(frameBytes); 712 var data = frameBytes.Skip(BufferElementHeaderSizeInBytes).Take((int)txBufferDataSize).ToArray(); 713 714 var dlcBufferSizeInBytes = MapDataLengthCodeToDataBytesCount(frame.DataLengthCode); 715 Array.Resize(ref data, dlcBufferSizeInBytes); 716 717 if(txBufferDataSize < dlcBufferSizeInBytes) 718 { 719 // The bytes not defined by the Tx Buffer are transmitted as “0xCC” (padding bytes). 720 for(var j = (int)txBufferDataSize; j < dlcBufferSizeInBytes; j++) 721 { 722 data[j] = PaddingByte; 723 } 724 } 725 726 var id = frame.Identifier; 727 id = frame.ExtendedIdentifier ? id : (id >> 18); // 11 or 29 bit identifier, a standard identifier is stored in ID[28:18] 728 var canMessage = new CANMessageFrame(id, data, frame.ExtendedIdentifier, frame.RemoteTransmissionRequest, frame.FDFormat, frame.BitRateSwitch); 729 730 var wasTransmitted = TransmitMessage(canMessage); 731 if(wasTransmitted) 732 { 733 HandleTransmitSuccess(i, frame); 734 } 735 736 machine.LocalTimeSource.ExecuteInNearestSyncedState(__ => 737 { 738 if(wasTransmitted) 739 { 740 UpdateInterrupts(); 741 TxScan(); 742 } 743 }, true); 744 } 745 HandleTransmitSuccess(int i, TxBufferElementHeader frame)746 private void HandleTransmitSuccess(int i, TxBufferElementHeader frame) 747 { 748 rv.TxBufferRequestPending.TransmissionRequestPendingFlags[i].Value = false; 749 rv.ProtocolStatusRegister.LastErrorCode.Value = LastErrorCode.NoError; 750 HandleTxEvent(frame); 751 752 if(!txFIFOQueue.QueueMode.Value && i >= (int)txFIFOQueue.Offset.Value) 753 { 754 // Transmitted message belonged to Tx FIFO 755 txFIFOQueue.GetIndex++; 756 txFIFOQueue.FullRaw.Value = false; 757 } 758 759 rv.TxBufferTransmissionOccurred.TransmissionOccurredFlags[i].Value = true; 760 } 761 HandleTxEvent(TxBufferElementHeader txHeader)762 private void HandleTxEvent(TxBufferElementHeader txHeader) 763 { 764 if(rv.CCControlRegister.ControlFields[(int)Control.WideMessageMarker].Value) 765 { 766 this.Log(LogLevel.Warning, "Wide Message Marker requires an external Time Stamping Unit (TSU) that is not available"); 767 return; 768 } 769 770 var txFIFOElement = new TxEventFIFOElement 771 { 772 Identifier = txHeader.Identifier, 773 RemoteTransmissionRequest = txHeader.RemoteTransmissionRequest, 774 ExtendedIdentifier = txHeader.ExtendedIdentifier, 775 ErrorStateIndicator = txHeader.ErrorStateIndicator, 776 TxTimestamp = 0, 777 DataLengthCode = txHeader.DataLengthCode, 778 BitRateSwitch = txHeader.BitRateSwitch, 779 FDFormat = txHeader.FDFormat, 780 EventType = 0b10, // Tx event 781 MessageMarker = txHeader.MessageMarkerLow 782 }; 783 784 StoreInTxEventFIFO(txFIFOElement); 785 } 786 StoreInTxEventFIFO(TxEventFIFOElement txFIFOElement)787 private void StoreInTxEventFIFO(TxEventFIFOElement txFIFOElement) 788 { 789 if(txEventFIFO.Full.Value || txEventFIFO.Size.Value == 0) 790 { 791 txEventFIFO.InterruptElementLost.Value = true; 792 txEventFIFO.ElementLost.Value = true; 793 return; 794 } 795 796 var addr = (txEventFIFO.StartAddress.Value << 2) + txEventFIFO.PutIndex * (ulong)TxEventFIFOElementSizeInBytes; 797 var txFIFOElementBytes = Packet.Encode(txFIFOElement); 798 799 messageRAM.WriteBytes((long)addr, txFIFOElementBytes, 0, txFIFOElementBytes.Length); 800 801 txEventFIFO.PutIndex += 1; 802 txEventFIFO.Full.Value = txEventFIFO.PutIndexRaw == txEventFIFO.GetIndexRaw; 803 804 var watermarkReached = (txEventFIFO.Watermark.Value > 0) && (txEventFIFO.FillLevel >= txEventFIFO.Watermark.Value); 805 if(watermarkReached) 806 { 807 txEventFIFO.InterruptWatermarkReached.Value = true; 808 } 809 810 if(txEventFIFO.Full.Value) 811 { 812 txEventFIFO.InterruptFull.Value = true; 813 } 814 815 txEventFIFO.InterruptNewEntry.Value = true; 816 } 817 TransmitMessage(CANMessageFrame canMessage)818 private bool TransmitMessage(CANMessageFrame canMessage) 819 { 820 var transmitted = true; 821 var fs = FrameSent; 822 if(fs != null) 823 { 824 fs.Invoke(canMessage); 825 } 826 else 827 { 828 transmitted = false; 829 this.Log(LogLevel.Warning, "FrameSent is not initialized. Is the controller connected to medium?"); 830 } 831 832 return transmitted; 833 } 834 HandleRxInner(CANMessageFrame rxMessage)835 private void HandleRxInner(CANMessageFrame rxMessage) 836 { 837 var match = FilterMessage(rxMessage); 838 if(!match) 839 { 840 this.Log(LogLevel.Debug, "Received CAN message discarded"); 841 } 842 } 843 FilterMessage(CANMessageFrame rxMessage)844 private bool FilterMessage(CANMessageFrame rxMessage) 845 { 846 var isExtended = rxMessage.ExtendedFormat; 847 var isRemote = rxMessage.RemoteFrame; 848 var id = rxMessage.Id; 849 850 rv.ProtocolStatusRegister.ReceivedCANFDMessage.Value = rxMessage.FDFormat; 851 852 var filterConfig = isExtended ? filterConfigurationExtended : filterConfigurationStandard; 853 854 var rejectRemoteFrames = filterConfig.RejectRemoteFrames.Value; 855 if(isRemote && rejectRemoteFrames) 856 { 857 return false; // discard remote frame 858 } 859 860 var listSize = filterConfig.ListSize.Value; 861 var receiveFilterListEnabled = listSize > 0; 862 863 var acceptNonMatchingFrames = filterConfig.AcceptNonMatchingFrames.Value; 864 var rejectNonMatchingFrames = acceptNonMatchingFrames != NonMatchingFrameTarget.AcceptInRxFIFO0 && acceptNonMatchingFrames != NonMatchingFrameTarget.AcceptInRxFIFO1; 865 if(!receiveFilterListEnabled && rejectNonMatchingFrames) 866 { 867 return false; // discard non-matching frame 868 } 869 870 if(receiveFilterListEnabled) 871 { 872 var startAddress = filterConfig.FilterListStartAddress.Value; 873 var filterSizeInBytes = isExtended ? ExtendedFilterSizeInBytes : StandardFilterSizeInBytes; 874 875 var match = false; 876 for(var i = 0; i < (int)listSize; i++) 877 { 878 var addr = (long)(startAddress << 2) + i * filterSizeInBytes; 879 var filterBytes = messageRAM.ReadBytes(addr, filterSizeInBytes); 880 var filter = DecodeFilterElement(isExtended, filterBytes); 881 882 if(filter.FilterElementConfiguration == FilterElementConfiguration.DisableFilter) 883 { 884 continue; // filter element disabled 885 } 886 else if(filter.FilterElementConfiguration == FilterElementConfiguration.RxBufferOrDebugMessageOnMatch) 887 { 888 var rxBufferIdx = BitHelper.GetValue(filter.ID2, 0, 6); 889 var newDataFlags = rxBufferIdx < 32 ? rv.NewData1.NewData1Flags : rv.NewData2.NewData2Flags; 890 if(newDataFlags[rxBufferIdx % 32].Value) 891 { 892 // While an Rx Buffer’s New Data flag is set, a Message ID Filter Element 893 // referencing this specific RxBuffer will not match. 894 continue; 895 } 896 } 897 898 match = MatchFilterElement(isExtended, id, filter); 899 900 if(!match) 901 { 902 continue; 903 } 904 905 HandleMatchedFilter(filter, i, rxMessage); 906 907 return true; 908 } 909 910 if(!match && rejectNonMatchingFrames) 911 { 912 return false; // discard non-matching frame 913 } 914 } 915 916 AcceptNonMatchingFrame(acceptNonMatchingFrames, rxMessage); 917 918 return true; 919 } 920 DecodeFilterElement(bool extended, byte[] filterBytes)921 private MessageIDFilterElement DecodeFilterElement(bool extended, byte[] filterBytes) 922 { 923 if(extended) 924 { 925 var filter = Packet.Decode<ExtendedMessageIDFilterElement>(filterBytes); 926 return new MessageIDFilterElement 927 { 928 ID1 = filter.ExtendedFilterID1, 929 ID2 = filter.ExtendedFilterID2, 930 SyncMessage = filter.ExtendedSyncMessage, 931 FilterElementConfiguration = filter.ExtendedFilterElementConfiguration, 932 FilterType = filter.ExtendedFilterType, 933 IsExtended = true 934 }; 935 } 936 else 937 { 938 var filter = Packet.Decode<StandardMessageIDFilterElement>(filterBytes); 939 return new MessageIDFilterElement 940 { 941 ID1 = filter.StandardFilterID1, 942 ID2 = filter.StandardFilterID2, 943 SyncMessage = filter.StandardSyncMessage, 944 FilterElementConfiguration = filter.StandardFilterElementConfiguration, 945 FilterType = filter.StandardFilterType, 946 IsExtended = false 947 }; 948 } 949 } 950 MatchFilterElement(bool isExtended, uint id, MessageIDFilterElement filter)951 private bool MatchFilterElement(bool isExtended, uint id, MessageIDFilterElement filter) 952 { 953 switch(filter.FilterType) 954 { 955 case FilterType.Range: 956 { 957 if(!isExtended) 958 { 959 if(id >= filter.ID1 && id <= filter.ID2) 960 { 961 return true; 962 } 963 } 964 else 965 { 966 var idMasked = id & (uint)rv.ExtendedIdANDMask.ExtendedIDANDMask.Value; 967 if(idMasked >= filter.ID1 && idMasked <= filter.ID2) 968 { 969 return true; 970 } 971 } 972 break; 973 } 974 case FilterType.DualID: 975 { 976 if((id == filter.ID1) || (id == filter.ID2)) 977 { 978 return true; 979 } 980 break; 981 } 982 case FilterType.Classic: 983 { 984 if((id & filter.ID2) == (filter.ID1 & filter.ID2)) 985 { 986 return true; 987 } 988 break; 989 } 990 case FilterType.RangeWithoutMask: 991 { 992 if(!isExtended) 993 { 994 break; 995 } 996 if(id >= filter.ID1 && id <= filter.ID2) 997 { 998 return true; 999 } 1000 break; 1001 } 1002 default: 1003 { 1004 this.Log(LogLevel.Warning, "Invalid filter type."); 1005 break; 1006 } 1007 } 1008 return false; 1009 } 1010 HandleMatchedFilter(MessageIDFilterElement filter, int idx, CANMessageFrame rxMessage)1011 private void HandleMatchedFilter(MessageIDFilterElement filter, int idx, CANMessageFrame rxMessage) 1012 { 1013 var rxBufferElementHeader = new RxBufferElementHeader 1014 { 1015 Identifier = rxMessage.ExtendedFormat ? rxMessage.Id : rxMessage.Id << 18, 1016 RemoteTransmissionRequest = rxMessage.RemoteFrame, 1017 ExtendedIdentifier = rxMessage.ExtendedFormat, 1018 ErrorStateIndicator = false, 1019 RxTimestamp = 0, 1020 DataLengthCode = MapDataBytesCountToDataLengthCode(k: rxMessage.Data.Length), 1021 BitRateSwitch = rxMessage.BitRateSwitch, 1022 FDFormat = rxMessage.FDFormat, 1023 FilterIndex = (byte)idx, 1024 AcceptedNonMatchingFrame = false 1025 }; 1026 1027 switch(filter.FilterElementConfiguration) 1028 { 1029 case FilterElementConfiguration.RxFIFO0OnMatch: 1030 { 1031 var wasStored = StoreInRxFIFO(0, rxBufferElementHeader, rxMessage.Data); 1032 break; 1033 } 1034 case FilterElementConfiguration.RxFIFO1OnMatch: 1035 { 1036 var wasStored = StoreInRxFIFO(1, rxBufferElementHeader, rxMessage.Data); 1037 break; 1038 } 1039 case FilterElementConfiguration.RejectIDOnMatch: 1040 { 1041 if(filter.SyncMessage) 1042 { 1043 this.Log(LogLevel.Warning, "Reject ID if filter matches is not intended to be used with Sync messages"); 1044 } 1045 break; 1046 } 1047 case FilterElementConfiguration.SetPriorityOnMatch: 1048 { 1049 if(filter.SyncMessage) 1050 { 1051 this.Log(LogLevel.Warning, "Setting priority on filter match is not intended to be used with Sync messages"); 1052 return; 1053 } 1054 1055 rv.HighPriorityMessageStatus.MessageStorageIndicator.Value = MessageStorageIndicator.NoFIFOselected; 1056 rv.HighPriorityMessageStatus.FilterIndex.Value = (ulong)idx; 1057 rv.HighPriorityMessageStatus.FilterList.Value = filter.IsExtended; 1058 1059 rv.InterruptRegister.InterruptFlags[(int)Interrupt.HighPriorityMessage].Value = true; 1060 break; 1061 } 1062 case FilterElementConfiguration.SetPriorityAndRxFIFO0OnMatch: 1063 { 1064 var wasStored = StoreInRxFIFO(0, rxBufferElementHeader, rxMessage.Data); 1065 1066 if(wasStored) 1067 { 1068 rv.HighPriorityMessageStatus.BufferIndex.Value = rv.RxFIFO0Status.RxFIFO0PutIndex.Value - 1; // Put Index was already incremented for new message so subtract one 1069 rv.HighPriorityMessageStatus.MessageStorageIndicator.Value = MessageStorageIndicator.MessageInFIFO0; 1070 } 1071 else 1072 { 1073 rv.HighPriorityMessageStatus.MessageStorageIndicator.Value = MessageStorageIndicator.FIFOMessageLost; 1074 } 1075 rv.HighPriorityMessageStatus.FilterIndex.Value = (ulong)idx; 1076 rv.HighPriorityMessageStatus.FilterList.Value = filter.IsExtended; 1077 1078 rv.InterruptRegister.InterruptFlags[(int)Interrupt.HighPriorityMessage].Value = true; 1079 break; 1080 } 1081 case FilterElementConfiguration.SetPriorityAndRxFIFO1OnMatch: 1082 { 1083 var wasStored = StoreInRxFIFO(1, rxBufferElementHeader, rxMessage.Data); 1084 1085 if(wasStored) 1086 { 1087 rv.HighPriorityMessageStatus.BufferIndex.Value = rv.RxFIFO1Status.RxFIFO1PutIndex.Value - 1; // Put Index was already incremented for new message so subtract one 1088 rv.HighPriorityMessageStatus.MessageStorageIndicator.Value = MessageStorageIndicator.MessageInFIFO1; 1089 } 1090 else 1091 { 1092 rv.HighPriorityMessageStatus.MessageStorageIndicator.Value = MessageStorageIndicator.FIFOMessageLost; 1093 } 1094 rv.HighPriorityMessageStatus.FilterIndex.Value = (ulong)idx; 1095 rv.HighPriorityMessageStatus.FilterList.Value = filter.IsExtended; 1096 1097 rv.InterruptRegister.InterruptFlags[(int)Interrupt.HighPriorityMessage].Value = true; 1098 break; 1099 } 1100 case FilterElementConfiguration.RxBufferOrDebugMessageOnMatch: 1101 { 1102 StoreInRxBuffer(rxBufferElementHeader, rxMessage.Data, filter); 1103 break; 1104 } 1105 default: 1106 { 1107 this.Log(LogLevel.Warning, "Invalid Filter Element Configuration"); 1108 break; 1109 } 1110 } 1111 } 1112 AcceptNonMatchingFrame(NonMatchingFrameTarget frameTarget, CANMessageFrame rxMessage)1113 private void AcceptNonMatchingFrame(NonMatchingFrameTarget frameTarget, CANMessageFrame rxMessage) 1114 { 1115 var rxBufferElementHeader = new RxBufferElementHeader 1116 { 1117 Identifier = rxMessage.ExtendedFormat ? rxMessage.Id : rxMessage.Id << 18, 1118 RemoteTransmissionRequest = rxMessage.RemoteFrame, 1119 ExtendedIdentifier = rxMessage.ExtendedFormat, 1120 ErrorStateIndicator = false, 1121 RxTimestamp = 0, 1122 DataLengthCode = MapDataBytesCountToDataLengthCode(k: rxMessage.Data.Length), 1123 BitRateSwitch = rxMessage.BitRateSwitch, 1124 FDFormat = rxMessage.FDFormat, 1125 FilterIndex = 0, 1126 AcceptedNonMatchingFrame = true 1127 }; 1128 1129 switch(frameTarget) 1130 { 1131 case NonMatchingFrameTarget.AcceptInRxFIFO0: 1132 { 1133 StoreInRxFIFO(0, rxBufferElementHeader, rxMessage.Data); 1134 break; 1135 } 1136 case NonMatchingFrameTarget.AcceptInRxFIFO1: 1137 { 1138 StoreInRxFIFO(1, rxBufferElementHeader, rxMessage.Data); 1139 break; 1140 } 1141 default: 1142 { 1143 this.Log(LogLevel.Warning, "Non-matching frame was rejected"); 1144 break; 1145 } 1146 } 1147 } 1148 StoreInRxFIFO(uint idx, RxBufferElementHeader rxHeader, byte[] rxData)1149 private bool StoreInRxFIFO(uint idx, RxBufferElementHeader rxHeader, byte[] rxData) 1150 { 1151 if(idx >= NumberOfRxFIFOs) 1152 { 1153 this.Log(LogLevel.Warning, "Only FIFO0 or FIFO1 are available"); 1154 } 1155 1156 var rxFIFO = idx == 0 ? rxFIFO0 : rxFIFO1; 1157 1158 if(rxFIFO.Size.Value == 0) 1159 { 1160 rxFIFO.InterruptMessageLost.Value = true; 1161 rxFIFO.MessageLost.Value = true; 1162 return false; // Message is discarded 1163 } 1164 1165 var dataFieldInBytes = MapDataFieldSizeToDataBytes(rxFIFO.DataFieldSize.Value); 1166 var fifoElementSizeInBytes = BufferElementHeaderSizeInBytes + dataFieldInBytes; 1167 1168 var addr = (rxFIFO.StartAddress.Value << 2) + rxFIFO.RxFIFOPutIndex * (ulong)fifoElementSizeInBytes; 1169 var rxHeaderBytes = Packet.Encode(rxHeader); 1170 1171 switch(rxFIFO.OperationMode.Value) 1172 { 1173 case FIFOOperationMode.Overwrite: 1174 { 1175 if(rxFIFO.Full.Value) 1176 { 1177 rxFIFO.RxFIFOGetIndex += 1; 1178 } 1179 break; 1180 } 1181 case FIFOOperationMode.Blocking: 1182 default: 1183 { 1184 if(rxFIFO.Full.Value) 1185 { 1186 rxFIFO.InterruptMessageLost.Value = true; 1187 rxFIFO.MessageLost.Value = true; 1188 return false; // Message is discarded 1189 } 1190 break; 1191 } 1192 } 1193 1194 messageRAM.WriteBytes((long)addr, rxHeaderBytes, 0, rxHeaderBytes.Length); 1195 messageRAM.WriteBytes((long)addr + rxHeaderBytes.Length, rxData, 0, rxData.Length); 1196 1197 rxFIFO.RxFIFOPutIndex += 1; 1198 rxFIFO.Full.Value = rxFIFO.RxFIFOPutIndex == rxFIFO.RxFIFOGetIndex; 1199 1200 var watermarkReached = (rxFIFO.Watermark.Value > 0) && (rxFIFO.RxFIFOFillLevel >= rxFIFO.Watermark.Value); 1201 if(watermarkReached) 1202 { 1203 rxFIFO.InterruptWatermarkReached.Value = true; 1204 } 1205 1206 if(rxFIFO.Full.Value) 1207 { 1208 rxFIFO.InterruptFull.Value = true; 1209 } 1210 1211 rxFIFO.InterruptNewMessage.Value = true; 1212 1213 return true; 1214 } 1215 StoreInRxBuffer(RxBufferElementHeader rxHeader, byte[] rxData, MessageIDFilterElement filter)1216 private void StoreInRxBuffer(RxBufferElementHeader rxHeader, byte[] rxData, MessageIDFilterElement filter) 1217 { 1218 var id2 = filter.ID2; 1219 1220 var rxBufferIdx = BitHelper.GetValue(id2, 0, 6); 1221 var filterEventPins = BitHelper.GetValue(id2, 6, 3); 1222 var target = (RxBufferOrDebugDestination)BitHelper.GetValue(id2, 9, 2); 1223 1224 var startAddress = rxBuffer.StartAddress.Value << 2; 1225 var dataFieldSize = rxBuffer.DataFieldSize.Value; 1226 1227 var dataFieldInBytes = MapDataFieldSizeToDataBytes(dataFieldSize); 1228 var bufferElementSizeInBytes = BufferElementHeaderSizeInBytes + dataFieldInBytes; 1229 1230 var addr = startAddress + rxBufferIdx * (ulong)bufferElementSizeInBytes; 1231 var rxHeaderBytes = Packet.Encode(rxHeader); 1232 1233 messageRAM.WriteBytes((long)addr, rxHeaderBytes, 0, rxHeaderBytes.Length); 1234 messageRAM.WriteBytes((long)addr + rxHeaderBytes.Length, rxData, 0, rxData.Length); 1235 1236 switch(target) 1237 { 1238 case RxBufferOrDebugDestination.StoreInRxBuffer: 1239 { 1240 var newDataFlags = rxBufferIdx < 32 ? rv.NewData1.NewData1Flags : rv.NewData2.NewData2Flags; 1241 newDataFlags[rxBufferIdx % 32].Value = true; 1242 1243 rv.InterruptRegister.InterruptFlags[(int)Interrupt.MessageStoredToDedicatedRxBuffer].Value = true; 1244 break; 1245 } 1246 case RxBufferOrDebugDestination.DebugMessageA: 1247 case RxBufferOrDebugDestination.DebugMessageB: 1248 case RxBufferOrDebugDestination.DebugMessageC: 1249 default: 1250 { 1251 this.Log(LogLevel.Warning, "DMU add-on is required to activate DMA request output after debug message is stored"); 1252 break; 1253 } 1254 } 1255 } 1256 MapDataFieldSizeToDataBytes(ulong k)1257 private int MapDataFieldSizeToDataBytes(ulong k) 1258 { 1259 if(k >= 8) 1260 { 1261 this.Log(LogLevel.Warning, "Invalid Data Field Size"); 1262 return 0; 1263 } 1264 1265 DataFieldSizeToBytesCountMap.TryGetValue(k, out var fieldSize); 1266 return fieldSize; 1267 } 1268 MapDataBytesCountToDataLengthCode(int k)1269 private byte MapDataBytesCountToDataLengthCode(int k) 1270 { 1271 if(k <= 8) 1272 { 1273 return (byte)k; 1274 } 1275 1276 if(k > 64) 1277 { 1278 this.Log(LogLevel.Warning, "Received frame has more than 64 bytes"); 1279 return 0; 1280 } 1281 var success = FDBytesCountToDataLengthCodeMap.TryGetValue(k, out var datalengthCode); 1282 1283 if(!success) 1284 { 1285 this.Log(LogLevel.Warning, "Invalid length of received frame"); 1286 return 0; 1287 } 1288 1289 return datalengthCode; 1290 } 1291 MapDataLengthCodeToDataBytesCount(int k)1292 private byte MapDataLengthCodeToDataBytesCount(int k) 1293 { 1294 if(k <= 8) 1295 { 1296 return (byte)k; 1297 } 1298 1299 if(k > 15) 1300 { 1301 this.Log(LogLevel.Warning, "Frame specfied an invalid Data Length Code"); 1302 return 0; 1303 } 1304 1305 DataLengthCodeToFDBytesCountMap.TryGetValue(k, out var fdBytesCount); 1306 return fdBytesCount; 1307 } 1308 UpdateInterrupts()1309 private void UpdateInterrupts() 1310 { 1311 var flag0 = false; 1312 var flag1 = false; 1313 1314 for(int i = 0; i < rv.TxBufferTransmissionInterruptEnable.TransmissionInterruptEnableFlags.Length; i++) 1315 { 1316 if(rv.TxBufferTransmissionInterruptEnable.TransmissionInterruptEnableFlags[i].Value && rv.TxBufferTransmissionOccurred.TransmissionOccurredFlags[i].Value) 1317 { 1318 rv.InterruptRegister.InterruptFlags[(int)Interrupt.TransmissionCompleted].Value = true; 1319 } 1320 } 1321 1322 for(int i = 0; i < rv.TxBufferCancellationFinishedInterruptEnable.CancellationFinishedInterruptEnableFlags.Length; i++) 1323 { 1324 if(rv.TxBufferCancellationFinishedInterruptEnable.CancellationFinishedInterruptEnableFlags[i].Value && rv.TxBufferCancellationFinished.CancellationFinishedFlags[i].Value) 1325 { 1326 rv.InterruptRegister.InterruptFlags[(int)Interrupt.TransmissionCancellationFinished].Value = true; 1327 } 1328 } 1329 1330 for(int i = 0; i < rv.InterruptRegister.InterruptFlags.Length; i++) 1331 { 1332 if(rv.InterruptEnable.InterruptEnableFlags[i].Value && rv.InterruptRegister.InterruptFlags[i].Value) 1333 { 1334 flag0 |= rv.InterruptLineEnable.EnableInterruptLine0.Value && !rv.InterruptLineSelect.InterruptLineSelectFlags[i].Value; 1335 flag1 |= rv.InterruptLineEnable.EnableInterruptLine1.Value && rv.InterruptLineSelect.InterruptLineSelectFlags[i].Value; 1336 } 1337 } 1338 1339 Line0.Set(flag0); 1340 Line1.Set(flag1); 1341 } 1342 } 1343 } 1344