1 // 2 // Copyright (c) 2010-2021 Antmicro 3 // Copyright (c) 2011-2015 Realtime Embedded 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 using System; 9 using Antmicro.Renode.Logging; 10 using Antmicro.Renode.Peripherals.Bus; 11 using Antmicro.Renode.Core; 12 using System.Collections.Generic; 13 using System.Collections.ObjectModel; 14 using Antmicro.Renode.Core.CAN; 15 using Antmicro.Renode.Exceptions; 16 using System.Linq; 17 18 namespace Antmicro.Renode.Peripherals.CAN 19 { 20 public class STMCAN : IDoubleWordPeripheral, ICAN, INumberedGPIOOutput 21 { STMCAN(STMCAN master = null)22 public STMCAN(STMCAN master = null) 23 { 24 // Register master CAN 25 this.master = master; 26 27 for(int i = 0; i < NumberOfRxFifos; i++) 28 { 29 RxFifo[i] = new Queue<CANMessage>(); 30 if(!IsSlave) 31 { 32 FifoFiltersPrioritized[i] = new List<FilterBank>(); 33 } 34 } 35 36 var innerConnections = new Dictionary<int, IGPIO>(); 37 for(int i = 0; i < NumberOfInterruptLines; i++) 38 { 39 innerConnections[i] = new GPIO(); 40 } 41 Connections = new ReadOnlyDictionary<int, IGPIO>(innerConnections); 42 43 registers = new DeviceRegisters(); 44 45 // Fixup receive fifo regs 46 registers.CAN_RFR[RxFifo0].SetRxFifo(RxFifo[RxFifo0]); 47 registers.CAN_RFR[RxFifo0].UpdateInterruptLine = 48 new UpdateInterruptLine(UpdateFifo0InterruptLine); 49 50 registers.CAN_RFR[RxFifo1].SetRxFifo(RxFifo[RxFifo1]); 51 registers.CAN_RFR[RxFifo1].UpdateInterruptLine = 52 new UpdateInterruptLine(UpdateFifo1InterruptLine); 53 54 if(!IsSlave) 55 { 56 FilterBanks = new FilterBank[NumberOfFilterBanks]; 57 for(int i = 0; i < NumberOfFilterBanks; i++) 58 { 59 FilterBanks[i] = new FilterBank(); 60 } 61 } 62 else 63 { 64 if(master.FilterBanks == null) 65 { 66 throw new ConstructionException("You need to construct the master first."); 67 } 68 if(master.IsSlave) 69 { 70 throw new ConstructionException("The master of this peripheral cannot be a slave to another master."); 71 } 72 FilterBanks = master.FilterBanks; 73 FifoFiltersPrioritized = master.FifoFiltersPrioritized; 74 registers.CAN_FMR = master.registers.CAN_FMR; 75 registers.CAN_FM1R = master.registers.CAN_FM1R; 76 registers.CAN_FS1R = master.registers.CAN_FS1R; 77 registers.CAN_FFA1R = master.registers.CAN_FFA1R; 78 registers.CAN_FA1R = master.registers.CAN_FA1R; 79 } 80 81 Reset(); 82 } 83 84 public event Action<int, byte[]> FrameReceived; 85 OnFrameReceived(CANMessageFrame message)86 public void OnFrameReceived(CANMessageFrame message) 87 { 88 if(registers.CAN_MCR.SleepRequest == true) 89 { 90 // Wake up if autowake up is on 91 if(registers.CAN_MCR.AutoWakeUpMode == true) 92 { 93 registers.CAN_MCR.SleepRequest = false; 94 registers.CAN_MSR.SleepAck = false; 95 } 96 // Signal wake up interrupt 97 registers.CAN_MSR.WakeupInterrupt = true; 98 UpdateSCEInterruptLine(); 99 } 100 else if(registers.CAN_BTR.LoopbackMode == false) 101 { 102 CANMessage RxMsg = new CANMessage(message); 103 for(int fifo = 0; fifo < NumberOfRxFifos; fifo++) 104 { 105 if(FilterCANMessage(fifo, RxMsg) == true) 106 { 107 this.Log(LogLevel.Debug, "Message received RIR={0:X}", message.Id); 108 ReceiveCANMessage(RxMsg); 109 } 110 else 111 { 112 this.Log(LogLevel.Debug, "Message dropped by filter RIR={0:X}", message.Id); 113 } 114 } 115 } 116 FrameReceived?.Invoke((int)message.Id, message.Data); 117 } 118 WriteDoubleWord(long address, uint value)119 public void WriteDoubleWord(long address, uint value) // cpu do per 120 { 121 if(IsSlave && AddressIsWithinFilterRegistersArea(address)) 122 { 123 this.Log(LogLevel.Warning, "Trying to access slave's filter registers, but the slave has to be configured via master's filters. This change has no effect."); 124 return; 125 } 126 127 // Filter bank registers 128 if((registerOffset)address >= registerOffset.CAN_F0R1 && 129 (registerOffset)address <= registerOffset.CAN_F27R2) 130 { 131 int bankIdx = AddressToFilterBankIdx(address); 132 133 // The filter bank registers can only be written if 134 // CAN_FMR.FINIT is true or the FA1R has FACtx cleared 135 // (the filter is disabled) 136 if(registers.CAN_FMR.FilterInitMode == true || 137 registers.CAN_FA1R.FilterActive(bankIdx) == false) 138 { 139 int regIdx = AddressToRegIdx(address); 140 //registers.CAN_FiRx[RegIdx] = value; 141 FilterBanks[bankIdx].FR[regIdx] = value; 142 } 143 return; 144 } 145 146 switch((registerOffset)address) 147 { 148 case registerOffset.CAN_MSR: 149 registers.CAN_MSR.SetValue(value); 150 UpdateSCEInterruptLine(); 151 return; 152 case registerOffset.CAN_MCR: 153 registers.CAN_MCR.SetValue(value); 154 155 if(registers.CAN_MCR.InitRequest == true && 156 registers.CAN_MCR.SleepRequest == false) 157 { 158 // Enter initialisation mode 159 registers.CAN_MSR.InitAck = true; 160 registers.CAN_MSR.SleepAck = false; 161 } 162 else if(registers.CAN_MCR.SleepRequest == true && 163 registers.CAN_MCR.InitRequest == false) 164 { 165 // Enter sleep mode 166 registers.CAN_MSR.SleepAck = true; 167 registers.CAN_MSR.SleepAckInterrupt = true; 168 registers.CAN_MSR.InitAck = false; 169 UpdateSCEInterruptLine(); 170 } 171 else 172 { 173 // Enter normal mode 174 registers.CAN_MSR.SleepAck = false; 175 registers.CAN_MSR.InitAck = false; 176 } 177 178 if(registers.CAN_MCR.Reset == true) 179 { 180 registers.Reset(); 181 } 182 183 return; 184 185 case registerOffset.CAN_TSR: 186 registers.CAN_TSR.SetValue(value); 187 UpdateTransmitInterruptLine(); 188 return; 189 190 case registerOffset.CAN_RF0R: 191 registers.CAN_RFR[RxFifo0].SetValue(value); 192 return; 193 194 case registerOffset.CAN_RF1R: 195 registers.CAN_RFR[RxFifo1].SetValue(value); 196 return; 197 198 case registerOffset.CAN_IER: 199 registers.CAN_IER.SetValue(value); 200 UpdateTransmitInterruptLine(); 201 registers.CAN_RFR[RxFifo0].UpdateInterruptLine(); 202 registers.CAN_RFR[RxFifo1].UpdateInterruptLine(); 203 UpdateSCEInterruptLine(); 204 return; 205 206 case registerOffset.CAN_ESR: 207 registers.CAN_ESR.SetValue(value); 208 UpdateSCEInterruptLine(); 209 return; 210 211 case registerOffset.CAN_BTR: 212 if(registers.CAN_MSR.InitAck == true) 213 { 214 registers.CAN_BTR.SetValue(value); 215 } 216 return; 217 218 // Filter registers 219 case registerOffset.CAN_FMR: 220 registers.CAN_FMR.SetValue(value); 221 UpdateFilterCANAssignment(); 222 return; 223 case registerOffset.CAN_FM1R: 224 if(registers.CAN_FMR.FilterInitMode == true) 225 { 226 registers.CAN_FM1R.SetValue(value); 227 for(int i = 0; i < NumberOfFilterBanks; i++) 228 { 229 FilterBanks[i].Mode = 230 registers.CAN_FM1R.FilterMode(i); 231 } 232 } 233 return; 234 case registerOffset.CAN_FS1R: 235 if(registers.CAN_FMR.FilterInitMode == true) 236 { 237 registers.CAN_FS1R.SetValue(value); 238 for(int i = 0; i < NumberOfFilterBanks; i++) 239 { 240 FilterBanks[i].Scale = 241 registers.CAN_FS1R.FilterScale(i); 242 } 243 } 244 return; 245 case registerOffset.CAN_FFA1R: 246 if(registers.CAN_FMR.FilterInitMode == true) 247 { 248 registers.CAN_FFA1R.SetValue(value); 249 for(int i = 0; i < NumberOfFilterBanks; i++) 250 { 251 FilterBanks[i].FifoAssignment = 252 registers.CAN_FFA1R.FifoAssignment(i); 253 } 254 } 255 return; 256 case registerOffset.CAN_FA1R: 257 registers.CAN_FA1R.SetValue(value); 258 for(int i = 0; i < NumberOfFilterBanks; i++) 259 { 260 FilterBanks[i].Active = 261 registers.CAN_FA1R.FilterActive(i); 262 } 263 for(uint fifo = 0; fifo < NumberOfRxFifos; fifo++) 264 { 265 PrioritizeFiFoFilters(fifo); 266 } 267 return; 268 269 // TX mailbox 0 270 case registerOffset.CAN_TI0R: 271 registers.CAN_TI0R.SetValue(value); 272 if(registers.CAN_TI0R.TransmitMailboxRequest(value) == true) 273 { 274 // Transmit data 275 // registers.CAN_TDT0R = timestamp_me; FIXME 276 CANMessage TxMsg = new CANMessage(registers.CAN_TI0R.GetValue(), 277 registers.CAN_TDT0R, 278 registers.CAN_TDL0R, 279 registers.CAN_TDH0R); 280 TransmitData(TxMsg); 281 282 // Transmition done 283 registers.CAN_TSR.TxMailbox0Done(); 284 UpdateTransmitInterruptLine(); 285 } 286 return; 287 case registerOffset.CAN_TDT0R: 288 registers.CAN_TDT0R = value; 289 return; 290 case registerOffset.CAN_TDL0R: 291 registers.CAN_TDL0R = value; 292 return; 293 case registerOffset.CAN_TDH0R: 294 registers.CAN_TDH0R = value; 295 return; 296 297 // TX mailbox 1 298 case registerOffset.CAN_TI1R: 299 registers.CAN_TI1R.SetValue(value); 300 if(registers.CAN_TI1R.TransmitMailboxRequest(value) == true) 301 { 302 // Transmit data 303 // registers.CAN_TDT1R = timestamp_me; FIXME 304 CANMessage TxMsg = new CANMessage(registers.CAN_TI1R.GetValue(), 305 registers.CAN_TDT1R, 306 registers.CAN_TDL1R, 307 registers.CAN_TDH1R); 308 TransmitData(TxMsg); 309 310 // Transmition done 311 registers.CAN_TSR.TxMailbox1Done(); 312 UpdateTransmitInterruptLine(); 313 } 314 return; 315 case registerOffset.CAN_TDT1R: 316 registers.CAN_TDT1R = value; 317 return; 318 case registerOffset.CAN_TDL1R: 319 registers.CAN_TDL1R = value; 320 return; 321 case registerOffset.CAN_TDH1R: 322 registers.CAN_TDH1R = value; 323 return; 324 325 // TX mailbox 2 326 case registerOffset.CAN_TI2R: 327 registers.CAN_TI2R.SetValue(value); 328 if(registers.CAN_TI2R.TransmitMailboxRequest(value) == true) 329 { 330 // Transmit data 331 // registers.CAN_TDT2R = timestamp_me; FIXME 332 CANMessage TxMsg = new CANMessage(registers.CAN_TI2R.GetValue(), 333 registers.CAN_TDT2R, 334 registers.CAN_TDL2R, 335 registers.CAN_TDH2R); 336 TransmitData(TxMsg); 337 338 // Transmition done 339 registers.CAN_TSR.TxMailbox2Done(); 340 UpdateTransmitInterruptLine(); 341 } 342 return; 343 case registerOffset.CAN_TDT2R: 344 registers.CAN_TDT2R = value; 345 return; 346 case registerOffset.CAN_TDL2R: 347 registers.CAN_TDL2R = value; 348 return; 349 case registerOffset.CAN_TDH2R: 350 registers.CAN_TDH2R = value; 351 return; 352 default: 353 this.LogUnhandledWrite(address, value); 354 return; 355 } 356 } 357 TransmitData(CANMessage msg)358 public void TransmitData(CANMessage msg) 359 { 360 if(registers.CAN_BTR.SilentMode == false) 361 { 362 if(FrameSent != null) 363 { 364 // Message frame created with receive identifier register 365 // value because filtering can be implemented on bits other 366 // than just standard/extended identifier value, e.g. IDE 367 // or RTR bit. 368 FrameSent(new CANMessageFrame(msg.CAN_RIR, msg.Data)); 369 } 370 else 371 { 372 registers.CAN_ESR.SetLECBitDominantError(); 373 UpdateSCEInterruptLine(); 374 } 375 } 376 if(registers.CAN_BTR.LoopbackMode == true) 377 { 378 for(int fifo = 0; fifo < NumberOfRxFifos; fifo++) 379 { 380 if(FilterCANMessage(fifo, msg) == true) 381 { 382 ReceiveCANMessage(msg); 383 } 384 } 385 } 386 } 387 PrioritizeFiFoFilters(uint Fifo)388 public void PrioritizeFiFoFilters(uint Fifo) 389 { 390 uint FirstFilterNumber = 0; 391 392 FifoFiltersPrioritized[Fifo].Clear(); 393 394 // Enumarate Fifo filters and add to priolist 395 for(int i = 0; i < NumberOfFilterBanks; i++) 396 { 397 if(FilterBanks[i].FifoAssignment == Fifo) 398 { 399 FilterBanks[i].FirstFilterNumber = FirstFilterNumber; 400 FirstFilterNumber += FilterBanks[i].NumberOfFiltersInBank(); 401 FifoFiltersPrioritized[Fifo].Add(FilterBanks[i]); 402 } 403 } 404 405 UpdateFilterCANAssignment(); 406 FifoFiltersPrioritized[Fifo].Sort(); 407 } 408 UpdateFilterCANAssignment()409 public void UpdateFilterCANAssignment() 410 { 411 for(var i = 0; i < NumberOfFilterBanks; i++) 412 { 413 FilterBanks[i].BelongsToMaster = i < registers.CAN_FMR.CAN2StartBank; 414 } 415 } 416 FilterCANMessage(int RxFifo, CANMessage msg)417 public bool FilterCANMessage(int RxFifo, CANMessage msg) 418 { 419 foreach(FilterBank filterBank in FifoFiltersPrioritized[RxFifo].Where(m => m.BelongsToMaster == !IsSlave)) 420 { 421 if(filterBank.Active == true && 422 filterBank.MatchMessage(msg) == true) 423 { 424 return true; 425 } 426 } 427 return false; 428 } 429 ReceiveCANMessage(CANMessage msg)430 public void ReceiveCANMessage(CANMessage msg) 431 { 432 if(msg.RxFifo < NumberOfRxFifos) 433 { 434 bool LockedMode = registers.CAN_MCR.RxFifoLockedMode; 435 registers.CAN_RFR[msg.RxFifo].ReceiveMessage(msg, LockedMode); 436 437 if(registers.CAN_RFR[msg.RxFifo].UpdateInterruptLine != null) 438 { 439 registers.CAN_RFR[msg.RxFifo].UpdateInterruptLine(); 440 } 441 } 442 } 443 UpdateTransmitInterruptLine()444 public void UpdateTransmitInterruptLine() 445 { 446 // Transmit interrupt 447 if(EnableTransmitInterrupt() == true) 448 { 449 Connections[CAN_Tx].Set(); 450 } 451 else 452 { 453 Connections[CAN_Tx].Unset(); 454 } 455 } 456 UpdateInterruptLine()457 public delegate void UpdateInterruptLine(); 458 UpdateFifo0InterruptLine()459 public void UpdateFifo0InterruptLine() 460 { 461 // Fifo0 interrupt 462 if(EnableFifo0Interrupt() == true) 463 { 464 Connections[CAN_Rx0].Set(); 465 } 466 else 467 { 468 Connections[CAN_Rx0].Unset(); 469 } 470 } 471 UpdateFifo1InterruptLine()472 public void UpdateFifo1InterruptLine() 473 { 474 // Fifo1 interrupt 475 if(EnableFifo1Interrupt() == true) 476 { 477 Connections[CAN_Rx1].Set(); 478 } 479 else 480 { 481 Connections[CAN_Rx1].Unset(); 482 } 483 } 484 UpdateSCEInterruptLine()485 public void UpdateSCEInterruptLine() 486 { 487 // Error and status change interrupt 488 if(EnableSCEInterrupt() == true) 489 { 490 Connections[CAN_SCE].Set(); 491 } 492 else 493 { 494 Connections[CAN_SCE].Unset(); 495 } 496 } 497 EnableTransmitInterrupt()498 public bool EnableTransmitInterrupt() 499 { 500 if(registers.CAN_IER.TMEInterruptEnabled == true && 501 registers.CAN_TSR.MailboxRequestCompleted() == true) 502 { 503 return true; 504 } 505 return false; 506 } 507 EnableFifo0Interrupt()508 public bool EnableFifo0Interrupt() 509 { 510 // Check pending message 511 if(registers.CAN_IER.FMP0InterruptEnabled == true && 512 registers.CAN_RFR[RxFifo0].HasMessagesPending() == true) 513 { 514 return true; 515 } 516 // Check Fifo0 full 517 if(registers.CAN_IER.FF0InterruptEnabled == true && 518 registers.CAN_RFR[RxFifo0].FifoFull == true) 519 { 520 return true; 521 } 522 // Check Fifo0 overrun 523 if(registers.CAN_IER.FOV0InterruptEnabled == true && 524 registers.CAN_RFR[RxFifo0].FifoOverrun == true) 525 { 526 return true; 527 } 528 return false; 529 } 530 EnableFifo1Interrupt()531 public bool EnableFifo1Interrupt() 532 { 533 // Check pending message 534 if(registers.CAN_IER.FMP1InterruptEnabled == true && 535 registers.CAN_RFR[RxFifo1].HasMessagesPending() == true) 536 { 537 return true; 538 } 539 // Check Fifo1 full 540 if(registers.CAN_IER.FF1InterruptEnabled == true && 541 registers.CAN_RFR[RxFifo1].FifoFull == true) 542 { 543 return true; 544 } 545 // Check Fifo1 overrun 546 if(registers.CAN_IER.FOV1InterruptEnabled == true && 547 registers.CAN_RFR[RxFifo1].FifoOverrun == true) 548 { 549 return true; 550 } 551 return false; 552 } 553 EnableSCEInterrupt()554 public bool EnableSCEInterrupt() 555 { 556 // An error condition is pending 557 if(registers.CAN_IER.ERRInterruptEnabled == true && 558 registers.CAN_MSR.ErrorInterrupt == true) 559 { 560 return true; 561 } 562 // Error warning interrupt 563 if(registers.CAN_IER.EWGInterruptEnabled == true && 564 registers.CAN_ESR.ErrorWarningFlag == true) 565 { 566 return true; 567 } 568 // Error passive interrupt 569 if(registers.CAN_IER.EPVInterruptEnabled == true && 570 registers.CAN_ESR.ErrorPassiveFlag == true) 571 { 572 return true; 573 } 574 // Error passive interrupt 575 if(registers.CAN_IER.BOFInterruptEnabled == true && 576 registers.CAN_ESR.BusOffFlag == true) 577 { 578 return true; 579 } 580 // LEC Error pending 581 if(registers.CAN_IER.LECInterruptEnabled == true && 582 registers.CAN_ESR.LECErrorPending() == true) 583 { 584 return true; 585 } 586 // Sleep interrupt 587 if(registers.CAN_IER.SLKInterruptEnabled == true && 588 registers.CAN_MSR.SleepAckInterrupt == true) 589 { 590 return true; 591 } 592 // Wakup interrupt 593 if(registers.CAN_IER.WKUInterruptEnabled == true && 594 registers.CAN_MSR.WakeupInterrupt == true) 595 { 596 return true; 597 } 598 return false; 599 } 600 AddressToFilterBankIdx(long address)601 public int AddressToFilterBankIdx(long address) 602 { 603 // Filter bank has a size of 2 * uint 604 return (int)(address - (long)registerOffset.CAN_F0R1) / (2 * sizeof(uint)); 605 } 606 AddressToRegIdx(long address)607 public int AddressToRegIdx(long address) 608 { 609 return (int)((address - (long)registerOffset.CAN_F0R1) / sizeof(uint)) % 2; 610 } 611 ReadDoubleWord(long offset)612 public uint ReadDoubleWord(long offset) 613 { 614 uint Retval = 0; 615 616 if(IsSlave && AddressIsWithinFilterRegistersArea(offset)) 617 { 618 this.Log(LogLevel.Warning, "Trying to read slave's filter registers, but the slave uses master's filter registers - reading from master instead."); 619 } 620 621 // Filter bank registers 622 if((registerOffset)offset >= registerOffset.CAN_F0R1 && (registerOffset)offset <= registerOffset.CAN_F27R2) 623 { 624 int bankIdx = AddressToFilterBankIdx(offset); 625 int regIdx = AddressToRegIdx(offset); 626 //Retval = registers.CAN_FiRx[RegIdx]; 627 Retval = FilterBanks[bankIdx].FR[regIdx]; 628 } 629 else 630 { 631 switch((registerOffset)offset) 632 { 633 case registerOffset.CAN_MCR: 634 Retval = registers.CAN_MCR.GetValue(); 635 break; 636 case registerOffset.CAN_MSR: 637 Retval = registers.CAN_MSR.GetValue(); 638 break; 639 case registerOffset.CAN_TSR: 640 Retval = registers.CAN_TSR.GetValue(); 641 break; 642 case registerOffset.CAN_RF0R: 643 Retval = registers.CAN_RFR[RxFifo0].GetValue(); 644 break; 645 case registerOffset.CAN_RF1R: 646 Retval = registers.CAN_RFR[RxFifo1].GetValue(); 647 break; 648 case registerOffset.CAN_IER: 649 Retval = registers.CAN_IER.GetValue(); 650 break; 651 case registerOffset.CAN_ESR: 652 Retval = registers.CAN_ESR.GetValue(); 653 break; 654 case registerOffset.CAN_BTR: 655 if(registers.CAN_MSR.InitAck == true) 656 { 657 Retval = registers.CAN_BTR.GetValue(); 658 } 659 break; 660 661 // Filter registers 662 case registerOffset.CAN_FMR: 663 Retval = registers.CAN_FMR.GetValue(); 664 break; 665 case registerOffset.CAN_FM1R: 666 Retval = registers.CAN_FM1R.GetValue(); 667 break; 668 case registerOffset.CAN_FS1R: 669 Retval = registers.CAN_FS1R.GetValue(); 670 break; 671 case registerOffset.CAN_FFA1R: 672 Retval = registers.CAN_FFA1R.GetValue(); 673 break; 674 case registerOffset.CAN_FA1R: 675 Retval = registers.CAN_FA1R.GetValue(); 676 break; 677 678 // TX mailboxes 0 679 case registerOffset.CAN_TI0R: 680 Retval = registers.CAN_TI0R.GetValue(); 681 break; 682 case registerOffset.CAN_TDT0R: 683 Retval = registers.CAN_TDT0R; 684 break; 685 case registerOffset.CAN_TDL0R: 686 Retval = registers.CAN_TDL0R; 687 break; 688 case registerOffset.CAN_TDH0R: 689 Retval = registers.CAN_TDH0R; 690 break; 691 692 // TX mailboxes 1 693 case registerOffset.CAN_TI1R: 694 Retval = registers.CAN_TI1R.GetValue(); 695 break; 696 case registerOffset.CAN_TDT1R: 697 Retval = registers.CAN_TDT1R; 698 break; 699 case registerOffset.CAN_TDL1R: 700 Retval = registers.CAN_TDL1R; 701 break; 702 case registerOffset.CAN_TDH1R: 703 Retval = registers.CAN_TDH1R; 704 break; 705 706 // TX mailboxes 2 707 case registerOffset.CAN_TI2R: 708 Retval = registers.CAN_TI2R.GetValue(); 709 break; 710 case registerOffset.CAN_TDT2R: 711 Retval = registers.CAN_TDT2R; 712 break; 713 case registerOffset.CAN_TDL2R: 714 Retval = registers.CAN_TDL2R; 715 break; 716 case registerOffset.CAN_TDH2R: 717 Retval = registers.CAN_TDH2R; 718 break; 719 720 // RX mailbox 0 721 case registerOffset.CAN_RI0R: 722 if(registers.CAN_RFR[RxFifo0].HasMessagesPending() == true) 723 { 724 Retval = RxFifo[RxFifo0].Peek().CAN_RIR; 725 } 726 break; 727 case registerOffset.CAN_RDT0R: 728 if(registers.CAN_RFR[RxFifo0].HasMessagesPending() == true) 729 { 730 Retval = RxFifo[RxFifo0].Peek().CAN_RDTR; 731 } 732 break; 733 case registerOffset.CAN_RL0R: 734 if(registers.CAN_RFR[RxFifo0].HasMessagesPending() == true) 735 { 736 Retval = RxFifo[RxFifo0].Peek().CAN_RLR; 737 } 738 break; 739 case registerOffset.CAN_RH0R: 740 if(registers.CAN_RFR[RxFifo0].HasMessagesPending() == true) 741 { 742 Retval = RxFifo[RxFifo0].Peek().CAN_RHR; 743 } 744 break; 745 746 // RX mailboxes 1 747 case registerOffset.CAN_RI1R: 748 if(registers.CAN_RFR[RxFifo1].HasMessagesPending() == true) 749 { 750 Retval = RxFifo[RxFifo1].Peek().CAN_RIR; 751 } 752 break; 753 case registerOffset.CAN_RDT1R: 754 if(registers.CAN_RFR[RxFifo1].HasMessagesPending() == true) 755 { 756 Retval = RxFifo[RxFifo1].Peek().CAN_RDTR; 757 } 758 break; 759 case registerOffset.CAN_RL1R: 760 if(registers.CAN_RFR[RxFifo1].HasMessagesPending() == true) 761 { 762 Retval = RxFifo[RxFifo1].Peek().CAN_RLR; 763 } 764 break; 765 case registerOffset.CAN_RH1R: 766 if(registers.CAN_RFR[RxFifo1].HasMessagesPending() == true) 767 { 768 Retval = RxFifo[RxFifo1].Peek().CAN_RHR; 769 } 770 break; 771 772 default: 773 this.LogUnhandledRead(offset); 774 break; 775 } 776 } 777 778 return Retval; 779 } 780 Reset()781 public void Reset() 782 { 783 registers.Reset(!IsSlave); 784 785 if(!IsSlave) 786 { 787 for(int i = 0; i < NumberOfFilterBanks; i++) 788 { 789 FilterBanks[i].Active = false; 790 FilterBanks[i].Mode = FilterBankMode.FilterModeIdMask; 791 FilterBanks[i].FifoAssignment = 0; 792 FilterBanks[i].Scale = FilterBankScale.FilterScale16Bit; 793 } 794 UpdateFilterCANAssignment(); 795 } 796 } 797 798 public bool IsSlave => master != null; 799 AddressIsWithinFilterRegistersArea(long address)800 private bool AddressIsWithinFilterRegistersArea(long address) 801 { 802 return (registerOffset)address >= registerOffset.CAN_FMR 803 && (registerOffset)address <= registerOffset.CAN_F27R2; 804 } 805 806 private enum registerOffset : uint 807 { 808 CAN_MCR = 0x00, 809 CAN_MSR = 0x04, 810 CAN_TSR = 0x08, 811 CAN_RF0R = 0x0C, 812 CAN_RF1R = 0x10, 813 CAN_IER = 0x14, 814 CAN_ESR = 0x18, 815 CAN_BTR = 0x1C, 816 817 // TX mailboxes 818 CAN_TI0R = 0x180, 819 CAN_TDT0R = 0x184, 820 CAN_TDL0R = 0x188, 821 CAN_TDH0R = 0x18C, 822 823 CAN_TI1R = 0x190, 824 CAN_TDT1R = 0x194, 825 CAN_TDL1R = 0x198, 826 CAN_TDH1R = 0x19C, 827 828 CAN_TI2R = 0x1A0, 829 CAN_TDT2R = 0x1A4, 830 CAN_TDL2R = 0x1A8, 831 CAN_TDH2R = 0x1AC, 832 833 // RX mailboxes 834 CAN_RI0R = 0x1B0, 835 CAN_RDT0R = 0x1B4, 836 CAN_RL0R = 0x1B8, 837 CAN_RH0R = 0x1BC, 838 839 CAN_RI1R = 0x1C0, 840 CAN_RDT1R = 0x1C4, 841 CAN_RL1R = 0x1C8, 842 CAN_RH1R = 0x1CC, 843 844 // Filter registers 845 CAN_FMR = 0x200, 846 CAN_FM1R = 0x204, 847 CAN_FS1R = 0x20C, 848 CAN_FFA1R = 0x214, 849 CAN_FA1R = 0x21C, 850 851 // Filter bank registers 852 CAN_F0R1 = 0x240, 853 CAN_F27R2 = 0x31C, 854 } 855 856 public enum FilterBankScale 857 { 858 FilterScale16Bit, 859 FilterScale32Bit 860 } 861 862 public enum FilterBankMode 863 { 864 FilterModeIdMask, 865 FilterIdentifierList 866 } 867 868 private class DeviceRegisters 869 { 870 // Constants 871 public const uint NUM_FILTERBANKS = 28; 872 public const uint NUM_FILTERBANK_REGS = 2 * NUM_FILTERBANKS; 873 874 // Control registers 875 public MasterControlRegister CAN_MCR = new MasterControlRegister(); 876 public MasterStatusRegister CAN_MSR = new MasterStatusRegister(); 877 public TransmitStatusRegister CAN_TSR = new TransmitStatusRegister(); 878 public ReceiveFifoRegister[] CAN_RFR = new ReceiveFifoRegister[NumberOfRxFifos]; 879 public InterruptEnableRegister CAN_IER = new InterruptEnableRegister(); 880 public ErrorStatusRegister CAN_ESR = new ErrorStatusRegister(); 881 public BitTimingRegister CAN_BTR = new BitTimingRegister(); 882 883 // Filter registers 884 public FilterMasterRegister CAN_FMR = new FilterMasterRegister(); 885 public FilterModeRegister CAN_FM1R = new FilterModeRegister(); 886 public FilterScaleRegister CAN_FS1R = new FilterScaleRegister(); 887 public FifoAssignmentRegister CAN_FFA1R = new FifoAssignmentRegister(); 888 public FilterActiveRegister CAN_FA1R = new FilterActiveRegister(); 889 890 // Filter bank registers 891 public uint[] CAN_FiRx = new uint[NUM_FILTERBANK_REGS]; 892 893 // TX mailbox 0 894 public MailboxIdentifierRegister CAN_TI0R = new MailboxIdentifierRegister(); 895 public uint CAN_TDT0R; 896 public uint CAN_TDL0R; 897 public uint CAN_TDH0R; 898 899 // TX mailbox 1 900 public MailboxIdentifierRegister CAN_TI1R = new MailboxIdentifierRegister(); 901 public uint CAN_TDT1R; 902 public uint CAN_TDL1R; 903 public uint CAN_TDH1R; 904 905 // TX mailbox 2 906 public MailboxIdentifierRegister CAN_TI2R = new MailboxIdentifierRegister(); 907 public uint CAN_TDT2R; 908 public uint CAN_TDL2R; 909 public uint CAN_TDH2R; 910 DeviceRegisters()911 public DeviceRegisters() 912 { 913 for(int i = 0; i < NumberOfRxFifos; i++) 914 { 915 CAN_RFR[i] = new ReceiveFifoRegister(); 916 } 917 } 918 Reset(bool resetFilters = true)919 public void Reset(bool resetFilters = true) 920 { 921 CAN_MCR.SetValue(0x00010002); 922 CAN_MSR.SetResetValue(0x00000C02); 923 CAN_TSR.SetResetValue(0x1C000000); 924 CAN_RFR[RxFifo0].SetValue(0x0); 925 CAN_RFR[RxFifo1].SetValue(0x0); 926 CAN_IER.SetValue(0x0); 927 CAN_ESR.SetResetValue(0x0); 928 CAN_BTR.SetValue(0x01230000); 929 930 if(resetFilters) 931 { 932 // Filter Registers 933 CAN_FMR.SetValue(0x2A1C0E01); 934 CAN_FM1R.SetValue(0x0); 935 CAN_FS1R.SetValue(0x0); 936 CAN_FFA1R.SetValue(0x0); 937 CAN_FA1R.SetValue(0x0); 938 } 939 } 940 941 public class MasterControlRegister 942 { 943 public const uint DBF = (1u << 16); 944 public const uint RESET = (1u << 15); 945 public const uint TTCM = (1u << 7); 946 public const uint ABOM = (1u << 6); 947 public const uint AWUM = (1u << 5); 948 public const uint NART = (1u << 4); 949 public const uint RFLM = (1u << 3); 950 public const uint TXFP = (1u << 2); 951 public const uint SLEEP = (1u << 1); 952 public const uint INRQ = (1u << 0); 953 954 public bool DebugFreeze; 955 public bool Reset; 956 public bool TimeTriggeredComMode; 957 public bool AutoBusOffManagement; 958 public bool AutoWakeUpMode; 959 public bool NoAutoRetransmission; 960 public bool RxFifoLockedMode; 961 public bool TxFifoPriority; 962 public bool SleepRequest; 963 public bool InitRequest; 964 SetValue(uint value)965 public void SetValue(uint value) 966 { 967 DebugFreeze = (value & DBF) != 0; 968 Reset = (value & RESET) != 0; 969 TimeTriggeredComMode = (value & TTCM) != 0; 970 AutoBusOffManagement = (value & ABOM) != 0; 971 AutoWakeUpMode = (value & AWUM) != 0; 972 NoAutoRetransmission = (value & NART) != 0; 973 RxFifoLockedMode = (value & RFLM) != 0; 974 TxFifoPriority = (value & TXFP) != 0; 975 SleepRequest = (value & SLEEP) != 0; 976 InitRequest = (value & INRQ) != 0; 977 } 978 GetValue()979 public uint GetValue() 980 { 981 var retVal = 982 (DebugFreeze ? DBF : 0) | 983 (TimeTriggeredComMode ? TTCM : 0) | 984 (AutoBusOffManagement ? ABOM : 0) | 985 (AutoWakeUpMode ? AWUM : 0) | 986 (NoAutoRetransmission ? NART : 0) | 987 (RxFifoLockedMode ? RFLM : 0) | 988 (TxFifoPriority ? TXFP : 0) | 989 (SleepRequest ? SLEEP : 0) | 990 (InitRequest ? INRQ : 0); 991 return retVal; 992 } 993 } 994 995 public class MasterStatusRegister 996 { 997 public const uint RX = (1u << 11); 998 public const uint SAMP = (1u << 10); 999 public const uint RXM = (1u << 9); 1000 public const uint TXM = (1u << 8); 1001 public const uint SLAKI = (1u << 4); 1002 public const uint WKUI = (1u << 3); 1003 public const uint ERRI = (1u << 2); 1004 public const uint SLAK = (1u << 1); 1005 public const uint INAK = (1u << 0); 1006 1007 public bool RxSignal; 1008 public bool LastSamplePoint; 1009 public bool RxMode; 1010 public bool TxMode; 1011 public bool SleepAckInterrupt; 1012 public bool WakeupInterrupt; 1013 public bool ErrorInterrupt; 1014 public bool SleepAck; 1015 public bool InitAck; 1016 SetResetValue(uint value)1017 public void SetResetValue(uint value) 1018 { 1019 RxSignal = (value & RX) != 0; 1020 LastSamplePoint = (value & SAMP) != 0; 1021 RxMode = (value & RXM) != 0; 1022 TxMode = (value & TXM) != 0; 1023 SleepAckInterrupt = (value & SLAKI) != 0; 1024 WakeupInterrupt = (value & WKUI) != 0; 1025 ErrorInterrupt = (value & ERRI) != 0; 1026 SleepAck = (value & SLAK) != 0; 1027 InitAck = (value & INAK) != 0; 1028 } 1029 SetValue(uint value)1030 public void SetValue(uint value) 1031 { 1032 if((value & SLAKI) != 0) 1033 { 1034 SleepAckInterrupt = false; 1035 } 1036 if((value & WKUI) != 0) 1037 { 1038 WakeupInterrupt = false; 1039 } 1040 if((value & ERRI) != 0) 1041 { 1042 ErrorInterrupt = false; 1043 } 1044 } 1045 GetValue()1046 public uint GetValue() 1047 { 1048 var retVal = 1049 (RxSignal ? RX : 0) | 1050 (LastSamplePoint ? SAMP : 0) | 1051 (RxMode ? RXM : 0) | 1052 (TxMode ? TXM : 0) | 1053 (SleepAckInterrupt ? SLAKI : 0) | 1054 (WakeupInterrupt ? WKUI : 0) | 1055 (ErrorInterrupt ? ERRI : 0) | 1056 (SleepAck ? SLAK : 0) | 1057 (InitAck ? INAK : 0); 1058 return retVal; 1059 } 1060 } 1061 1062 public class ReceiveFifoRegister 1063 { 1064 public const uint MaxMessagesInFifo = 3; 1065 public const uint FULL = (1u << 3); 1066 public const uint FOVR = (1u << 4); 1067 public const uint RFOM = (1u << 5); 1068 public const uint FMPMASK = 0x3; 1069 1070 public bool FifoFull = false; 1071 public bool FifoOverrun = false; 1072 public uint FifoMessagesPending = 0; 1073 private Queue<CANMessage> RxFifo; 1074 1075 public UpdateInterruptLine UpdateInterruptLine; 1076 SetRxFifo(Queue<CANMessage> RxFifo)1077 public void SetRxFifo(Queue<CANMessage> RxFifo) 1078 { 1079 this.RxFifo = RxFifo; 1080 } 1081 SetValue(uint value)1082 public void SetValue(uint value) 1083 { 1084 if((value & FULL) != 0) 1085 { 1086 FifoFull = false; 1087 } 1088 if((value & FOVR) != 0) 1089 { 1090 FifoOverrun = false; 1091 } 1092 if((value & RFOM) != 0) 1093 { 1094 if(RxFifo.Count > 0) 1095 { 1096 RxFifo.Dequeue(); 1097 } 1098 } 1099 if(UpdateInterruptLine != null) 1100 UpdateInterruptLine(); 1101 } 1102 GetValue()1103 public uint GetValue() 1104 { 1105 var retVal = 1106 (FifoFull ? FULL : 0) | 1107 (FifoOverrun ? FOVR : 0) | 1108 ((uint)RxFifo.Count & FMPMASK); 1109 return retVal; 1110 } 1111 HasMessagesPending()1112 public bool HasMessagesPending() 1113 { 1114 return (RxFifo.Count > 0); 1115 } 1116 FifoEmpty()1117 public bool FifoEmpty() 1118 { 1119 return (RxFifo.Count == 0); 1120 } 1121 ReceiveMessage(CANMessage msg, bool RxFifoLockedMode)1122 public void ReceiveMessage(CANMessage msg, bool RxFifoLockedMode) 1123 { 1124 if(RxFifo.Count < 3) 1125 { 1126 RxFifo.Enqueue(msg); 1127 if(RxFifo.Count == MaxMessagesInFifo) 1128 { 1129 FifoFull = true; 1130 } 1131 } 1132 else if(RxFifoLockedMode == false) 1133 { 1134 // Keep 3 newest messages in queue and signal overrun 1135 RxFifo.Dequeue(); 1136 RxFifo.Enqueue(msg); 1137 FifoOverrun = true; 1138 } 1139 else 1140 { 1141 // Keep 3 oldest messages in queue and signal overrun 1142 FifoOverrun = true; 1143 } 1144 } 1145 } 1146 1147 public class InterruptEnableRegister 1148 { 1149 public const uint TMEIE = (1u << 0); 1150 public const uint FMPIE0 = (1u << 1); 1151 public const uint FFIE0 = (1u << 2); 1152 public const uint FOVIE0 = (1u << 3); 1153 public const uint FMPIE1 = (1u << 4); 1154 public const uint FFIE1 = (1u << 5); 1155 public const uint FOVIE1 = (1u << 6); 1156 public const uint EWGIE = (1u << 8); 1157 public const uint EPVIE = (1u << 9); 1158 public const uint BOFIE = (1u << 10); 1159 public const uint LECIE = (1u << 11); 1160 public const uint ERRIE = (1u << 15); 1161 public const uint WKUIE = (1u << 16); 1162 public const uint SLKIE = (1u << 17); 1163 1164 public bool TMEInterruptEnabled; 1165 public bool FMP0InterruptEnabled; 1166 public bool FF0InterruptEnabled; 1167 public bool FOV0InterruptEnabled; 1168 public bool FMP1InterruptEnabled; 1169 public bool FF1InterruptEnabled; 1170 public bool FOV1InterruptEnabled; 1171 public bool EWGInterruptEnabled; 1172 public bool EPVInterruptEnabled; 1173 public bool BOFInterruptEnabled; 1174 public bool LECInterruptEnabled; 1175 public bool ERRInterruptEnabled; 1176 public bool WKUInterruptEnabled; 1177 public bool SLKInterruptEnabled; 1178 SetValue(uint value)1179 public void SetValue(uint value) 1180 { 1181 TMEInterruptEnabled = (value & TMEIE) != 0; 1182 FMP0InterruptEnabled = (value & FMPIE0) != 0; 1183 FF0InterruptEnabled = (value & FFIE0) != 0; 1184 FOV0InterruptEnabled = (value & FOVIE0) != 0; 1185 FMP1InterruptEnabled = (value & FMPIE1) != 0; 1186 FF1InterruptEnabled = (value & FFIE1) != 0; 1187 FOV1InterruptEnabled = (value & FOVIE1) != 0; 1188 EWGInterruptEnabled = (value & EWGIE) != 0; 1189 EPVInterruptEnabled = (value & EPVIE) != 0; 1190 BOFInterruptEnabled = (value & BOFIE) != 0; 1191 LECInterruptEnabled = (value & LECIE) != 0; 1192 ERRInterruptEnabled = (value & ERRIE) != 0; 1193 WKUInterruptEnabled = (value & WKUIE) != 0; 1194 SLKInterruptEnabled = (value & SLKIE) != 0; 1195 } 1196 GetValue()1197 public uint GetValue() 1198 { 1199 var retVal = 1200 (TMEInterruptEnabled ? TMEIE : 0) | 1201 (FMP0InterruptEnabled ? FMPIE0 : 0) | 1202 (FF0InterruptEnabled ? FFIE0 : 0) | 1203 (FOV0InterruptEnabled ? FOVIE0 : 0) | 1204 (FMP1InterruptEnabled ? FMPIE1 : 0) | 1205 (FF1InterruptEnabled ? FFIE1 : 0) | 1206 (FOV1InterruptEnabled ? FOVIE1 : 0) | 1207 (EWGInterruptEnabled ? EWGIE : 0) | 1208 (EPVInterruptEnabled ? EPVIE : 0) | 1209 (BOFInterruptEnabled ? BOFIE : 0) | 1210 (LECInterruptEnabled ? LECIE : 0) | 1211 (ERRInterruptEnabled ? ERRIE : 0) | 1212 (WKUInterruptEnabled ? WKUIE : 0) | 1213 (SLKInterruptEnabled ? SLKIE : 0); 1214 return retVal; 1215 } 1216 } 1217 1218 public class ErrorStatusRegister 1219 { 1220 public const uint EWGF = (1u << 0); 1221 public const uint EPVF = (1u << 1); 1222 public const uint BOFF = (1u << 2); 1223 1224 public const int LECSHIFT = 4; 1225 public const uint LECMASK = 0x7; 1226 public const int TECSHIFT = 16; 1227 public const uint TECMASK = 0xFF; 1228 public const int RECSHIFT = 24; 1229 public const uint RECMASK = 0xFF; 1230 1231 public const uint LECNoError = 0x0; 1232 public const uint LECBitDominantError = 0x5; 1233 public const uint LECSetBySoftware = 0x7; 1234 1235 public bool ErrorWarningFlag; 1236 public bool ErrorPassiveFlag; 1237 public bool BusOffFlag; 1238 1239 public uint LastErrorCode; 1240 public uint TransmitErrorCounter; 1241 public uint ReceiveErrorCounter; 1242 SetResetValue(uint value)1243 public void SetResetValue(uint value) 1244 { 1245 ErrorWarningFlag = (value & EWGF) != 0; 1246 ErrorPassiveFlag = (value & EPVF) != 0; 1247 BusOffFlag = (value & BOFF) != 0; 1248 LastErrorCode = (value >> LECSHIFT) & LECMASK; 1249 TransmitErrorCounter = (value >> TECSHIFT) & TECMASK; 1250 ReceiveErrorCounter = (value >> RECSHIFT) & RECMASK; 1251 } 1252 SetValue(uint value)1253 public void SetValue(uint value) 1254 { 1255 LastErrorCode = (value >> LECSHIFT) & LECMASK; 1256 TransmitErrorCounter = (value >> TECSHIFT) & TECMASK; 1257 ReceiveErrorCounter = (value >> RECSHIFT) & RECMASK; 1258 } 1259 GetValue()1260 public uint GetValue() 1261 { 1262 var retVal = 1263 (ErrorWarningFlag ? EWGF : 0) | 1264 (ErrorPassiveFlag ? EPVF : 0) | 1265 (BusOffFlag ? BOFF : 0) | 1266 ((LastErrorCode & LECMASK) << LECSHIFT) | 1267 ((TransmitErrorCounter & TECMASK) << TECSHIFT) | 1268 ((ReceiveErrorCounter & RECMASK) << RECSHIFT); 1269 return retVal; 1270 } 1271 SetLECBitDominantError()1272 public void SetLECBitDominantError() 1273 { 1274 LastErrorCode = LECBitDominantError; 1275 } 1276 LECErrorPending()1277 public bool LECErrorPending() 1278 { 1279 return (LastErrorCode > LECNoError) && (LastErrorCode < LECSetBySoftware); 1280 } 1281 } 1282 1283 public class BitTimingRegister 1284 { 1285 public const uint SILM = (1u << 31); 1286 public const uint LBKM = (1u << 30); 1287 1288 public bool SilentMode; 1289 public bool LoopbackMode; 1290 1291 public uint RegValue; 1292 SetValue(uint value)1293 public void SetValue(uint value) 1294 { 1295 RegValue = value; 1296 SilentMode = (value & SILM) != 0; 1297 LoopbackMode = (value & LBKM) != 0; 1298 } 1299 GetValue()1300 public uint GetValue() 1301 { 1302 return RegValue; 1303 } 1304 } 1305 1306 // CAN_TSR 1307 public class TransmitStatusRegister 1308 { 1309 public const uint RQCP0 = (1u << 0); 1310 public const uint TXOK0 = (1u << 1); 1311 public const uint ALST0 = (1u << 2); 1312 public const uint TERR0 = (1u << 3); 1313 public const uint ABRQ0 = (1u << 7); 1314 1315 public const uint RQCP1 = (1u << 8); 1316 public const uint TXOK1 = (1u << 9); 1317 public const uint ALST1 = (1u << 10); 1318 public const uint TERR1 = (1u << 11); 1319 public const uint ABRQ1 = (1u << 15); 1320 1321 public const uint RQCP2 = (1u << 16); 1322 public const uint TXOK2 = (1u << 17); 1323 public const uint ALST2 = (1u << 18); 1324 public const uint TERR2 = (1u << 19); 1325 public const uint ABRQ2 = (1u << 23); 1326 1327 public const uint TME0 = (1u << 26); 1328 public const uint TME1 = (1u << 27); 1329 public const uint TME2 = (1u << 28); 1330 1331 private uint RegValue; 1332 SetValue(uint value)1333 public void SetValue(uint value) 1334 { 1335 if((value & TERR2) != 0) 1336 { 1337 RegValue &= ~(TERR2); 1338 } 1339 if((value & ALST2) != 0) 1340 { 1341 RegValue &= ~(ALST2); 1342 } 1343 if((value & TXOK2) != 0) 1344 { 1345 RegValue &= ~(TXOK2); 1346 } 1347 if((value & TERR1) != 0) 1348 { 1349 RegValue &= ~(TERR1); 1350 } 1351 if((value & ALST1) != 0) 1352 { 1353 RegValue &= ~(ALST1); 1354 } 1355 if((value & TXOK1) != 0) 1356 { 1357 RegValue &= ~(TXOK1); 1358 } 1359 if((value & TERR0) != 0) 1360 { 1361 RegValue &= ~(TERR1); 1362 } 1363 if((value & ALST0) != 0) 1364 { 1365 RegValue &= ~(ALST0); 1366 } 1367 if((value & TXOK0) != 0) 1368 { 1369 RegValue &= ~(TXOK0); 1370 } 1371 if((value & RQCP0) != 0) 1372 { 1373 RegValue &= ~(TXOK0 | ALST0 | TERR0 | RQCP0); 1374 } 1375 if((value & RQCP1) != 0) 1376 { 1377 RegValue &= ~(TXOK1 | ALST1 | TERR1 | RQCP1); 1378 } 1379 if((value & RQCP2) != 0) 1380 { 1381 RegValue &= ~(TXOK2 | ALST2 | TERR2 | RQCP2); 1382 } 1383 } 1384 SetResetValue(uint value)1385 public void SetResetValue(uint value) 1386 { 1387 RegValue = value; 1388 } 1389 GetValue()1390 public uint GetValue() 1391 { 1392 return RegValue; 1393 } 1394 TxMailbox0Done()1395 public void TxMailbox0Done() 1396 { 1397 RegValue |= (TME0 | TXOK0 | RQCP0); 1398 } 1399 TxMailbox1Done()1400 public void TxMailbox1Done() 1401 { 1402 RegValue |= (TME1 | TXOK1 | RQCP1); 1403 } 1404 TxMailbox2Done()1405 public void TxMailbox2Done() 1406 { 1407 RegValue |= (TME2 | TXOK2 | RQCP2); 1408 } 1409 ClearTxInterrupt(uint value)1410 public bool ClearTxInterrupt(uint value) 1411 { 1412 return ((value & RQCP0) != 0); 1413 } 1414 MailboxRequestCompleted()1415 public bool MailboxRequestCompleted() 1416 { 1417 var retVal = 1418 ((RegValue & RQCP0) != 0) || 1419 ((RegValue & RQCP1) != 0) || 1420 ((RegValue & RQCP2) != 0); 1421 return retVal; 1422 } 1423 } 1424 1425 public class FilterMasterRegister 1426 { 1427 public const uint FINIT = (1u << 0); 1428 1429 public const int CAN2SBSHIFT = 8; 1430 public const uint CAN2SBMASK = 0x3F; 1431 1432 public const int RESERVED1SHIFT = 14; 1433 public const int RESERVED2SHIFT = 1; 1434 public const uint RESERVED2MASK = 0x7F; 1435 public const uint RESERVED1MASK = 0x3FFFF; 1436 1437 public bool FilterInitMode; 1438 public uint CAN2StartBank; 1439 public uint Reserved1; 1440 public uint Reserved2; 1441 SetValue(uint value)1442 public void SetValue(uint value) 1443 { 1444 FilterInitMode = (value & FINIT) != 0; 1445 CAN2StartBank = (value >> CAN2SBSHIFT) & CAN2SBMASK; 1446 Reserved1 = (value >> RESERVED1SHIFT) & RESERVED1MASK; 1447 Reserved2 = (value >> RESERVED2SHIFT) & RESERVED2MASK; 1448 } GetValue()1449 public uint GetValue() 1450 { 1451 var retVal = (FilterInitMode ? FINIT : 0) | 1452 ((CAN2StartBank & CAN2SBMASK) << CAN2SBSHIFT) | 1453 ((Reserved1 & RESERVED1MASK) << RESERVED1SHIFT) | 1454 ((Reserved2 & RESERVED2MASK) << RESERVED2SHIFT); 1455 return retVal; 1456 } 1457 } 1458 1459 public class FilterActiveRegister 1460 { 1461 public const uint REGMASK = 0xFFFFFFF; 1462 1463 private uint RegValue; 1464 SetValue(uint value)1465 public void SetValue(uint value) 1466 { 1467 RegValue = value & REGMASK; 1468 } 1469 GetValue()1470 public uint GetValue() 1471 { 1472 return RegValue; 1473 } 1474 FilterActive(int filterIdx)1475 public bool FilterActive(int filterIdx) 1476 { 1477 return (RegValue & (1u << filterIdx)) != 0; 1478 } 1479 } 1480 1481 public class FilterModeRegister 1482 { 1483 private uint RegValue; 1484 SetValue(uint value)1485 public void SetValue(uint value) 1486 { 1487 RegValue = value; 1488 } 1489 GetValue()1490 public uint GetValue() 1491 { 1492 return RegValue; 1493 } 1494 FilterMode(int filterIdx)1495 public FilterBankMode FilterMode(int filterIdx) 1496 { 1497 if((RegValue & (1u << filterIdx)) != 0) 1498 { 1499 return FilterBankMode.FilterIdentifierList; 1500 } 1501 else 1502 { 1503 return FilterBankMode.FilterModeIdMask; 1504 } 1505 } 1506 } 1507 1508 public class FilterScaleRegister 1509 { 1510 private uint RegValue; 1511 SetValue(uint value)1512 public void SetValue(uint value) 1513 { 1514 RegValue = value; 1515 } 1516 GetValue()1517 public uint GetValue() 1518 { 1519 return RegValue; 1520 } 1521 FilterScale(int filterIdx)1522 public FilterBankScale FilterScale(int filterIdx) 1523 { 1524 if((RegValue & (1u << filterIdx)) != 0) 1525 { 1526 return FilterBankScale.FilterScale32Bit; 1527 } 1528 else 1529 { 1530 return FilterBankScale.FilterScale16Bit; 1531 } 1532 } 1533 } 1534 1535 public class FifoAssignmentRegister 1536 { 1537 private uint RegValue; 1538 SetValue(uint value)1539 public void SetValue(uint value) 1540 { 1541 RegValue = value; 1542 } 1543 GetValue()1544 public uint GetValue() 1545 { 1546 return RegValue; 1547 } 1548 FifoAssignment(int filterIdx)1549 public uint FifoAssignment(int filterIdx) 1550 { 1551 if((RegValue & (1u << filterIdx)) != 0) 1552 { 1553 return 1; 1554 } 1555 else 1556 { 1557 return 0; 1558 } 1559 } 1560 } 1561 1562 public class MailboxIdentifierRegister 1563 { 1564 1565 public const uint TXRQ = (1u << 0); 1566 private uint RegValue; 1567 SetValue(uint value)1568 public void SetValue(uint value) 1569 { 1570 RegValue = (value & 0xFFFFFFFE); 1571 } 1572 GetValue()1573 public uint GetValue() 1574 { 1575 return RegValue; 1576 } 1577 TransmitMailboxRequest(uint value)1578 public bool TransmitMailboxRequest(uint value) 1579 { 1580 return (value & TXRQ) != 0; 1581 } 1582 } 1583 } 1584 1585 public class CANMessage 1586 { 1587 public const int STIDSHIFT = 21; 1588 public const uint STIDMASK = 0x7FF; 1589 public const int EXIDSHIFT = 3; 1590 public const uint EXIDMASK = 0x3FFFF; 1591 public const int IDESHIFT = 2; 1592 public const uint IDEMASK = 0x1; 1593 public const int RTRSHIFT = 1; 1594 public const uint RTRMASK = 0x1; 1595 1596 public const int TIMESHIFT = 16; 1597 public const uint TIMEMASK = 0xFFFF; 1598 public const int FMISHIFT = 8; 1599 public const uint FMIMASK = 0xFF; 1600 public const int DLCSHIFT = 0; 1601 public const uint DLCMASK = 0xF; 1602 1603 public const uint RIRMASK = 1604 (STIDMASK << STIDSHIFT) | 1605 (EXIDMASK << EXIDSHIFT) | 1606 (IDEMASK << IDESHIFT) | 1607 (RTRMASK << RTRSHIFT); 1608 public const uint RDTRMASK = (DLCMASK << DLCSHIFT); 1609 1610 public uint CAN_RIR; 1611 public uint CAN_RDTR; 1612 public uint CAN_RLR; 1613 public uint CAN_RHR; 1614 1615 public uint STID; 1616 public uint RTR; 1617 public uint IDE; 1618 public uint EXID; 1619 public uint DLC; 1620 public byte[] Data; 1621 public uint TimeStamp; 1622 1623 public uint FilterMatchIndex; 1624 public uint RxFifo; 1625 CANMessage(uint RIR, uint RDTR, uint RLR, uint RHR)1626 public CANMessage(uint RIR, uint RDTR, uint RLR, uint RHR) 1627 { 1628 CAN_RIR = RIR & RIRMASK; 1629 CAN_RDTR = RDTR & RDTRMASK; 1630 CAN_RLR = RLR; 1631 CAN_RHR = RHR; 1632 1633 // Not needed at Tx 1634 //TimeStamp = (RDTR >> TIMESHIFT) & TIMEMASK; 1635 1636 ExtractRegisters(); 1637 } 1638 CANMessage(uint STID, uint EXID, uint RTR, uint IDE, uint DLC, byte[] Data, uint TimeStamp)1639 public CANMessage(uint STID, uint EXID, uint RTR, 1640 uint IDE, uint DLC, byte[] Data, uint TimeStamp) 1641 { 1642 this.STID = STID; 1643 this.EXID = EXID; 1644 this.RTR = RTR; 1645 this.IDE = IDE; 1646 this.DLC = DLC; 1647 this.Data = Data; 1648 this.TimeStamp = TimeStamp; 1649 1650 GenerateRegisters(); 1651 } 1652 CANMessage(CANMessageFrame message)1653 public CANMessage(CANMessageFrame message) 1654 { 1655 CAN_RIR = (uint)message.Id & RIRMASK; 1656 ExtractRIRRegister(); 1657 1658 //this.TimeStamp = (Data[6] << 8) | Data[7]; 1659 this.DLC = (uint)message.Data.Length; 1660 GenerateRDTRRegister(); 1661 1662 this.Data = message.Data; 1663 GenerateDataRegisters(); 1664 } 1665 GenerateRegisters()1666 public void GenerateRegisters() 1667 { 1668 CAN_RIR = 1669 ((STID & STIDMASK) << STIDSHIFT) | 1670 ((EXID & EXIDMASK) << EXIDSHIFT) | 1671 ((IDE & IDEMASK) << IDESHIFT) | 1672 ((RTR & RTRMASK) << RTRSHIFT); 1673 1674 GenerateRDTRRegister(); 1675 GenerateDataRegisters(); 1676 } 1677 GenerateRDTRRegister()1678 public void GenerateRDTRRegister() 1679 { 1680 CAN_RDTR = 1681 ((TimeStamp & TIMEMASK) << TIMESHIFT) | 1682 ((FilterMatchIndex & FMIMASK) << FMISHIFT) | 1683 ((DLC & DLCMASK) << DLCSHIFT); 1684 } 1685 GenerateDataRegisters()1686 public void GenerateDataRegisters() 1687 { 1688 var l = Data.Length; 1689 CAN_RLR = 0U; 1690 CAN_RLR |= (uint)((l > 0) ? Data[0] << 0 : 0); 1691 CAN_RLR |= (uint)((l > 1) ? Data[1] << 8 : 0); 1692 CAN_RLR |= (uint)((l > 2) ? Data[2] << 16 : 0); 1693 CAN_RLR |= (uint)((l > 3) ? Data[3] << 24 : 0); 1694 CAN_RHR = 0U; 1695 CAN_RHR |= (uint)((l > 4) ? Data[4] << 0 : 0); 1696 CAN_RHR |= (uint)((l > 5) ? Data[5] << 8 : 0); 1697 CAN_RHR |= (uint)((l > 6) ? Data[6] << 16 : 0); 1698 CAN_RHR |= (uint)((l > 7) ? Data[7] << 24 : 0); 1699 } 1700 ExtractRegisters()1701 public void ExtractRegisters() 1702 { 1703 ExtractRIRRegister(); 1704 ExtractRDTRRegister(); 1705 ExtractDataRegisters(); 1706 } 1707 ExtractRIRRegister()1708 public void ExtractRIRRegister() 1709 { 1710 STID = (CAN_RIR >> STIDSHIFT) & STIDMASK; 1711 EXID = (CAN_RIR >> EXIDSHIFT) & EXIDMASK; 1712 IDE = (CAN_RIR >> IDESHIFT) & IDEMASK; 1713 RTR = (CAN_RIR >> RTRSHIFT) & RTRMASK; 1714 } 1715 ExtractRDTRRegister()1716 public void ExtractRDTRRegister() 1717 { 1718 TimeStamp = (CAN_RDTR >> TIMESHIFT) & TIMEMASK; 1719 DLC = (CAN_RDTR >> DLCSHIFT) & DLCMASK; 1720 } 1721 ExtractDataRegisters()1722 public void ExtractDataRegisters() 1723 { 1724 if(DLC > 0) 1725 { 1726 Data = new byte[DLC]; 1727 1728 // Extract CAN_RLR 1729 for(int i = 0; i < DLC && i < 4; i++) 1730 { 1731 Data[i] = (byte)((CAN_RLR >> (i * 8)) & 0xFF); 1732 } 1733 1734 // Extract CAN_RHR 1735 for(int i = 0; (i + 4) < DLC && i < 4; i++) 1736 { 1737 Data[i + 4] = (byte)((CAN_RHR >> (i * 8)) & 0xFF); 1738 } 1739 } 1740 } 1741 } 1742 1743 public class Filter 1744 { 1745 public uint STID; 1746 public uint RTR; 1747 public uint IDE; 1748 public uint EXID; 1749 public uint EXIDMask; 1750 } 1751 1752 public class FilterBank : IComparable<FilterBank> 1753 { 1754 public const int STIDSHIFT = 21; 1755 public const int STIDSHIFT2 = 5; 1756 public const uint STIDMASK = 0x7FF; 1757 public const uint STIDMASK2 = 0x7; 1758 public const int EXIDSHIFT = 3; 1759 public const int EXIDSHIFT2 = 16; 1760 public const int EXIDSHIFT3 = 0; 1761 public const int EXIDSHIFT4 = 15; 1762 public const uint EXIDMASK = 0x3FFFF; 1763 public const uint EXIDMASK2 = 0x7; 1764 public const int IDESHIFT = 2; 1765 public const int IDESHIFT2 = 20; 1766 public const int IDESHIFT3 = 4; 1767 public const uint IDEMASK = 0x1; 1768 public const int RTRSHIFT = 1; 1769 public const int RTRSHIFT2 = 19; 1770 public const int RTRSHIFT3 = 3; 1771 public const uint RTRMASK = 0x1; 1772 1773 public bool Active; 1774 public FilterBankMode Mode; 1775 public FilterBankScale Scale; 1776 public uint FifoAssignment; 1777 public uint[] FR = new uint[2]; 1778 public uint FirstFilterNumber; 1779 public bool BelongsToMaster; 1780 FilterBank()1781 public FilterBank() 1782 { 1783 Active = false; 1784 Mode = FilterBankMode.FilterModeIdMask; 1785 FifoAssignment = 0; 1786 Scale = FilterBankScale.FilterScale16Bit; 1787 BelongsToMaster = true; 1788 } 1789 MatchMessage(CANMessage msg)1790 public bool MatchMessage(CANMessage msg) 1791 { 1792 Filter[] filters = ExtractFilters(); 1793 int NumOfFilters = (Scale == FilterBankScale.FilterScale32Bit) ? 2 : 4; 1794 uint FilterNumber = FirstFilterNumber; 1795 1796 if(Mode == FilterBankMode.FilterModeIdMask) 1797 { 1798 for(int i = 0; i < NumOfFilters / 2; i += 2, FilterNumber++) 1799 { 1800 int mask = i + 1; 1801 if( 1802 ((filters[i].STID & filters[mask].STID) == (msg.STID & filters[mask].STID)) && 1803 ((filters[i].EXID & filters[mask].EXID & filters[mask].EXIDMask) == 1804 (msg.EXID & filters[mask].EXID & filters[mask].EXIDMask)) && 1805 ((filters[i].IDE & filters[mask].IDE) == (msg.IDE & filters[mask].IDE)) && 1806 ((filters[i].RTR & filters[mask].RTR) == (msg.RTR & filters[mask].RTR)) && 1807 ((filters[i].STID & filters[mask].STID) == (msg.STID & filters[mask].STID)) 1808 ) 1809 { 1810 msg.FilterMatchIndex = FilterNumber; 1811 msg.RxFifo = FifoAssignment; 1812 return true; 1813 } 1814 } 1815 } 1816 else 1817 { 1818 for(int i = 0; i < NumOfFilters; i++, FilterNumber++) 1819 { 1820 if( 1821 (filters[i].STID == msg.STID) && 1822 ((filters[i].EXID & filters[i].EXIDMask) == (msg.EXID & filters[i].EXIDMask)) && 1823 (filters[i].IDE == msg.IDE) && 1824 (filters[i].RTR == msg.RTR) 1825 ) 1826 { 1827 msg.FilterMatchIndex = FilterNumber; 1828 msg.RxFifo = FifoAssignment; 1829 return true; 1830 } 1831 } 1832 } 1833 return false; 1834 } 1835 ExtractFilters()1836 public Filter[] ExtractFilters() 1837 { 1838 Filter[] filters; 1839 1840 if(Scale == FilterBankScale.FilterScale32Bit) 1841 { 1842 filters = new Filter[2]; 1843 for(int i = 0; i < 2; i++) 1844 { 1845 filters[i] = new Filter(); 1846 filters[i].STID = (FR[i] >> STIDSHIFT) & STIDMASK; 1847 filters[i].EXID = (FR[i] >> EXIDSHIFT) & EXIDMASK; 1848 filters[i].IDE = (FR[i] >> IDESHIFT) & IDEMASK; 1849 filters[i].RTR = (FR[i] >> RTRSHIFT) & RTRMASK; 1850 filters[i].EXIDMask = 0x3FFF; 1851 } 1852 } 1853 else 1854 { 1855 filters = new Filter[4]; 1856 for(int i = 0; i < 4; i++) 1857 { 1858 filters[i] = new Filter(); 1859 } 1860 filters[0].STID = (FR[0] >> STIDSHIFT) & STIDMASK; 1861 filters[0].IDE = (FR[0] >> IDESHIFT2) & IDEMASK; 1862 filters[0].RTR = (FR[0] >> RTRSHIFT2) & RTRMASK; 1863 filters[0].EXID = ((FR[0] >> EXIDSHIFT2) & EXIDMASK2) << EXIDSHIFT4; 1864 filters[0].EXIDMask = EXIDMASK2 << EXIDSHIFT4; 1865 filters[1].STID = (FR[0] >> STIDSHIFT2) & STIDMASK; 1866 filters[1].IDE = (FR[0] >> IDESHIFT3) & IDEMASK; 1867 filters[1].RTR = (FR[0] >> RTRSHIFT3) & RTRMASK; 1868 filters[1].EXID = ((FR[0] >> EXIDSHIFT3) & EXIDMASK2) << EXIDSHIFT4; 1869 filters[1].EXIDMask = EXIDMASK2 << EXIDSHIFT4; 1870 filters[2].STID = (FR[1] >> STIDSHIFT) & STIDMASK; 1871 filters[2].IDE = (FR[1] >> IDESHIFT2) & 0x1; 1872 filters[2].RTR = (FR[1] >> RTRSHIFT2) & 0x1; 1873 filters[2].EXID = ((FR[1] >> EXIDSHIFT2) & EXIDMASK2) << EXIDSHIFT4; 1874 filters[2].EXIDMask = EXIDMASK2 << EXIDSHIFT4; 1875 filters[3].STID = (FR[1] >> STIDSHIFT2) & STIDMASK; 1876 filters[3].IDE = (FR[1] >> IDESHIFT3) & IDEMASK; 1877 filters[3].RTR = (FR[1] >> RTRSHIFT3) & RTRMASK; 1878 filters[3].EXID = ((FR[1] >> EXIDSHIFT3) & EXIDMASK2) << EXIDSHIFT4; 1879 filters[3].EXIDMask = EXIDMASK2 << EXIDSHIFT4; 1880 } 1881 1882 return filters; 1883 } 1884 CompareTo(FilterBank filterBank)1885 public int CompareTo(FilterBank filterBank) 1886 { 1887 if(filterBank == null) 1888 return 1; 1889 1890 // 32BitScale higher priority than 16BitScale 1891 if(Scale > filterBank.Scale) 1892 return 1; 1893 1894 // IdentifierList higher priority than IdMask 1895 if(Mode > filterBank.Mode) 1896 return 1; 1897 1898 // Lower FilterNumber has higher priority 1899 if(FirstFilterNumber < filterBank.FirstFilterNumber) 1900 return 1; 1901 1902 // Lower priority on this than filterBank 1903 return -1; 1904 } 1905 NumberOfFiltersInBank()1906 public uint NumberOfFiltersInBank() 1907 { 1908 uint NumFiltersInBank = 4; 1909 if(Scale == FilterBankScale.FilterScale32Bit) 1910 { 1911 NumFiltersInBank = 2; 1912 } 1913 if(Mode == FilterBankMode.FilterModeIdMask) 1914 { 1915 NumFiltersInBank /= 2; 1916 } 1917 return NumFiltersInBank; 1918 } 1919 } 1920 1921 private readonly STMCAN master; 1922 1923 private const int NumberOfInterruptLines = 4; 1924 private const int CAN_Tx = 0; 1925 private const int CAN_Rx0 = 1; 1926 private const int CAN_Rx1 = 2; 1927 private const int CAN_SCE = 3; 1928 1929 private const int NumberOfRxFifos = 2; 1930 private const int RxFifo0 = 0; 1931 private const int RxFifo1 = 1; 1932 private const int NumberOfFilterBanks = 28; 1933 1934 public event Action<CANMessageFrame> FrameSent; 1935 private DeviceRegisters registers; 1936 public IReadOnlyDictionary<int, IGPIO> Connections { get; private set; } 1937 private Queue<CANMessage>[] RxFifo = new Queue<CANMessage>[NumberOfRxFifos]; 1938 public FilterBank[] FilterBanks; 1939 public List<FilterBank>[] FifoFiltersPrioritized = new List<FilterBank>[NumberOfRxFifos]; 1940 } 1941 } 1942