#include "CAN.h" namespace canSpace { CAN::CAN(CAN_VARIANT canVariant) : canPort(canVariant) {} void CAN::initGpio(){ if(canPort == CANA) InitECanaGpio(); else if (canPort == CANB) InitECanbGpio(); } void CAN::config(Uint16 baudrate, Uint16 flags){ if (canPort == CANA){ EALLOW; SysCtrlRegs.PCLKCR0.bit.ECANAENCLK = 1; EDIS; p_CanRegs_ = &ECanaRegs; p_CanMBoxes_ = &ECanaMboxes; } else if (canPort == CANB){ EALLOW; SysCtrlRegs.PCLKCR0.bit.ECANBENCLK = 1; EDIS; p_CanRegs_ = &ECanbRegs; p_CanMBoxes_ = &ECanbMboxes; } else { return; } // Create a shadow register structure for the CAN control registers. This // TODO add this into description // is needed, since only 32-bit access is allowed to these registers. // 16-bit access to these registers could potentially corrupt the register // contents or return false data. This is especially true while writing // to/reading from a bit (or group of bits) among bits 16 - 31 EALLOW; // Configure eCAN RX and TX pins for CAN operation using eCAN regs CanShadow_.CANTIOC.all = p_CanRegs_->CANTIOC.all; CanShadow_.CANTIOC.bit.TXFUNC = 1; p_CanRegs_->CANTIOC.all = CanShadow_.CANTIOC.all; CanShadow_.CANRIOC.all = p_CanRegs_->CANRIOC.all; CanShadow_.CANRIOC.bit.RXFUNC = 1; p_CanRegs_->CANRIOC.all = CanShadow_.CANRIOC.all; // Configure eCAN for HECC mode - (reqd to access mailboxes 16 thru 31) // HECC mode also enables time-stamping feature CanShadow_.CANMC.all = p_CanRegs_->CANMC.all; CanShadow_.CANMC.bit.SCB = 1; p_CanRegs_->CANMC.all = CanShadow_.CANMC.all; // Initialize all bits of 'Master Control Field' to zero // Some bits of MSGCTRL register come up in an unknown state. For proper // operation, all bits (including reserved bits) of MSGCTRL must be // initialized to zero p_CanMBoxes_->MBOX0.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX1.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX2.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX3.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX4.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX5.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX6.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX7.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX8.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX9.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX10.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX11.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX12.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX13.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX14.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX15.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX16.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX17.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX18.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX19.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX20.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX21.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX22.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX23.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX24.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX25.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX26.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX27.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX28.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX29.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX30.MSGCTRL.all = 0x00000000; p_CanMBoxes_->MBOX31.MSGCTRL.all = 0x00000000; // TAn, RMPn, GIFn bits are all zero upon reset and are cleared again // as a matter of precaution. p_CanRegs_->CANTA.all = 0xFFFFFFFF; p_CanRegs_->CANRMP.all = 0xFFFFFFFF; p_CanRegs_->CANGIF0.all = 0xFFFFFFFF; p_CanRegs_->CANGIF1.all = 0xFFFFFFFF; // Configure bit timing parameters for eCANA CanShadow_.CANMC.all = p_CanRegs_->CANMC.all; CanShadow_.CANMC.bit.CCR = 1 ; p_CanRegs_->CANMC.all = CanShadow_.CANMC.all; do { CanShadow_.CANES.all = p_CanRegs_->CANES.all; } while(CanShadow_.CANES.bit.CCE != 1 ); // LSB - 0; MSB - 1 CanShadow_.CANMC.all = p_CanRegs_->CANMC.all; if (flags & MSB_ENABLE){ CanShadow_.CANMC.bit.DBO = 1; } else { CanShadow_.CANMC.bit.DBO = 0; } p_CanRegs_->CANMC.all = CanShadow_.CANMC.all; CanShadow_.CANBTC.all = 0; // The following block for all 150 MHz SYSCLKOUT // (75 MHz CAN clock) - default. Bit rate = 1 Mbps / 500 kbps / 250 kbps / 100 kbps switch (baudrate) { case 1000: CanShadow_.CANBTC.bit.BRPREG = 4; CanShadow_.CANBTC.bit.TSEG2REG = 3; CanShadow_.CANBTC.bit.TSEG1REG = 9; break; case 500: CanShadow_.CANBTC.bit.BRPREG = 9; CanShadow_.CANBTC.bit.TSEG2REG = 3; CanShadow_.CANBTC.bit.TSEG1REG = 9; break; case 250: CanShadow_.CANBTC.bit.BRPREG = 19; CanShadow_.CANBTC.bit.TSEG2REG = 3; CanShadow_.CANBTC.bit.TSEG1REG = 9; break; case 100: CanShadow_.CANBTC.bit.BRPREG = 49; CanShadow_.CANBTC.bit.TSEG2REG = 3; CanShadow_.CANBTC.bit.TSEG1REG = 9; break; default: return; } CanShadow_.CANBTC.bit.SAM = 1; p_CanRegs_->CANBTC.all = CanShadow_.CANBTC.all; CanShadow_.CANMC.all = p_CanRegs_->CANMC.all; CanShadow_.CANMC.bit.CCR = 0 ; p_CanRegs_->CANMC.all = CanShadow_.CANMC.all; do { CanShadow_.CANES.all = p_CanRegs_->CANES.all; } while(CanShadow_.CANES.bit.CCE != 0 ); // Wait for CCE bit to be cleared // Disable all Mailboxes p_CanRegs_->CANME.all = 0; // Disable all interrupts p_CanRegs_->CANGIM.all = 0; p_CanRegs_->CANMIM.all = 0; // // Debug feature // Configure the eCAN for self test mode. CanShadow_.CANMC.all = p_CanRegs_->CANMC.all; if (flags & STM_ENABLE){ CanShadow_.CANMC.bit.STM = 1; } else { CanShadow_.CANMC.bit.STM = 0; } p_CanRegs_->CANMC.all = CanShadow_.CANMC.all; EDIS; } void CAN::configTxMBox(Uint16 boxNumber, const MsgID& configID, const MsgCtrlReg& configCtrlReg){ if (boxNumber > 31) return; volatile MBOX* p_MailBox(0); p_MailBox = &(p_CanMBoxes_->MBOX0) + boxNumber; Uint32 mboxControl(0); mboxControl = 1ul << boxNumber; // Reset transmittion if (CanShadow_.CANTRS.all &= mboxControl) { CanShadow_.CANTRR.all = p_CanRegs_->CANTRR.all; CanShadow_.CANTRR.all |= mboxControl; p_CanRegs_->CANTRR.all = CanShadow_.CANTRR.all; do {CanShadow_.CANTRS.all = p_CanRegs_->CANTRS.all;} while((CanShadow_.CANTRS.all & mboxControl) != 0); // Wait for TRS bit to be cleared } // Mailbox disable CanShadow_.CANME.all = p_CanRegs_->CANME.all; CanShadow_.CANME.all &= ~(mboxControl); p_CanRegs_->CANME.all = CanShadow_.CANME.all; // Write to the MSGID field p_MailBox->MSGID.all = configID.all; // Mailbox direction - transmit CanShadow_.CANMD.all = p_CanRegs_->CANMD.all; CanShadow_.CANMD.all &= ~(mboxControl); p_CanRegs_->CANMD.all = CanShadow_.CANMD.all; // Write to RTR and TPL field in control reg p_MailBox->MSGCTRL.bit.RTR = configCtrlReg.bit.RTR; p_MailBox->MSGCTRL.bit.TPL = configCtrlReg.bit.TPL; // Mailbox enable CanShadow_.CANME.all = p_CanRegs_->CANME.all; CanShadow_.CANME.all |= mboxControl; p_CanRegs_->CANME.all = CanShadow_.CANME.all; } void CAN::configRxMBox(Uint16 boxNumber, const MsgID& configID, const MsgCtrlReg& configCtrlReg){ if (boxNumber > 31) return; volatile MBOX* p_MailBox(0); p_MailBox = &(p_CanMBoxes_->MBOX0) + boxNumber; Uint32 mboxControl(0); mboxControl = 1ul << boxNumber; // Mailbox disable CanShadow_.CANME.all = p_CanRegs_->CANME.all; CanShadow_.CANME.all &= ~(mboxControl); p_CanRegs_->CANME.all = CanShadow_.CANME.all; // Write to the MSGID field p_MailBox->MSGID.all = 0x0; p_MailBox->MSGID.all = configID.all; // Write to DLC and RTR field in control reg p_MailBox->MSGCTRL.bit.DLC = configCtrlReg.bit.DLC; p_MailBox->MSGCTRL.bit.RTR = configCtrlReg.bit.RTR; // Configure Mailbox under test as a Receive mailbox CanShadow_.CANMD.all = p_CanRegs_->CANMD.all; CanShadow_.CANMD.all |= mboxControl; p_CanRegs_->CANMD.all = CanShadow_.CANMD.all; // Overwrite protection // If "ON" make sure that an additional mailbox is configured to store ’overflow’ messages. // CanShadow_.CANOPC.all = p_CanRegs_->CANOPC.all; // CanShadow_.CANOPC.all |= mboxControl; // Should be one more mailbox to store 'overflow' messages // p_CanRegs_->CANOPC.all = CanShadow_.CANOPC.all; // Enable Mailbox CanShadow_.CANME.all = p_CanRegs_->CANME.all; CanShadow_.CANME.all |= mboxControl; p_CanRegs_->CANME.all = CanShadow_.CANME.all; } void CAN::configSystemIsr(Uint32 flags){ EALLOW; p_CanRegs_->CANGIM.all = flags; EDIS; } } //canSpace