You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
CCS-COMM_BOARD/Protocol/CANConfig.cpp

287 lines
9.0 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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 );
// MSB - 0; LSB - 1
CanShadow_.CANMC.all = p_CanRegs_->CANMC.all;
if (flags & MSB_ENABLE){
CanShadow_.CANMC.bit.DBO = 0;
}
else
{ CanShadow_.CANMC.bit.DBO = 1; }
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;
// Config MBOX control reg
p_MailBox->MSGCTRL.all = configCtrlReg.all;
// 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.
if(configCtrlReg.bit.OPC){
CanShadow_.CANOPC.all = p_CanRegs_->CANOPC.all;
CanShadow_.CANOPC.all |= mboxControl;
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;
}
void CAN::configMBoxIsr(Uint16 boxNumber){
if (boxNumber > 31) return;
Uint32 mboxControl(0);
mboxControl = 1ul << boxNumber;
EALLOW;
p_CanRegs_->CANMIL.all |= mboxControl;
p_CanRegs_->CANMIM.all |= mboxControl;
EDIS;
}
} //canSpace