Philipp Reist

FlexCAN Wrong Baudrate: Caveat using Default Protocol Timings in FLEXCAN_Init of MCUXpresso SDK 2.2

Discussion created by Philipp Reist on Oct 23, 2017

EDIT: In SDK v2.3.0, this issue has been addressed by including the protocol timing parameters in the flexcan_config_t struct. The time quantum is then calculated in the baud rate setting function. You still have to make sure that the bus clock is an integer multiple of the time quantum * desired baud rate.

 

If the FlexCAN peripheral clock is not an integer multiple * 10 of the desired baud rate, the baud rate will be off using the default settings in the FlexCAN driver of MCUXpresso SDK 2.2. I discovered this debugging FlexCAN on a Kinetis KE1xF512.

 

Here is the relevant code from the driver, the baud rate setting function called at the end of the FLEXCAN_Init function:

static void FLEXCAN_SetBaudRate(CAN_Type *base, uint32_t sourceClock_Hz, uint32_t baudRate_Bps)
{
    flexcan_timing_config_t timingConfig;
    uint32_t priDiv = baudRate_Bps * FLEXCAN_TIME_QUANTA_NUM;

    /* Assertion: Desired baud rate is too high. */
    assert(baudRate_Bps <= 1000000U);
    /* Assertion: Source clock should greater than baud rate * FLEXCAN_TIME_QUANTA_NUM. */
    assert(priDiv <= sourceClock_Hz);

    if (0 == priDiv)
    {
        priDiv = 1;
    }

    priDiv = (sourceClock_Hz / priDiv) - 1;

    /* Desired baud rate is too low. */
    if (priDiv > 0xFF)
    {
        priDiv = 0xFF;
    }

    /* FlexCAN timing setting formula:
     * FLEXCAN_TIME_QUANTA_NUM = 1 + (PSEG1 + 1) + (PSEG2 + 1) + (PROPSEG + 1);
     */

    timingConfig.preDivider = priDiv;
    timingConfig.phaseSeg1 = 5;
    timingConfig.phaseSeg2 = 2;
    timingConfig.propSeg = 1;
    timingConfig.rJumpwidth = 1;

    /* Update actual timing characteristic. */
    FLEXCAN_SetTimingConfig(base, &timingConfig);
}

 

The recommended high speed run clock configuration results in a bus clock of 84MHz. Let the desired baud rate be 1Mbps. The define FLEXCAN_TIME_QUANTA_NUM is 10.

 

Line 4: First the required minimal peripheral clock speed is calculated by the number of time quanta (TQ) per bit multiplied by the bit rate. Given the defined 10 TQ per bit, we obtain 1e6 * 10 = 10MHz as the minimum peripheral clock speed. This is fine given that the actual input speed is 84MHz.

 

Line 16: The minimum peripheral clock speed is equal to the serial clock speed producing the TQ. Here, the issue arises that the integer division here is 84e6/10e6 which floors to 8, resulting in a priDiv value of 7. Then, effectively, the serial clock TQ will be (7 + 1) / 84e6 = 95.2ns instead of 100ns, and the effective bit rate will be 1/(10*TQ) = 1.05Mbps which will not work.

 

In my case, a small adjustment to the driver worked: I set FLEXCAN_TIME_QUANTA_NUM  to 12 and timingConfig.phaseSeg1 to 5 so that the total TQ per bit are 12, and the correct bitrate is achieved.

 

This is a good resource to further study and properly calculating the protocol timing: https://www.nxp.com/docs/en/application-note/AN1798.pdf 

 

Hope this helps someone!

Philipp

Outcomes