📄 ecan.cpp
字号:
#include <c280xpcl.h>
#include <bin.h>
#if defined(__C280X_ECANA)\
|| defined(__C280X_ECANB)
//
// class ecan_base
//
ecan_base::ecan_base (
volatile ECAN_REGS& EcanxRegs
, volatile ECAN_MBOXES& EcanxMboxes
, volatile LAM_REGS& EcanxLAMRegs
, const pclk& /*pclk_ena*/
, pio& CANTX
, pio& CANRX
, unsigned long bitrate
) : EcanRegs(EcanxRegs)
, EcanMboxes(EcanxMboxes)
, EcanLAMRegs(EcanxLAMRegs)
{
/* Create a shadow register structure for the CAN control registers. This 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
*/
struct ECAN_REGS EcanShadow;
EALLOW; // EALLOW enables access to protected bits
// Configure eCAN RX and TX pins for CAN operation using eCAN regs
EcanShadow.CANTIOC.all = EcanRegs.CANTIOC.all;
EcanShadow.CANTIOC.bit.TXFUNC = 1;
EcanRegs.CANTIOC.all = EcanShadow.CANTIOC.all;
EcanShadow.CANRIOC.all = EcanRegs.CANRIOC.all;
EcanShadow.CANRIOC.bit.RXFUNC = 1;
EcanRegs.CANRIOC.all = EcanShadow.CANRIOC.all;
// Configure eCAN for HECC mode - (reqd to access mailboxes 16 thru 31)
// HECC mode also enables time-stamping feature
EcanShadow.CANMC.all = EcanRegs.CANMC.all;
EcanShadow.CANMC.bit.SCB = 1;
EcanRegs.CANMC.all = EcanShadow.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
volatile struct MBOX *pmb = &EcanMboxes.MBOX0;
for(unsigned short n = 0; n < mbox_number; n++, pmb++)
(*pmb).MSGCTRL.all = 0x00000000;
// TAn, RMPn, GIFn bits are all zero upon reset and are cleared again
// as a matter of precaution.
EcanRegs.CANTA.all = 0xFFFFFFFF; /* Clear all TAn bits */
EcanRegs.CANRMP.all = 0xFFFFFFFF; /* Clear all RMPn bits */
EcanRegs.CANGIF0.all = 0xFFFFFFFF; /* Clear all interrupt flag bits */
EcanRegs.CANGIF1.all = 0xFFFFFFFF;
// Configure bit timing parameters for eCAN
EcanShadow.CANMC.all = EcanRegs.CANMC.all;
EcanShadow.CANMC.bit.CCR = 1 ; // Set CCR = 1
EcanRegs.CANMC.all = EcanShadow.CANMC.all;
// Wait until the CPU has been granted permission to change the configuration registers
do
{ EcanShadow.CANES.all = EcanRegs.CANES.all;
} while(EcanShadow.CANES.bit.CCE != 1 ); // Wait for CCE bit to be set..
EcanShadow.CANBTC.all = 0;
// sysclk = 10^9 / CPU_RATE
// BRPREG = sysclk / (15 * br)
EcanShadow.CANBTC.bit.BRPREG =
(unsigned short)(((long double)66666666.667/((long double)CPU_RATE * bitrate)) + 0.5)
- 1;
// bit-time = 15qt, sp = 73,(3)%
EcanShadow.CANBTC.bit.TSEG2REG = 3;
EcanShadow.CANBTC.bit.TSEG1REG = 9;
EcanShadow.CANBTC.bit.SAM = 1;
EcanRegs.CANBTC.all = EcanShadow.CANBTC.all;
EcanShadow.CANMC.all = EcanRegs.CANMC.all;
EcanShadow.CANMC.bit.CCR = 0; // Set CCR = 0
EcanShadow.CANMC.bit.PDR = 0;
EcanShadow.CANMC.bit.DBO = 1;
EcanShadow.CANMC.bit.WUBA = 0;
EcanShadow.CANMC.bit.CDR = 0;
EcanShadow.CANMC.bit.ABO = 1;
EcanShadow.CANMC.bit.STM = 0;
EcanShadow.CANMC.bit.SRES = 0;
EcanShadow.CANMC.bit.MBNR = 0;
EcanShadow.CANMC.bit.SUSP = 1; // free mode
EcanRegs.CANMC.all = EcanShadow.CANMC.all;
// Wait until the CPU no longer has permission to change the configuration registers
do
{ EcanShadow.CANES.all = EcanRegs.CANES.all;
} while(EcanShadow.CANES.bit.CCE != 0 ); // Wait for CCE bit to be cleared..
/* Disable all Mailboxes */
EcanRegs.CANME.all = 0; // Required before writing the MSGIDs
EcanRegs.CANMIL.all = 0xFFFFFFFF; // set all mailbox interrupts to level 1 (ECAN1INT)
EcanRegs.CANMIM.all = 0xFFFFFFFF; // enable all mailbox interrupts
EcanShadow.CANGIM.all = 0;
EcanShadow.CANGIM.bit.GIL = 0; // All global interrupts are mapped to the ECAN0INT interrupt line.
EcanShadow.CANGIM.bit.I0EN = 1; // enable all interrupts for the ECAN0INT
EcanShadow.CANGIM.bit.I1EN = 1; // enable all interrupts for the ECAN1INT
EcanShadow.CANGIM.bit.AAIM = 1; // Abort Acknowledge Interrupt Mask
EcanShadow.CANGIM.bit.WDIM = 1; // Write denied interrupt mask
EcanShadow.CANGIM.bit.WUIM = 1; // Wake-up interrupt mask
EcanShadow.CANGIM.bit.BOIM = 1; // Bus-off interrupt mask
EcanShadow.CANGIM.bit.EPIM = 1; // Error-passive interrupt mask
EcanShadow.CANGIM.bit.WLIM = 1; // Warning level interrupt mask
EcanRegs.CANGIM.all = EcanShadow.CANGIM.all;
EDIS;
}
#ifdef __C280X_ECANxxx_ISR
//iointctrl
void ecan_base::enable_rx_interrupt (unsigned short /*ena*/)
{
}
void ecan_base::enable_rx_interrupt (unsigned short /*ena*/, unsigned short /*level*/)
{
}
void ecan_base::enable_tx_interrupt (unsigned short /*ena*/)
{
}
void ecan_base::enable_tx_interrupt (unsigned short /*ena*/, unsigned short /*level*/)
{
}
#endif //__C280X_ECANxxx_ISR
//
// class mbox
//
mbox::mbox( // configure for transmit
ecan_base& ecanref
, unsigned short n
, unsigned long msgid
, unsigned short rtr
) : ecan(ecanref)
, MboxRegs(*(&ECanaMboxes.MBOX0 + n))
, mbnr(n)
, mask((unsigned long)1 << n)
{ struct ECAN_REGS EcanShadow;
// Clear the appropriate bit in the CANTRS register to 0
ecan.EcanRegs.CANTRR.all |= mask;
// wait until TRS.n clears
do
{ EcanShadow.CANTRS.all = ecan.EcanRegs.CANTRS.all;
} while((EcanShadow.CANTRS.all & mask) != 0 ); // Wait for CCE bit to be cleared..
// Clear the appropriate Abort-Acknowledge bit
ecan.EcanRegs.CANAA.all |= mask;
// Disable the mailbox
EcanShadow.CANME.all = ecan.EcanRegs.CANME.all;
EcanShadow.CANME.all&= ~mask;
ecan.EcanRegs.CANME.all = EcanShadow.CANME.all;
// Loading the message identifier (MSGID) register of the mailbox
MboxRegs.MSGID.all = msgid;
MboxRegs.MSGID.bit.AAM = 0; // ensure that AAM and AME bit cleared for a normal send mailbox
MboxRegs.MSGID.bit.AME = 0;
MboxRegs.MSGID.bit.IDE = 0; // The RECEIVED message had a standard identifier
// Write the data length and RTR flag
MboxRegs.MSGCTRL.bit.DLC = 0;
MboxRegs.MSGCTRL.bit.RTR = rtr;
// Set the mailbox direction (transmit)
EcanShadow.CANMD.all = ecan.EcanRegs.CANMD.all;
EcanShadow.CANMD.all&= ~mask;
ecan.EcanRegs.CANMD.all = EcanShadow.CANMD.all;
// Enable the mailbox
EcanShadow.CANME.all = ecan.EcanRegs.CANME.all;
EcanShadow.CANME.all|= mask;
ecan.EcanRegs.CANME.all = EcanShadow.CANME.all;
}
mbox::mbox( // configure for receive
ecan_base& ecanref
, unsigned short n
, unsigned long msgid
, unsigned long lam
, unsigned short opc
, unsigned short rtr
) : ecan(ecanref)
, MboxRegs(*(&ECanaMboxes.MBOX0 + n))
, mbnr(n)
, mask((unsigned long)1 << n)
{ struct ECAN_REGS EcanShadow;
// Disable the mailbox
EcanShadow.CANME.all = ecan.EcanRegs.CANME.all;
EcanShadow.CANME.all&= ~mask;
ecan.EcanRegs.CANME.all = EcanShadow.CANME.all;
// Loading the message identifier (MSGID)
// and corresponding acceptance mask
MboxRegs.MSGID.all = msgid;
if(MboxRegs.MSGID.bit.AME != 0)
(*(&ecan.EcanLAMRegs.LAM0 + mbnr)).all = lam;
// Set the mailbox direction (receive)
EcanShadow.CANMD.all = ecan.EcanRegs.CANMD.all;
EcanShadow.CANMD.all|= mask;
ecan.EcanRegs.CANMD.all = EcanShadow.CANMD.all;
// overwrite protection control
EcanShadow.CANOPC.all = ecan.EcanRegs.CANOPC.all;
if(opc)
EcanShadow.CANOPC.all |= mask;
else
EcanShadow.CANOPC.all &= ~mask;
ecan.EcanRegs.CANOPC.all = EcanShadow.CANOPC.all;
// Write the RTR flag
MboxRegs.MSGCTRL.bit.RTR = rtr;
// Enable the mailbox
EcanShadow.CANME.all = ecan.EcanRegs.CANME.all;
EcanShadow.CANME.all|= mask;
ecan.EcanRegs.CANME.all = EcanShadow.CANME.all;
}
mbox::size_type mbox::size()
{ return (size_type)MboxRegs.MSGCTRL.bit.DLC;
}
template bool __safe_wait_helper<mbox::transmission>(mbox::transmission);
void mbox::write(data_type* buf, size_type bufsize )
{ if( buf == 0
|| bufsize == 0
|| (ecan.EcanRegs.CANMD.all & mask) != 0)
return;
struct ECAN_REGS EcanShadow;
// wait for previous trasmission end
safe_wait(transmission(*this));
if(ecan.EcanRegs.CANTRS.all & mask)
{ ecan.EcanRegs.CANTRR.all |= mask;
}
// clear transmit acknowledge bit
EcanShadow.CANTA.all = ecan.EcanRegs.CANTA.all;
EcanShadow.CANTA.all|= mask;
ecan.EcanRegs.CANTA.all = EcanShadow.CANTA.all;
while(ecan.EcanRegs.CANTA.all & mask);
if(bufsize > max_bufsize)
bufsize = max_bufsize;
EALLOW;
EcanShadow.CANMC.all = ecan.EcanRegs.CANMC.all;
EcanShadow.CANMC.bit.MBNR = mbnr;
EcanShadow.CANMC.bit.CDR = 1;
ecan.EcanRegs.CANMC.all = EcanShadow.CANMC.all;
if(bufsize != size())
MboxRegs.MSGCTRL.bit.DLC = bufsize;
for(size_type n = 0; n < bufsize; n++)
binarizer((binarizer::value_type*)&MboxRegs.MDL.all, n) = *binarizer(buf, n);
EcanShadow.CANMC.all = ecan.EcanRegs.CANMC.all;
EcanShadow.CANMC.bit.MBNR = 0;
EcanShadow.CANMC.bit.CDR = 0;
ecan.EcanRegs.CANMC.all = EcanShadow.CANMC.all;
EDIS;
// transmit request
ecan.EcanRegs.CANTRS.all |= mask;
}
void mbox::read (data_type* buf, size_type bufsize )
{ if((ecan.EcanRegs.CANRMP.all & mask) == 0)
return;
if(bufsize < size())
bufsize = size();
for(size_type n = 0; n < bufsize; n++)
binarizer(buf, n) = *binarizer((binarizer::value_type*)&MboxRegs.MDL.all, n);
ecan.EcanRegs.CANRMP.all |= mask;
}
//
// class mbox::transmission
//
mbox::transmission::transmission(mbox& mbRef)
: mb(mbRef)
{
}
bool mbox::transmission::operator()(void) const
{ return mb.ecan.EcanRegs.CANTRS.all & mb.mask;
}
#if defined(__C280X_ECANA)
//
// class ecana
//
ecana::ecana(
pio& CANTX
, pio& CANRX
, unsigned long bitrate
) : ecan_base (
ECanaRegs
, ECanaMboxes
, ECanaLAMRegs
, pclk(SysCtrlRegs.PCLKCR0.all, 0x4000)
, CANTX
, CANRX
, bitrate
)
{ EALLOW;
#ifdef __C280X_ECANA0_ISR
PieVectTable.ECAN0INTA = (PINT)&ecana0_isr;
#endif //__C280X_ECANA0_ISR
#ifdef __C280X_ECANA1_ISR
PieVectTable.ECAN1INTA = (PINT)&ecana1_isr;
#endif //__C280X_ECANA1_ISR
EDIS;
}
#ifdef __C280X_ECANxxx_ISR
//iointctrl
void ecana::enable_pie_interrupt(unsigned short ena)
{ ::enable_pie_interrupt(ena, 9, 0x0030);
}
#endif //__C280X_ECANxxx_ISR
#endif // __C280X_ECANA
#endif // #if defined(__C280X_ECANA)\
|| defined(__C280X_ECANB)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -