RT 1062 CAN clock prescaler

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

RT 1062 CAN clock prescaler

Jump to solution
1,309 Views
jim_verheijde
Contributor II

Hi all,

 

I am currently trying to get the CAN2 controller to work on the RT1062 with a CAN clock speed of 80MHz. However, when connecting the CAN bus to a CAN-USB converter I am getting errors.

jim_verheijde_0-1600429037873.png

 

 

I have a feeling that the prescaler doesn't work. To confirm, is this prescaler (see section 44.7.9.4 Protocol Timing in the IMXRT1060 reference manual) the same as the CAN_CLK_ROOT prescaler CSCMR2[CAN_CLK_PODF] (Figure 14-3. Clock Tree - Part 2 in the IMXRT1060 RM)?

 

Below my code for the clock settings:

 

 

#define FLEXCAN_CLOCK_SOURCE_SELECT (2U)
#define FLEXCAN_CLOCK_SOURCE_DIVIDER (0U)

/* Get frequency of flexcan clock */
#if FLEXCAN_CLOCK_SOURCE_SELECT==(0U)
#define CAN_CLK_FREQ ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / 8U) / (FLEXCAN_CLOCK_SOURCE_DIVIDER + 1U))
#elif FLEXCAN_CLOCK_SOURCE_SELECT==(1U)
#define CAN_CLK_FREQ (CLOCK_GetFreq(kCLOCK_OscClk))
#elif FLEXCAN_CLOCK_SOURCE_SELECT==(2U)
#define CAN_CLK_FREQ ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / 6U) / (FLEXCAN_CLOCK_SOURCE_DIVIDER + 1U))
#else
#error "FLEXCAN_CLOCK_SOURCE_SELECT, should be (0U) for /8 or (2U) for /6, see page 1060 of the RT.1060 reference manual"
#endif

CLOCK_SetMux(kCLOCK_CanMux, FLEXCAN_CLOCK_SOURCE_SELECT);
CLOCK_SetDiv(kCLOCK_CanDiv, FLEXCAN_CLOCK_SOURCE_DIVIDER);

if (FLEXCAN_CalculateImprovedTimingValues(flexcanConfig.baudRate, CAN_CLK_FREQ, &timing_config))
{
	/* Update the improved timing configuration*/
	memcpy(&(flexcanConfig.timingConfig), &timing_config, sizeof(flexcan_timing_config_t));
}

printf("Chosen settings\n");
printf("PROPSEG: %d\n", timing_config.propSeg);
printf("Phase seg 1: %d\n", timing_config.phaseSeg1);
printf("Phase seg 2: %d\n", timing_config.phaseSeg2);
printf("RJW: %d\n", timing_config.rJumpwidth);
printf("preDivider: %d\n", timing_config.preDivider);
printf("CAN clock freq: %d\n", CAN_CLK_FREQ);

 

Output of the above code:

 

Chosen settings
PROPSEG: 7
Phase seg 1: 7
Phase seg 2: 7
RJW: 3
preDivider: 4
CAN clock freq: 80000000

 

As you can see it has a preDivider of 4, which should result in an effective SClock of 20MHz, however I am getting the errors as showed in the screenshot above.

However, when I change the CAN clock settings to 80MHz/4=20MHz:

#define FLEXCAN_CLOCK_SOURCE_SELECT (2U)
#define FLEXCAN_CLOCK_SOURCE_DIVIDER (3U)

Output:

Chosen settings
PROPSEG: 6
Phase seg 1: 7
Phase seg 2: 3
RJW: 3
preDivider: 0
CAN clock freq: 20000000

Now it does work correctly with the CAN-USB controller:

jim_verheijde_0-1600430807296.png

So using a 20MHz CAN_CLK with a preDivider of 0 does work while a 80MHz CAN_CLK with a predivider of 4 which should result in a SClock of 20MHz does not work.

 

So somehow the predivider does not work or am I misunderstanding something about the predivider?

