예제 #1
0
// -------------------------------------------------------------
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);
  }
}
예제 #2
0
// -------------------------------------------------------------
FlexCAN::FlexCAN(uint32_t baud)
{
  // set up the pins, 3=PTA12=CAN0_TX, 4=PTA13=CAN0_RX
  CORE_PIN3_CONFIG = PORT_PCR_MUX(2);
  CORE_PIN4_CONFIG = PORT_PCR_MUX(2);// | PORT_PCR_PE | PORT_PCR_PS;
  // select clock source 16MHz xtal
  OSC0_CR |= OSC_ERCLKEN;
  SIM_SCGC6 |=  SIM_SCGC6_FLEXCAN0;
  FLEXCAN0_CTRL1 &= ~FLEXCAN_CTRL_CLK_SRC;

  // enable CAN
  FLEXCAN0_MCR |=  FLEXCAN_MCR_FRZ;
  FLEXCAN0_MCR &= ~FLEXCAN_MCR_MDIS;
  while(FLEXCAN0_MCR & FLEXCAN_MCR_LPM_ACK)
    ;
  // soft reset
  FLEXCAN0_MCR ^=  FLEXCAN_MCR_SOFT_RST;
  while(FLEXCAN0_MCR & FLEXCAN_MCR_SOFT_RST)
    ;
  // wait for freeze ack
  while(!(FLEXCAN0_MCR & FLEXCAN_MCR_FRZ_ACK))
    ;
  // disable self-reception
  FLEXCAN0_MCR |= FLEXCAN_MCR_SRX_DIS;

  //enable RX FIFO
  FLEXCAN0_MCR |= FLEXCAN_MCR_FEN;

  // segment splits and clock divisor based on baud rate
  if ( 250000 == baud ) {
    FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1)
                      | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(3));
  } else if ( 500000 == baud ) {
    FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1)
                      | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(1));
  } else if ( 1000000 == baud ) {
    FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(0)
                      | FLEXCAN_CTRL_PSEG1(1) | FLEXCAN_CTRL_PSEG2(1) | FLEXCAN_CTRL_PRESDIV(1));
  } else { // 125000
    FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1)
                      | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(7));
  }

  // Default mask is allow everything
  defaultMask.rtr = 0;
  defaultMask.ext = 0;
  defaultMask.id = 0;
}
예제 #3
0
// -------------------------------------------------------------
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);
  } 
}
예제 #4
0
void FlexCAN::begin (uint32_t baud, const CAN_filter_t &mask, uint8_t txAlt, uint8_t rxAlt)
{
    // set up the pins

    if (flexcanBase == FLEXCAN0_BASE) {
        dbg_println ("Begin setup of CAN0");

#if defined(__MK66FX1M0__) || defined(__MK64FX512__)
        //  3=PTA12=CAN0_TX,  4=PTA13=CAN0_RX (default)
        // 29=PTB18=CAN0_TX, 30=PTB19=CAN0_RX (alternative)

        if (txAlt == 1)
            CORE_PIN29_CONFIG = PORT_PCR_MUX(2);
        else
            CORE_PIN3_CONFIG = PORT_PCR_MUX(2);

        // | PORT_PCR_PE | PORT_PCR_PS;

        if (rxAlt == 1)
            CORE_PIN30_CONFIG = PORT_PCR_MUX(2);
        else
            CORE_PIN4_CONFIG = PORT_PCR_MUX(2);
#else
        //  3=PTA12=CAN0_TX,  4=PTA13=CAN0_RX (default)
        // 32=PTB18=CAN0_TX, 25=PTB19=CAN0_RX (alternative)

        if (txAlt == 1)
            CORE_PIN32_CONFIG = PORT_PCR_MUX(2);
        else
            CORE_PIN3_CONFIG = PORT_PCR_MUX(2);

        // | PORT_PCR_PE | PORT_PCR_PS;

        if (rxAlt == 1)
            CORE_PIN25_CONFIG = PORT_PCR_MUX(2);
        else
            CORE_PIN4_CONFIG = PORT_PCR_MUX(2);
#endif
    }
#if defined(INCLUDE_FLEXCAN_CAN1)
    else if (flexcanBase == FLEXCAN1_BASE) {
        dbg_println("Begin setup of CAN1");

        // 33=PTE24=CAN1_TX, 34=PTE25=CAN1_RX (default)
        // NOTE: Alternative CAN1 pins are not broken out on Teensy 3.6

        CORE_PIN33_CONFIG = PORT_PCR_MUX(2);
        CORE_PIN34_CONFIG = PORT_PCR_MUX(2);// | PORT_PCR_PE | PORT_PCR_PS;
    }
#endif

    // select clock source 16MHz xtal

    OSC0_CR |= OSC_ERCLKEN;

    if (flexcanBase == FLEXCAN0_BASE) {
        SIM_SCGC6 |=  SIM_SCGC6_FLEXCAN0;
#if defined(INCLUDE_FLEXCAN_CAN1)
    } else if (flexcanBase == FLEXCAN1_BASE) {
        SIM_SCGC3 |=  SIM_SCGC3_FLEXCAN1;
#endif
    }

    FLEXCANb_CTRL1(flexcanBase) &= ~FLEXCAN_CTRL_CLK_SRC;

    // enable CAN

    FLEXCANb_MCR (flexcanBase) |=  FLEXCAN_MCR_FRZ;
    FLEXCANb_MCR (flexcanBase) &= ~FLEXCAN_MCR_MDIS;

    while (FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_LPM_ACK)
        ;

    // soft reset

    FLEXCANb_MCR (flexcanBase) ^=  FLEXCAN_MCR_SOFT_RST;

    while (FLEXCANb_MCR (flexcanBase) & FLEXCAN_MCR_SOFT_RST)
        ;

    // wait for freeze ack

    while (!(FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_FRZ_ACK))
        ;

    // disable self-reception

    FLEXCANb_MCR (flexcanBase) |= FLEXCAN_MCR_SRX_DIS;

    /*
      now using a system that tries to automatically generate a viable baud setting.
      Bear these things in mind:
      - The master clock is 16Mhz
      - You can freely divide it by anything from 1 to 256
      - There is always a start bit (+1)
      - The rest (prop, seg1, seg2) are specified 1 less than their actual value (aka +1)
      - This gives the low end bit timing as 5 (1 + 1 + 2 + 1) and the high end 25 (1 + 8 + 8 + 8)
      A worked example: 16Mhz clock, divisor = 19+1, bit values add up to 16 = 16Mhz / 20 / 16 = 50k baud
    */

    // have to find a divisor that ends up as close to the target baud as possible while keeping the end result between 5 and 25

    uint32_t divisor = 0;
    uint32_t bestDivisor = 0;
    uint32_t result = 16000000 / baud / (divisor + 1);
    int error = baud - (16000000 / (result * (divisor + 1)));
    int bestError = error;

    while (result > 5) {
        divisor++;
        result = 16000000 / baud / (divisor + 1);

        if (result <= 25) {
            error = baud - (16000000 / (result * (divisor + 1)));

            if (error < 0)
                error *= -1;

            // if this error is better than we've ever seen then use it - it's the best option

            if (error < bestError) {
                bestError = error;
                bestDivisor = divisor;
            }

            // If this is equal to a previously good option then
            // switch to it but only if the bit time result was in the middle of the range
            // this biases the output to use the middle of the range all things being equal
            // Otherwise it might try to use a higher divisor and smaller values for prop, seg1, seg2
            // and that's not necessarily the best idea.

            if ((error == bestError) && (result > 11) && (result < 19)) {
                bestError = error;
                bestDivisor = divisor;
            }
        }
    }

    divisor = bestDivisor;
    result = 16000000 / baud / (divisor + 1);

    if ((result < 5) || (result > 25) || (bestError > 300)) {
        Serial.println ("Abort in CAN begin. Couldn't find a suitable baud config!");
        return;
    }

    result -= 5; // the bitTimingTable is offset by 5 since there was no reason to store bit timings for invalid numbers
    uint8_t propSeg = bitTimingTable[result][0];
    uint8_t pSeg1   = bitTimingTable[result][1];
    uint8_t pSeg2   = bitTimingTable[result][2];

    // baud rate debug information

    dbg_println ("Bit time values:");
    dbg_print ("Prop = ");
    dbg_println (propSeg + 1);
    dbg_print ("Seg1 = ");
    dbg_println (pSeg1 + 1);
    dbg_print ("Seg2 = ");
    dbg_println (pSeg2 + 1);
    dbg_print ("Divisor = ");
    dbg_println (divisor + 1);

    FLEXCANb_CTRL1 (flexcanBase) = (FLEXCAN_CTRL_PROPSEG(propSeg) | FLEXCAN_CTRL_RJW(1) | FLEXCAN_CTRL_ERR_MSK |
                                    FLEXCAN_CTRL_PSEG1(pSeg1) | FLEXCAN_CTRL_PSEG2(pSeg2) | FLEXCAN_CTRL_PRESDIV(divisor));

    // enable per-mailbox filtering

    FLEXCANb_MCR(flexcanBase) |= FLEXCAN_MCR_IRMQ;

    // now have to set mask and filter for all the Rx mailboxes or they won't receive anything by default.

    for (uint8_t c = 0; c < NUM_MAILBOXES - numTxMailboxes; c++) {
        setMask (0, c);
        setFilter (mask, c);
    }

    // start the CAN

    FLEXCANb_MCR(flexcanBase) &= ~(FLEXCAN_MCR_HALT);

    // wait till exit of freeze mode

    while (FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_FRZ_ACK)
        ;

    // wait till ready

    while (FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_NOT_RDY)
        ;

    setNumTxBoxes (2);

#if defined(__MK20DX256__)
    NVIC_SET_PRIORITY (IRQ_CAN_MESSAGE, IRQ_PRIORITY);
    NVIC_ENABLE_IRQ (IRQ_CAN_MESSAGE);
#elif defined(__MK64FX512__)
    NVIC_SET_PRIORITY (IRQ_CAN0_MESSAGE, IRQ_PRIORITY);
    NVIC_ENABLE_IRQ (IRQ_CAN0_MESSAGE);
#elif defined(__MK66FX1M0__)
    if (flexcanBase == FLEXCAN0_BASE) {
        NVIC_SET_PRIORITY (IRQ_CAN0_MESSAGE, IRQ_PRIORITY);
        NVIC_ENABLE_IRQ (IRQ_CAN0_MESSAGE);
    } else {
        NVIC_SET_PRIORITY (IRQ_CAN1_MESSAGE, IRQ_PRIORITY);
        NVIC_ENABLE_IRQ (IRQ_CAN1_MESSAGE);
    }
#endif

    // enable interrupt masks for all 16 mailboxes

    FLEXCANb_IMASK1 (flexcanBase) = 0xFFFF;

    dbg_println ("CAN initialized properly");
}