123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 |
- //==============================================================================
- // Purpose: allgemeines CAN Interface für FlexCAN von MPC5646
- //
- // Created on: 20.04.2012 by IPE
- //
- // History
- // 20.04.2012 neu, T.Maurer
- // 29.07.2013 CAN_Init() modified V.Reiling
- // 26.02.2016 CAN_Init() modified V.Reiling: Sample Point at 87.5%
- //==============================================================================
- #include "BMS_Master.h"
- //CAN - MESSAGEBOX-STATUS-CODES
- #define CAN_MBCODE_RXINACTIVE 0
- #define CAN_MBCODE_RXEMPTY 4
- #define CAN_MBCODE_RXFULL 2
- #define CAN_MBCODE_RXOVERRUN 6 // MB war voll und wurde nicht von CPU ausgelesen
- #define CAN_MBCODE_RXBUSY 1 // (XXX1)
- #define CAN_MBCODE_TXINACTIVE 8 //Grundzustand
- #define CAN_MBCODE_TXABORT 9 //ABORT muss mit MCR.AEN freigegeben werden
- #define CAN_MBCODE_TXSEND 12 //RTR=0 -> sende Data, wenn beendet: Rückkehr zu INACTIVE;
- //RTR=1 -> sende RemoteFrame, Wenn fertig: neuer Zustand = CAN_MBCODE_RXEMPTY
- #define CAN_MBCODE_TXREMOTEWAIT 10 //warte auf Remote request und sende Data zurück (-> CAN_MBCODE_TXREMOTESEND)
- #define CAN_MBCODE_TXREMOTESEND 16 //sende Data nach Remote request, wenn beendet: Rückkehr zu CAN_MBCODE_TXREMOTEWAIT;
- //Abort Enable des Boards verwenden?
- #define CAN_AEN 0
- //Funktionen
- int8_t CAN_Init(CAN_CONFIG *config)
- {
- volatile struct FLEXCAN_tag *p_CAN = config->CAN_Modul;
- uint8_t i;
-
- // Fehler-Check: CAN-Modul-Adresse vorhanden?
- if ((p_CAN != &CAN_0) &&
- (p_CAN != &CAN_1) &&
- (p_CAN != &CAN_2) &&
- (p_CAN != &CAN_3) &&
- (p_CAN != &CAN_4) &&
- (p_CAN != &CAN_5) )
- return CAN_ERROR;
- // MCR-Register, die meisten Bits koennen nur im FreezeMode beschrieben werden
- p_CAN->MCR.B.MDIS = 0; // Module Disable (init=1)
- while (p_CAN->MCR.B.LPMACK) {}
- p_CAN->MCR.B.FRZ = 1; // FreezeMode enable (initVal=1)
- p_CAN->MCR.B.HALT = 1; // FreezeMode ON (wenn FRZ=1);(initVal=1) Clear after module-init
- while (!p_CAN->MCR.B.FRZACK) {} // warte auf FreezeMode
-
- p_CAN->MCR.B.BCC = 1; // 1 = Enable Indididual RxMasking
- if (config->RxMaskType == RxMask_Global)
- {
- p_CAN->MCR.B.BCC = 0; // 0 = Enable Global RxMasking
- p_CAN->RXGMASK.R = config->GlobalRxMask; // Global Acceptance Mask (InitVal = 0xFFFF_FFFF)
- }
-
- p_CAN->MCR.B.AEN = CAN_AEN; // Abort Enable
- p_CAN->MCR.B.SUPV = 0; // Freeze mode only:
-
- switch( config->BaudConfig )
- {
- case CANBaud_1000kHz_OSC_40MHz : // @ 40m Buslength
- p_CAN->CR.B.CLKSRC = 0; // CPI-ClockSource: 0=oscillator clock (40MHz); 1=bus clock (PLL/2=60MHz)
- p_CAN->CR.B.PRESDIV = 1; // f_SerialClock = f_CPI_clock / (PRESDIV + 1)
- p_CAN->CR.B.PROPSEG = 7; // Propagation Segment Time = (PROPSEG + 1) * Time-Quanta.
- p_CAN->CR.B.PSEG1 = 7; // Phase Buffer Segment 1 = (PSEG1 + 1) x Time-Quanta.
- p_CAN->CR.B.PSEG2 = 2; // Phase Buffer Segment 2 = (PSEG1 + 1) x Time-Quanta.
- p_CAN->CR.B.RJW = 0; // Resync Jump Width = RJW + 1.
- break;
-
- case CANBaud_500kHz_OSC_40MHz : // @ 100m Buslength
- p_CAN->CR.B.CLKSRC = 0; // CPI-ClockSource: 0=oscillator clock (40MHz); 1=bus clock (PLL/2=60MHz)
- p_CAN->CR.B.PRESDIV = 4; // f_SerialClock = f_CPI_clock / (PRESDIV + 1)
- p_CAN->CR.B.PROPSEG = 4; // Propagation Segment Time = (PROPSEG + 1) * Time-Quanta.
- p_CAN->CR.B.PSEG1 = 7; // Phase Buffer Segment 1 = (PSEG1 + 1) x Time-Quanta.
- p_CAN->CR.B.PSEG2 = 1; // Phase Buffer Segment 2 = (PSEG1 + 1) x Time-Quanta.
- p_CAN->CR.B.RJW = 0; // Resync Jump Width = RJW + 1.
- break;
-
- case CANBaud_250kHz_OSC_40MHz : // @ 200m Buslength
- p_CAN->CR.B.CLKSRC = 0; // CPI-ClockSource: 0=oscillator clock (40MHz); 1=bus clock (PLL/2=60MHz)
- p_CAN->CR.B.PRESDIV = 9; // f_SerialClock = f_CPI_clock / (PRESDIV + 1)
- p_CAN->CR.B.PROPSEG = 4; // Propagation Segment Time = (PROPSEG + 1) * Time-Quanta.
- p_CAN->CR.B.PSEG1 = 7; // Phase Buffer Segment 1 = (PSEG1 + 1) x Time-Quanta.
- p_CAN->CR.B.PSEG2 = 1; // Phase Buffer Segment 2 = (PSEG1 + 1) x Time-Quanta.
- p_CAN->CR.B.RJW = 0; // Resync Jump Width = RJW + 1.
- break;
-
- case CANBaud_125kHz_OSC_40MHz : // @ 420m Buslength
- p_CAN->CR.B.CLKSRC = 0; // CPI-ClockSource: 0=oscillator clock (40MHz); 1=bus clock (PLL/2=60MHz)
- p_CAN->CR.B.PRESDIV = 19; // f_SerialClock = f_CPI_clock / (PRESDIV + 1)
- p_CAN->CR.B.PROPSEG = 4; // Propagation Segment Time = (PROPSEG + 1) * Time-Quanta.
- p_CAN->CR.B.PSEG1 = 7; // Phase Buffer Segment 1 = (PSEG1 + 1) x Time-Quanta.
- p_CAN->CR.B.PSEG2 = 1; // Phase Buffer Segment 2 = (PSEG1 + 1) x Time-Quanta.
- p_CAN->CR.B.RJW = 0; // Resync Jump Width = RJW + 1.
- break;
-
- default :
- return CAN_ERROR;
- }
- p_CAN->CR.B.SMP = 1; // Sampling Mode: 0=1 Sample, 1=3 Samples
- switch( config->Port )
- {
- case CAN0_PortB0_1 : // Config Ports: PB0 = CAN0_Tx, PB1 = CAN0_Rx
- SIU.PCR[16].B.OBE = 1; // Output Buffer Enable = Output
- SIU.PCR[16].B.PA = 1; // Pad Output Assignment = CAN0TX
- SIU.PCR[16].B.ODE = (config->TxPortType==Tx_OpenDrain)? 1:0; // Open Drain Output Enable
- SIU.PCR[16].B.SRC = 1; // Slew Rate Control = Fast
- SIU.PCR[17].B.IBE = 1; // Input Buffer Enable = Input
- break;
-
- case CAN1_PortC10_11 : // Config Ports: PC10 = CAN1_Tx, PC11 = CAN1_Rx
- SIU.PCR[42].B.OBE = 1; // Output Buffer Enable = Output
- SIU.PCR[42].B.PA = 1; // Pad Output Assignment = CAN1TX
- SIU.PCR[42].B.ODE = (config->TxPortType==Tx_OpenDrain)? 1:0; // Open Drain Output Enable
- SIU.PCR[42].B.SRC = 1; // Slew Rate Control = Fast
- SIU.PCR[43].B.IBE = 1; // Input Buffer Enable = Input
- SIU.PSMI[0].R = 0x01; // Peripheral input pin selection: CAN1RX -> PCR[43]
- break;
-
- case CAN2_PortE8_9 : // Config Ports: PE8 = CAN2_Tx, PE9 = CAN2_Rx
- SIU.PCR[72].B.OBE = 1; // Output Buffer Enable = Output
- SIU.PCR[72].B.PA = 1; // Pad Output Assignment = CAN2TX
- SIU.PCR[72].B.ODE = (config->TxPortType==Tx_OpenDrain)? 1:0; // Open Drain Output Enable
- SIU.PCR[72].B.SRC = 1; // Slew Rate Control = Fast
- SIU.PCR[73].B.IBE = 1; // Input Buffer Enable = Input
- SIU.PSMI[1].R = 0x00; // Peripheral input pin selection: CAN2RX -> PCR[73]
- break;
- case CAN3_PortF8_9 : // Config Ports: PF8 = CAN3_Tx, PF9 = CAN3_Rx
- SIU.PCR[88].B.OBE = 1; // Output Buffer Enable = Output
- SIU.PCR[88].B.PA = 1; // Pad Output Assignment = CAN3TX
- SIU.PCR[88].B.ODE = (config->TxPortType==Tx_OpenDrain)? 1:0; // Open Drain Output Enable
- SIU.PCR[88].B.SRC = 1; // Slew Rate Control = Fast
- SIU.PCR[89].B.IBE = 1; // Input Buffer Enable = Input
- SIU.PSMI[2].R = 0x02; // Peripheral input pin selection: CAN3RX -> PCR[89]
- break;
-
- default :
- return CAN_ERROR;
- }
-
- p_CAN->MCR.B.MAXMB = 55; // Max 64 Massage Buffer
- for (i=0; i<64; i++)
- p_CAN->BUF[i].CS.B.CODE = CAN_MBCODE_RXINACTIVE; // Inactivate all message buffers
-
- p_CAN->MCR.B.HALT = 0; // FreezeModeON-Bit; Clear after module-init (init=1)
- p_CAN->MCR.B.FRZ = 0; // FreezeMode
- return CAN_OK;
- }
- int8_t CAN_Init_Mailbox(CAN_MAILBOX *mbox)
- {
- volatile struct FLEXCAN_BUF_t *p_BUF; //pointer auf einen Message Buffer
- volatile struct FLEXCAN_tag *p_CAN = mbox->p_CAN_Config->CAN_Modul;
-
- if (mbox->MBNumber >= 64) return CAN_ERROR;
- p_BUF = p_CAN->BUF + mbox->MBNumber;
- if (p_CAN->MCR.B.LPMACK) return CAN_ERROR; //CAN in DisableMode
- p_CAN->MCR.B.FRZ = 1; // FreezeMode enable (initVal=1)
- p_CAN->MCR.B.HALT = 1; // FreezeMode ON (wenn FRZ=1);(initVal=1) Clear after module-init
- while (!p_CAN->MCR.B.FRZACK) {} //warte auf FreezeMode
-
- if (mbox->RemoteEn >= 2) return CAN_ERROR;
- p_BUF->CS.B.RTR = mbox->RemoteEn; /* Data frame, not remote Tx request frame */
- if (mbox->Direction == MB_Tx) {
- //TX-Box
- if (mbox->DataBytes >= 9) return CAN_ERROR;
- p_BUF->CS.B.LENGTH = mbox->DataBytes; /* # bytes to transmit*/
- p_BUF->CS.B.CODE = CAN_MBCODE_TXINACTIVE;
- }
- else if (mbox->Direction == MB_Rx) {
- //RX-Box
- p_BUF->CS.B.CODE = CAN_MBCODE_RXEMPTY;
- //Individuelle Acceptance Mask
- if (mbox->p_CAN_Config->RxMaskType == RxMask_Individual)
- p_CAN->RXIMR[mbox->MBNumber].R = mbox->AcceptMask;
- //MB-Interrupt-Enable
- }
- else return CAN_ERROR;
-
- if( mbox->IDE == SHORT_ID)
- {
- p_BUF->CS.B.IDE = 0; // Use standard ID length
- p_BUF->ID.B.STD_ID = mbox->ID;
- }
- else
- {
- p_BUF->CS.B.IDE = 1; // Use extended ID length
- p_BUF->ID.B.EXT_ID = (mbox->ID & 0x3FFFF);
- p_BUF->ID.B.STD_ID = (mbox->ID >> 18);
- }
-
- if (mbox->Interrupt) {
- if (mbox->MBNumber <= 31)
- SETBIT(p_CAN->IMRL.R, mbox->MBNumber); // Interrupt Mask 1
- else
- SETBIT(p_CAN->IMRH.R, mbox->MBNumber - 32); // Interrupt Mask 2
- }
- p_CAN->MCR.B.HALT = 0; // FreezeMode ON (wenn FRZ=1);(initVal=1) Clear after module-init
- p_CAN->MCR.B.FRZ = 0; //FreezeMode;
- //init Ende
- return CAN_OK;
- }
- int8_t CAN_Write(CAN_MAILBOX *mbox, uint8_t *data)
- {
- uint8_t i;
- volatile struct FLEXCAN_BUF_t *p_BUF;
- volatile struct FLEXCAN_tag *p_CAN = mbox->p_CAN_Config->CAN_Modul;
-
- if (p_CAN->MCR.B.NOTRDY) return CAN_ERROR;
- p_BUF = p_CAN->BUF + mbox->MBNumber;
- if (mbox->MBNumber >= 64) return CAN_ERROR;
- p_BUF->CS.B.CODE = CAN_MBCODE_TXINACTIVE;
- //I-Flag löschen, um die MB zu entsperren
- /* if (mbox->MBNumber < 32)
- p_CAN->IFRL.R = 1 << mbox->MBNumber;
- else
- p_CAN->IFRH.R = 1 << (mbox->MBNumber-32);
- */ p_BUF = p_CAN->BUF + mbox->MBNumber; //pointer auf einen Message Buffer
-
- if( mbox->IDE == SHORT_ID)
- p_BUF->ID.B.STD_ID = mbox->ID;
- else
- p_BUF->ID.B.EXT_ID = mbox->ID;
- for (i=0; i<mbox->DataBytes; i++) {
- p_BUF->DATA.B[i] = *(data+i); /* Data to be transmitted */
- }
- // CAN_0.BUF[0].CS.B.SRR = 1; /* Tx frame (not req'd for standard frame)*/
- p_BUF->CS.B.CODE = CAN_MBCODE_TXSEND; /* Activate msg. buf. to transmit data frame */
- return CAN_OK;
- }
- int8_t CAN_Write_dataset(CAN_MAILBOX *mbox, uint8_t* data,uint64_t timestamp)
- {
- uint8_t i;
- int8_t CAN_status=CAN_OK;
- uint8_t dataSetSize= mbox->DataBytes;
- volatile struct FLEXCAN_BUF_t *p_BUF;
- volatile struct FLEXCAN_tag *p_CAN = mbox->p_CAN_Config->CAN_Modul;
- p_BUF = p_CAN->BUF + mbox->MBNumber;
- while(p_BUF->CS.B.CODE !=CAN_MBCODE_TXINACTIVE) {
- //wait
- if(Global_1msCounter >= timestamp + CAN1_TX_TIMEOUT) {
- return CAN_ERROR;
- }
- }
- CAN_status=CAN_Write(mbox,data);
- timestamp=Global_1msCounter;
- if(CAN_status != CAN_OK) {
- return CAN_ERROR;
- }
-
- return CAN_OK;
- }
- int8_t CAN_Read(CAN_MAILBOX *mbox, uint8_t *data)
- {
- uint8_t i;
- int8_t returnval;
- uint32_t dummy;
- volatile struct FLEXCAN_BUF_t *p_BUF; //pointer auf einen Message Buffer
- volatile struct FLEXCAN_tag *p_CAN = mbox->p_CAN_Config->CAN_Modul;
- returnval = CAN_OK;
-
- if (mbox->MBNumber >= 64) return CAN_ERROR;
- p_BUF = p_CAN->BUF + mbox->MBNumber;
- dummy = p_BUF->CS.B.CODE; //Muss ausgelesen werden zum Lock des Puffers
- if (p_BUF->CS.B.LENGTH > CAN_DATA_ARR_LEN) returnval = CAN_ERROR;
- if (p_BUF->CS.B.LENGTH != mbox->DataBytes) returnval = CAN_ERROR;
-
- if( mbox->IDE == SHORT_ID)
- mbox->ID = p_BUF->ID.B.STD_ID; // copy received ID to MailBox
- else
- mbox->ID = p_BUF->ID.B.EXT_ID; // copy received ID to MailBox
-
- for (i=0; i < p_BUF->CS.B.LENGTH; i++){
- *(data+i) = p_BUF->DATA.B[i];
- }
- //Timer auslesen und I-Flag löschen, um die MB zu entsperren
- dummy = p_CAN->TIMER.R;
- // Clear Int-Flag
- if (mbox->MBNumber < 32)
- p_CAN->IFRL.R = 1 << mbox->MBNumber;
- else
- p_CAN->IFRH.R = 1 << (mbox->MBNumber-32);
- return returnval;
- }
- // Funktionen
- int8_t CAN_Abort(CAN_MAILBOX *mbox)
- {
- volatile struct FLEXCAN_BUF_t *p_BUF;
- volatile struct FLEXCAN_tag *p_CAN = mbox->p_CAN_Config->CAN_Modul;
-
- p_BUF = p_CAN->BUF + mbox->MBNumber; //pointer auf einen Message Buffer
- if (mbox->Direction == MB_Rx) return CAN_ERROR;
- #if CAN_AEN == 1
- p_BUF->CS.B.CODE = CAN_MBCODE_TXABORT;
- #else
- p_BUF->CS.B.CODE = CAN_MBCODE_TXINACTIVE;
- #endif
- return CAN_OK;
- }
- /**
- * @function Check CAN Error State Register for Errors
- * @param config pointer to CAN Module
- * @param can_esr 32 Bi vaiable for error state
- * @return TRUE if CAN IS OK, FALSE IF Error occured
- *
- */
- uint8_t CAN_Get_error_Register(CAN_CONFIG *config,uint32_t* can_esr) {
- volatile struct FLEXCAN_tag *p_CAN = config->CAN_Modul;
- if(p_CAN->ESR.R == 0) {
- return TRUE;
- }
- else {
- *can_esr=p_CAN->ESR.R;
- return FALSE;
- }
- }
- /**
- *@brief Check if CAN Errors occured
- */
- int8_t CAN_Check_error_Register(CAN_CONFIG *config) {
- volatile struct FLEXCAN_tag *p_CAN = config->CAN_Modul;
- if(p_CAN->ESR.R == 0) {
- return CAN_OK;
- }
- else {
- return CAN_ERROR;
- }
- }
|