|
|
|
|
#include "CAN.h"
|
|
|
|
|
#include "DSP2833x_ECan.h"
|
|
|
|
|
|
|
|
|
|
namespace can_space {
|
|
|
|
|
|
|
|
|
|
CAN::CAN(CAN_VARIANT canVariant) :
|
|
|
|
|
_canPort(canVariant),
|
|
|
|
|
_p_CanRegs(0),
|
|
|
|
|
_p_CanMBoxes(0),
|
|
|
|
|
_p_CanMotoRegs(0),
|
|
|
|
|
_p_CanMotsRegs(0)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CAN::initGpio(){
|
|
|
|
|
if(_canPort == CANA) InitECanaGpio();
|
|
|
|
|
else if (_canPort == CANB) InitECanbGpio();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CAN::config(uint16_t baudrate, uint16_t flags){
|
|
|
|
|
if (_canPort == CANA){
|
|
|
|
|
EALLOW;
|
|
|
|
|
SysCtrlRegs.PCLKCR0.bit.ECANAENCLK = 1;
|
|
|
|
|
EDIS;
|
|
|
|
|
_p_CanRegs = &ECanaRegs;
|
|
|
|
|
_p_CanMBoxes = &ECanaMboxes;
|
|
|
|
|
_p_CanMotoRegs = &ECanaMOTORegs;
|
|
|
|
|
_p_CanMotsRegs = &ECanaMOTSRegs;
|
|
|
|
|
}
|
|
|
|
|
else if (_canPort == CANB){
|
|
|
|
|
EALLOW;
|
|
|
|
|
SysCtrlRegs.PCLKCR0.bit.ECANBENCLK = 1;
|
|
|
|
|
EDIS;
|
|
|
|
|
_p_CanRegs = &ECanbRegs;
|
|
|
|
|
_p_CanMBoxes = &ECanbMboxes;
|
|
|
|
|
_p_CanMotoRegs = &ECanbMOTORegs;
|
|
|
|
|
_p_CanMotsRegs = &ECanbMOTSRegs;
|
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
_CanShadow.CANMC.all = _p_CanRegs->CANMC.all;
|
|
|
|
|
_CanShadow.CANMC.bit.ABO = 1;
|
|
|
|
|
_p_CanRegs->CANMC.all = _CanShadow.CANMC.all;
|
|
|
|
|
|
|
|
|
|
// 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_t boxNumber, const MsgID& configID, const MsgCtrlReg& configCtrlReg){
|
|
|
|
|
if (boxNumber > 31) return;
|
|
|
|
|
|
|
|
|
|
volatile MBOX* p_MailBox(0);
|
|
|
|
|
p_MailBox = &(_p_CanMBoxes->MBOX0) + boxNumber;
|
|
|
|
|
|
|
|
|
|
uint32_t 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_t boxNumber, const MsgID& configID, const MsgCtrlReg& configCtrlReg){
|
|
|
|
|
if (boxNumber > 31) return;
|
|
|
|
|
|
|
|
|
|
volatile MBOX* p_MailBox(0);
|
|
|
|
|
p_MailBox = &(_p_CanMBoxes->MBOX0) + boxNumber;
|
|
|
|
|
|
|
|
|
|
uint32_t 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_t flags){
|
|
|
|
|
EALLOW;
|
|
|
|
|
_p_CanRegs->CANGIM.all = flags;
|
|
|
|
|
EDIS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CAN::configMBoxIsr(uint16_t boxNumber){
|
|
|
|
|
if (boxNumber > 31) return;
|
|
|
|
|
|
|
|
|
|
uint32_t mboxControl(0);
|
|
|
|
|
mboxControl = 1ul << boxNumber;
|
|
|
|
|
|
|
|
|
|
EALLOW;
|
|
|
|
|
_p_CanRegs->CANMIL.all |= mboxControl;
|
|
|
|
|
_p_CanRegs->CANMIM.all |= mboxControl;
|
|
|
|
|
EDIS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CAN::enableTimeOutControl(uint16_t boxNumber){
|
|
|
|
|
if (boxNumber > 31) return;
|
|
|
|
|
|
|
|
|
|
uint32_t mboxControl(0);
|
|
|
|
|
|
|
|
|
|
mboxControl = _p_CanRegs->CANTOC.all;
|
|
|
|
|
mboxControl |= 1ul << boxNumber;
|
|
|
|
|
_p_CanRegs->CANTOC.all = mboxControl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CAN::disableTimeOutControl(uint16_t boxNumber){
|
|
|
|
|
if (boxNumber > 31) return;
|
|
|
|
|
|
|
|
|
|
uint32_t mboxControl(0);
|
|
|
|
|
|
|
|
|
|
mboxControl = _p_CanRegs->CANTOC.all;
|
|
|
|
|
mboxControl &= ~(1ul << boxNumber);
|
|
|
|
|
_p_CanRegs->CANTOC.all = mboxControl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} //can_space
|