Labels (1)
0 Kudos
1 Solution
1,205 Views
jim_verheijde
Contributor II

After updating to the newest fsl libraries (from SDK 2.8.6) everything worked correctly. So the old libraries probably used faulty bit timing calculations.

View solution in original post

0 Kudos
3 Replies
1,206 Views
jim_verheijde
Contributor II

After updating to the newest fsl libraries (from SDK 2.8.6) everything worked correctly. So the old libraries probably used faulty bit timing calculations.

0 Kudos
1,283 Views
mjbcswitzerland
Specialist V

Hi

1. The maximum CAN_CLK_ROOT frequency is 80MHz in most operating modes but is restricted to 24MHz in low power run and low power idle modes. Therefore make sure that the mode of operation is not causing frequency issues with a higher CAN clock source.

2. The setting for CAN_CTRL1 for 80MHZ CAN clock root and 1MHz CAN bus speed is 0x03a70005
For 20MHz CAN clock root it is 0x13bf0007

Check these with the ones that you calculate to verify that the setting is optimal.

The calculations are made using the uTasker FlexCAN driver's clock calculation code shown below.

Regards

Mark
uTasker project developer for Kinetis and i.MX RT]
Contact me by personal message or on the uTasker web site to discuss professional training or product development requirements

// The best choice of clock input is from the external crystal (lowest jitter), however this may not always enable the best settings to achieve the required speed.
// The choice of clock source is user-defined but this routine tries to achieve best settings using highest time quanta resolution. 
//
// There are up to 25 time quanta in a CAN bit time and the bit frequency is equal to the clock frequency divided by the quanta number (8..25 time quanta range)
// There is always a single time quanta at the start of a bit period called the SYNC_SEG which cannot be changed (transitions are expected to occur on the bus during this period)
// The sampling occurs after time segment 1, which is made up of a propagation segment (1..8 time quanta) plus a phase buffer segment 1 (1..8 time quanta),
// followed by time segment 2, made up of phase buffer segment 2 (2..8 time quanta)
//
// CAN standard compliant bit segment settings give the following ranges (re-synchronisation jump width of 2 is used since it is compliant with all)
// Time segment 1 should be 5..10 when time segment 2 is 2 (min/max time quanta per bit is 8/13)
// Time segment 1 should be 4..11 when time segment 2 is 3 (min/max time quanta per bit is 8/15)
// Time segment 1 should be 5..12 when time segment 2 is 4 (min/max time quanta per bit is 10/17)
// Time segment 1 should be 6..13 when time segment 2 is 5 (min/max time quanta per bit is 12/19)
// Time segment 1 should be 7..14 when time segment 2 is 6 (min/max time quanta per bit is 14/21)
// Time segment 1 should be 8..15 when time segment 2 is 7 (min/max time quanta per bit is 16/23)
// Time segment 1 should be 9..16 when time segment 2 is 8 (min/max time quanta per bit is 18/25)
//
static unsigned long fnOptimalCAN_clock(unsigned short usMode, unsigned long ulSpeed)
{
    unsigned long ulClockSourceFlag = EXTAL_CLK_SOURCE;
    unsigned long ulClockSpeed;
    unsigned long ulLowestError = 0xffffffff;
    unsigned long ulCanSpeed;
    unsigned long ulError;
    unsigned long ulPrescaler;
    int iTimeQuanta = 25;                                                // highest value for highest control resolution
    int iBestTimeQuanta = 25;
    unsigned long ulBestPrescaler = 0;
#if defined ERR050235 && defined CAN_CLK_ROOT_FROM_PLL3_SW_CLK_6
    // When selecting the CCM CAN clock source with CAN_CLK_SEL set to 2, the UART clock gate
    // will not open and CAN_CLK_ROOT will be off. Therefore we workaround this by opening any LPUART clock gate
    //
    POWER_UP_ATOMIC(5, LPUART1_CLOCK);
#endif

    ulClockSpeed = CAN_CLK_ROOT_FREQUENCY;

    while (iTimeQuanta >=  {                                           // test for best time quanta
        ulCanSpeed = (ulClockSpeed/iTimeQuanta);                         // speed without prescaler
        ulPrescaler = ((ulCanSpeed + (ulSpeed/2))/ulSpeed);              // best prescale value
        if (ulPrescaler > 256) {
            ulPrescaler = 256;                                           // maximum possible prescale divider
        }
        else if (ulPrescaler == 0) {
            ulPrescaler = 1;
        }
        ulCanSpeed /= ulPrescaler;
        if (ulCanSpeed >= ulSpeed) {                                     // determine the absolute error value with this quanta setting
            ulError = (ulCanSpeed - ulSpeed);
        }
        else {
            ulError = (ulSpeed - ulCanSpeed);
        }
        if (ulError < ulLowestError) {                                   // if this is an improvement
            ulLowestError = ulError;
            iBestTimeQuanta = iTimeQuanta;                               // best time quanta value
            ulBestPrescaler = ulPrescaler;
        }
        iTimeQuanta--;
    }
    ulBestPrescaler--;                                                   // convert to register setting value
    ulBestPrescaler <<= 24;                                              // move the prescale value into position
    if (iBestTimeQuanta >= 18) {                                         // determine the phase buffer length value
        ulBestPrescaler |= PHASE_BUF_SEG2_LEN8;
        iBestTimeQuanta -= (8 + 1);                                      // remaining time quanta (time segment 1) after removal of the time segment 2 and the SYN_SEG
    }
    else if (iBestTimeQuanta >= 16) {
        ulBestPrescaler |= PHASE_BUF_SEG2_LEN7;
        iBestTimeQuanta -= (7 + 1);
    }
    else if (iBestTimeQuanta >= 14) {
        ulBestPrescaler |= PHASE_BUF_SEG2_LEN6;
        iBestTimeQuanta -= (6 + 1);
    }
    else if (iBestTimeQuanta >= 12) {
        ulBestPrescaler |= PHASE_BUF_SEG2_LEN5;
        iBestTimeQuanta -= (5 + 1);
    }
    else if (iBestTimeQuanta >= 10) {
        ulBestPrescaler |= PHASE_BUF_SEG2_LEN4;
        iBestTimeQuanta -= (4 + 1);
    }
    else {
        ulBestPrescaler |= PHASE_BUF_SEG2_LEN3;
        iBestTimeQuanta -= (3 + 1);
    }
    if ((iBestTimeQuanta & 0x1) != 0) {                                  // odd
        iBestTimeQuanta /= 2;                                            // PROP_SEG and PSEG1 to achieve time segment 1
        ulBestPrescaler |= iBestTimeQuanta;                              // set propogation bit time (1 more than phase buffer segment 1)
        iBestTimeQuanta--;
        ulBestPrescaler |= (iBestTimeQuanta << 19);                      // set phase buffer segment 1
    }
    else {                                                               // even
        iBestTimeQuanta /= 2;                                            // PROP_SEG and PSEG1 to achieve time segment 1 and phase buffer segment 1
        iBestTimeQuanta--;
        ulBestPrescaler |= ((iBestTimeQuanta << 19) | (iBestTimeQuanta));// set equal propogation bit times
    }
    return (RJW_2 | ulClockSourceFlag | ulBestPrescaler);                // initialise the CAN controller with the required speed and parameters
}

 

0 Kudos
1,288 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,

Thank you for your interest in NXP Semiconductor products and for the opportunity to serve you.
Firstly, the above errors are caused by the unmatched rate clock instead of the Serial Clock, the rate clock formula is below.
Next, the number of Time Quanta is the sum of 1 + (PSEG1 + 1) + (PSEG2 + 1) + (PROPSEG + 1).
I think this information can explain your question.
In further, you can learn the information about the protocol timing in the section: 44.7.9.4 Protocol Timing in i.MX RT1060's RM.

Have a great day,

TIC
 
-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
 
- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------
0 Kudos