// ------------------------------------------------------------- CAN_Frame CAN_K2X::read() { unsigned long int startMillis; CAN_Frame msg; msg.timeout = CAN_TIMEOUT_T3; startMillis = msg.timeout ? millis() : 0; while ( !available() ) { if ( !msg.timeout || (msg.timeout <= (millis() - startMillis)) ) { // early EXIT nothing here msg.valid = false; return msg; } yield(); } // get identifier and dlc msg.length = FLEXCAN_get_length(FLEXCAN0_MBn_CS(rxb)); msg.extended = (FLEXCAN0_MBn_CS(rxb) & FLEXCAN_MB_CS_IDE) ? 1 : 0; msg.id = (FLEXCAN0_MBn_ID(rxb) & FLEXCAN_MB_ID_EXT_MASK); if (!msg.extended) { msg.id >>= FLEXCAN_MB_ID_STD_BIT_NO; }
// ------------------------------------------------------------- void FlexCAN::setMask(const CAN_filter_t &mask) { // enter freeze mode FLEXCAN0_MCR |= (FLEXCAN_MCR_HALT); while(!(FLEXCAN0_MCR & FLEXCAN_MCR_FRZ_ACK)); FLEXCAN0_RXMGMASK = 0; //enable reception of all messages that fit the mask if (mask.ext) { FLEXCAN0_RXFGMASK = ((mask.rtr?1:0) << 31) | ((mask.ext?1:0) << 30) | ((mask.id & FLEXCAN_MB_ID_EXT_MASK) << 1); } else { FLEXCAN0_RXFGMASK = ((mask.rtr?1:0) << 31) | ((mask.ext?1:0) << 30) | (FLEXCAN_MB_ID_IDSTD(mask.id) << 1); } // start the CAN FLEXCAN0_MCR &= ~(FLEXCAN_MCR_HALT); // wait till exit of freeze mode while(FLEXCAN0_MCR & FLEXCAN_MCR_FRZ_ACK); // wait till ready while(FLEXCAN0_MCR & FLEXCAN_MCR_NOT_RDY); //set tx buffers to inactive for (int i = txb; i < txb + txBuffers; i++) { FLEXCAN0_MBn_CS(i) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_INACTIVE); } }
// ------------------------------------------------------------- int FlexCAN::read(CAN_message_t &msg) { unsigned long int startMillis; startMillis = msg.timeout? millis() : 0; while( !available() ) { if ( !msg.timeout || (msg.timeout<=(millis()-startMillis)) ) { // early EXIT nothing here return 0; } yield(); } // get identifier and dlc msg.len = FLEXCAN_get_length(FLEXCAN0_MBn_CS(rxb)); msg.ext = (FLEXCAN0_MBn_CS(rxb) & FLEXCAN_MB_CS_IDE)? 1:0; msg.id = (FLEXCAN0_MBn_ID(rxb) & FLEXCAN_MB_ID_EXT_MASK); if(!msg.ext) { msg.id >>= FLEXCAN_MB_ID_STD_BIT_NO; }
// ------------------------------------------------------------- void CAN_K2X::begin(uint32_t bitrate) { // segment timings from freescale loopback test if ( 250000 == bitrate ) { FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1) | FLEXCAN_CTRL_PSEG1(3) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(15)); } else if ( 500000 == bitrate ) { FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1) | FLEXCAN_CTRL_PSEG1(3) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(7)); } else if ( 1000000 == bitrate ) { FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(3) | FLEXCAN_CTRL_RJW(0) | FLEXCAN_CTRL_PSEG1(0) | FLEXCAN_CTRL_PSEG2(1) | FLEXCAN_CTRL_PRESDIV(5)); } else // 125000 { FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(2) | FLEXCAN_CTRL_PSEG1(3) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(31)); } FLEXCAN0_RXMGMASK = 0; //enable reception of all messages that fit the mask // if (mask.extended) // { // FLEXCAN0_RXFGMASK = ((mask.rtr ? 1 : 0) << 31) | ((mask.extended ? 1 : 0) << 30) | ((mask.id & FLEXCAN_MB_ID_EXT_MASK) << 1); // } // else // { // FLEXCAN0_RXFGMASK = ((mask.rtr ? 1 : 0) << 31) | ((mask.extended ? 1 : 0) << 30) | (FLEXCAN_MB_ID_IDSTD(mask.id) << 1); // } FLEXCAN0_RXFGMASK = 0; // start the CAN FLEXCAN0_MCR &= ~(FLEXCAN_MCR_HALT); // wait till exit of freeze mode while (FLEXCAN0_MCR & FLEXCAN_MCR_FRZ_ACK); // wait till ready while (FLEXCAN0_MCR & FLEXCAN_MCR_NOT_RDY); //set tx buffers to inactive for (int i = txb; i < txb + txBuffers; i++) { FLEXCAN0_MBn_CS(i) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_INACTIVE); } }
// ------------------------------------------------------------- void FlexCAN::begin(uint8_t _baud) { // soft reset can bus reset(); // segment splits and clock divisor based on baud rate switch (_baud){ case (CAN_5KBPS): FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(199)); // 5000 baud Prescaler -> 199 Tq -> 16 break; case (CAN_10KBPS): FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(99)); // 10000 baud Prescaler -> 99 Tq -> 16 break; case (CAN_20KBPS): FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(49)); // 20000 baud Prescaler -> 49 Tq -> 16 break; case (CAN_25KBPS): FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(39)); // 25000 baud Prescaler -> 39 Tq -> 16 break; case (CAN_31K25BPS): FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(31)); // 31250 baud Prescaler -> 31 Tq -> 16 break; case (CAN_33KBPS): FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(29)); // 33333 baud Prescaler -> 29 Tq -> 16 break; case (CAN_40KBPS): FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(24)); // 40000 baud Prescaler -> 24 Tq -> 16 break; case (CAN_50KBPS): FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(19)); // 50000 baud Prescaler -> 19 Tq -> 16 break; case (CAN_80KBPS): FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1) | FLEXCAN_CTRL_PSEG1(3) | FLEXCAN_CTRL_PSEG2(1) | FLEXCAN_CTRL_PRESDIV(19)); // 80000 baud Prescaler -> 19 !!Tq -> 10!! break; case (CAN_83K3BPS): FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(11)); // 83333 baud Prescaler -> 11 Tq -> 16 break; case (CAN_95KBPS): FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(2) | FLEXCAN_CTRL_PSEG1(4) | FLEXCAN_CTRL_PSEG2(2) | FLEXCAN_CTRL_PRESDIV(13)); // 95000 baud Prescaler -> 13 !!Tq -> 12!! break; case (CAN_100KBPS): FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(9)); // 100000 baud Prescaler -> 9 Tq -> 16 break; case (CAN_125KBPS): FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(7)); // 125000 baud Prescaler -> 7 Tq -> 16 break; case (CAN_200KBPS): FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(4)); // 200000 baud Prescaler -> 4 Tq -> 16 break; case (CAN_250KBPS): FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(3)); // 250000 baud Prescaler -> 3 Tq -> 16 break; case (CAN_500KBPS): FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(1)); // 500000 baud Prescaler -> 1 Tq -> 16 break; case (CAN_666KBPS): FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(2) | FLEXCAN_CTRL_PSEG1(4) | FLEXCAN_CTRL_PSEG2(2) | FLEXCAN_CTRL_PRESDIV(1)); // 666666 baud Prescaler -> 1 !!Tq -> 12!! break; case (CAN_1000KBPS): FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(0)); // 100000 baud Prescaler -> 0 Tq -> 16 break; default: // 125000 FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(2) | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(7)); // 125000 baud Prescaler -> 7 Tq -> 16 break; } //enable reception of all messages FLEXCAN0_RXMGMASK = 0; FLEXCAN0_RXFGMASK = ((defaultMask.rtr?1:0) << 31) | ((defaultMask.ext?1:0) << 30) | (FLEXCAN_MB_ID_IDSTD(defaultMask.id) << 1); // start the CAN FLEXCAN0_MCR &= ~(FLEXCAN_MCR_HALT); // wait till exit of freeze mode while(FLEXCAN0_MCR & FLEXCAN_MCR_FRZ_ACK); // wait till ready while(FLEXCAN0_MCR & FLEXCAN_MCR_NOT_RDY); //set tx buffers to inactive for (int i = txb; i < txb + txBuffers; i++) { FLEXCAN0_MBn_CS(i) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_INACTIVE); } }