Hello,
First the back story:
I have a system of four K60 devices which are communicating over the CAN Bus. When the communication is occurring, the device and peripheral is clocked from the FLL driven by the RTC crystal.
From a fresh power up the system has no problems communicating. Every time the system comes up establishes CAN communications and then proceeds to do what it does. Once it starts doing what it does, it no longer talks over CAN for a while and switches it's clock to the PLL Driven by OSC0.
On a command it switches it's clock mode back to RTC driven FLL, and then resumes CAN communications.
The problem:
After a variable number of clock source switches, CAN communications breaks down. There are many form and stuffing errors, as well as BIT1 errors.
I have been having great difficulty in tracking down the source of this issue. I've read vague rumblings about the FLL is not a good source for the CAN bus, but no firm documentation as to why.
Based on AN1798, the system should be able to tolerate at least a 1.4% to 1.5% clock error.
Any advice would be greatly appreciated.
Hi
First of all, sorry for the later reply.
Have you tried to initialize FlexCAN module after each clock source switching? If there still with the stuffing error or Bit1 error?
Wish it helps.
Have a great day,
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Below is the initialization I use:
// start the initialization
Hwi_clearInterrupt(K60CAN_MessageInterruptVectorNumber[obj->DeviceId]);
Hwi_clearInterrupt(K60CAN_BusOffInterruptVectorNumber [obj->DeviceId]);
Hwi_clearInterrupt(K60CAN_ErrorInterruptVectorNumber [obj->DeviceId]);
Hwi_clearInterrupt(K60CAN_TxWarnInterruptVectorNumber [obj->DeviceId]);
Hwi_clearInterrupt(K60CAN_RxWarnInterruptVectorNumber [obj->DeviceId]);
Hwi_clearInterrupt(K60CAN_WakeInterruptVectorNumber [obj->DeviceId]);
// enable the peripheral clock through the system integration module
if (obj->DeviceId == 0)
{
SIM_SCGC6 |= SIM_SCGC6_FLEXCAN0_MASK;
}
else
{
SIM_SCGC3 |= SIM_SCGC3_FLEXCAN1_MASK;
}
// disable the CAN module
//obj->RegPtr->MCR |= CAN_MCR_MDIS_MASK;
// set CAN to use the bus clock
obj->RegPtr->CTRL1 |= CAN_CTRL1_CLKSRC_MASK;
// enable the CAN module
obj->RegPtr->MCR &= ~CAN_MCR_MDIS_MASK;
// wait until out of power power mode
while((obj->RegPtr->MCR & CAN_MCR_LPMACK_MASK) != 0);
// wait until into freeze mode
while((obj->RegPtr->MCR & CAN_MCR_FRZACK_MASK) == 0);
// enable individual Mailbox masks
obj->RegPtr->MCR |= CAN_MCR_IRMQ_MASK;
// disable self reception
obj->RegPtr->MCR |= CAN_MCR_SRXDIS_MASK;
// enable abort
obj->RegPtr->MCR |= CAN_MCR_AEN_MASK;
// enable local priority
obj->RegPtr->MCR |= CAN_MCR_LPRIOEN_MASK;
// get the current clock rate
peripheralClockKHz = Clocking_GetClockkHz(Clocking_BUS_CLK);
// configure the baud rate for the bus
status = K60CAN_SetBaud(obj, peripheralClockKHz * 1000);
// BUS OFF auto recovery ON
obj->RegPtr->CTRL1 &= ~CAN_CTRL1_BOFFREC_MASK;
// Bus Off Interrupt OFF
//obj->RegPtr->CTRL1 &= ~CAN_CTRL1_BOFFMSK_MASK;
// Bus Off Interrupt ON
obj->RegPtr->CTRL1 |= CAN_CTRL1_BOFFMSK_MASK;
// Error Interrupt OFF
//obj->RegPtr->CTRL1 &= ~CAN_CTRL1_ERRMSK_MASK;
// Error Interrupt ON
obj->RegPtr->CTRL1 |= CAN_CTRL1_ERRMSK_MASK;
// TX Warning Interrupt OFF
//obj->RegPtr->CTRL1 &= ~CAN_CTRL1_TWRNMSK_MASK;
// TX Warning Interrupt ON
obj->RegPtr->CTRL1 |= CAN_CTRL1_TWRNMSK_MASK;
// RX Warning Interrupt OFF
//obj->RegPtr->CTRL1 &= ~CAN_CTRL1_RWRNMSK_MASK;
// RX Warning Interrupt ON
obj->RegPtr->CTRL1 |= CAN_CTRL1_RWRNMSK_MASK;
// Wake Interupt OFF
obj->RegPtr->MCR &= ~CAN_MCR_WAKMSK_MASK;
// Wake Interupt ON
//obj->RegPtr->MCR |= CAN_MCR_WAKMSK_MASK;
// take the device out of halt mode
obj->RegPtr->MCR &= ~CAN_MCR_HALT_MASK;
// wait until out of freeze mode
while((obj->RegPtr->MCR & CAN_MCR_FRZACK_MASK) != 0);
// Turn off all interrupts
/// obj->RegPtr->IMASK1 = 0x00000000;
/// obj->RegPtr->IMASK2 = 0x00000000;
// Clear all pending interrupts
/// obj->RegPtr->IFLAG1 = 0x0000FFFF;
/// obj->RegPtr->IFLAG2 = 0x0000FFFF;
Hwi_enableInterrupt(K60CAN_MessageInterruptVectorNumber[obj->DeviceId]);
Hwi_enableInterrupt(K60CAN_BusOffInterruptVectorNumber [obj->DeviceId]);
Hwi_enableInterrupt(K60CAN_ErrorInterruptVectorNumber [obj->DeviceId]);
Hwi_enableInterrupt(K60CAN_TxWarnInterruptVectorNumber [obj->DeviceId]);
Hwi_enableInterrupt(K60CAN_RxWarnInterruptVectorNumber [obj->DeviceId]);
Hi
I got the feedback from Kinetis product team with below comments:
If bus clock is from FLL, the high bit rate may not be achieved due to CAN clock tolerance requirement 1.58%
So, we recommend customer to use the PLL clock as FlexCAN module clock source.
If customer still want to use FLL clock as FlexCAN module clock source, customer need to slow down the CAN bus baud rate.
Before the FlexCAN module software reset, customer can disable the FlexCAN module.
Then, after FlexCAN module software reset, do the full initialization.
Wish it helps.
Have a great day,
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
After looking a bit more, I believe I have arrived at a new theory on what is happening:
Errata: e7993 on the 120MHz K60 device.
Basically, the clock the device is running at is not the correct value.
Hi
Have you tried the e7993 provided workaround way? If that fix the issue?
Wish it helps.
Have a great day,
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
I have implemented the errata workaround, but it ultimately did not help. Eventually after switching enough times the errors crop up again. I even have in my Error ISR to perform a software reset and re-init, but that still won't help it recover.
Except for the initial switch from FEI to FEE, I am switching clock modes between PEE and FEE. So I believe the errata only holds true for the first switch, not all of the subsequent ones where I am always in external clock mode.
Any additional info on the FLL accuracy?
Also any ideas on when I place the CAN peripheral in disable mode and perform a SW reset why it never comes out of SW reset?
Hi
FlexCAN module software reset doesn't work with FlexCAN module disable mode.
So, customer need to enable the FlexCAN module with below code and let module in Freeze mode.
Please refer below code for the detailed info:
SIM_SCGC6 |= SIM_SCGC6_FLEXCAN0_MASK;
CAN0_CTRL1 |= CAN_CTRL1_CLKSRC_MASK;
CAN0_MCR |= CAN_MCR_FRZ_MASK; // enable HALT feature
CAN0_MCR &= ~CAN_MCR_MDIS_MASK; //enable FlexCAN module
while((CAN_MCR_LPMACK_MASK & CAN0_MCR));
// Now can apply Soft Reset
CAN0_MCR |= CAN_MCR_SOFTRST_MASK;
while(CAN_MCR_SOFTRST_MASK & CAN0_MCR);
// Now it should be in Freeze mode
while(!(CAN_MCR_FRZACK_MASK & CAN0_MCR));
About more info of FLL accuracy, I need double check with Kinetis product team.
I will let you know when there with any updated info. Thank you for the patience.
Wish it helps.
Have a great day,
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi
For the K60 datasheet doesn't provide the FLL Max. period jitter data, the Kinetis MCG module is using modified module from MCF51xx MCG module, and I check MCF51CN MCG module FLL Max. Long term Jitter of DCO output clock (averaged over 2ms interval) is 0.2%. I identify Kinetis MCG module with same performance as MCF51XX MCG module.
As the FlexCAN module also mentioned below info:
The oscillator clock should be selected whenever a tight tolerance (up to 0.1%) is required in the CAN bus timing. The oscillator clock has better jitter performance.
I would recommend customer to use PLL generated clock for FlexCAN module instead of using FLL generated clock.
Wish it helps.
Have a great day,
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Given that information I have been attempting to run the device in FBE mode with the external RTC as the input. In this mode the FLEXCAN module appears to get "stuck" in Freeze mode sometimes? It will not transmit or receive.
When I attempt to debug, it functions properly. But if I attach after the target has been running and not acting as it should, I notice that the MCR register has the freeze ack bit set, even though the halt bit is not set.
Any idea how this could happen?
Again, I do not have access to an external clock which can drive the PLL in this hardware.
Hi
The FlexCAN module clock source could from Bus clock or from OSCERCLK.
From your description, the MCG works in FBE mode with external 32KHz crystal clock.
So, I think the FlexCAN module clock is 32KHz clock, right?
And the core and bus clock is also 32KHz, right?
The CANx_MCR[FRZACK] bit will be set with the CANx_MCR[HALT] bit is set.
If it possible, could you attach your tested code here? Thanks.
Have a great day,
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
When a K60 is halted from the debugger, does the CAN peripheral essentially go into freeze mode? Other peripherals explain how they react when the debugger takes control, but the CAN module does not.
Hi
The FlexCAN module has below description about MCR[FRZ_ACK] bit. When debugger halt the MCU, this bit will be set. So, your previous observed this bit is set during debug is normal.
Wish it helps.
Have a great day,
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
I have tried baud rates from 1k to 100k. All with the same results.
In my hardware, when I require the CAN bus to be functional, I only have the internal oscillators (which have a horrible tolerance), and the RTC crystal. I do not have an oscillator available to drive the PLL.
What about the FLL generates such a bad clock tolerance? Given a particular input clock tolerance rating, what is the tolerance output of the FLL?
The FLL period jitter spec is 180ps. In comparison to 24MHz, that is a pretty small fraction.
I will attempt disable, followed by SW reset, then full init.
When I disable the peripheral and then run a SW reset, the code hangs waiting for the reset to complete.
Here is the code snippet:
// command the reset
obj->RegPtr->MCR |= CAN_MCR_SOFTRST_MASK;
// while the reset bit is still high, reset has not yet completed
while((obj->RegPtr->MCR & CAN_MCR_SOFTRST_MASK) != 0); <--- stuck here
After each clock switch I reprogram the required baud and timing registers only. But I do not halt (enter freeze) the peripheral before I switch the clocks.
Are you suggesting that I perform a soft reset on the CAN peripheral and then perform a full re-initialization?
Hi
After the clock switch, I recommend do a FlexCAN module software reset and then with a full re-initialization.
For the FlexCAN software reset doesn't affect CTRL1, CTRL2, RXIMR0–RXIMR63, RXMGMASK, RX14MASK, RX15MASK, RXFGMASK, RXFIR, all Message Buffers. Customer need to make sure previous setting value in those registers be cleared before set a new value.
Wish it helps.
Have a great day,
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
I have tried the following and none of them have removed the problem:
Disable CAN controller before clock switch then Software Reset and Re-Init as if from scratch after clock switch
If an error interrupt occurs, Software Reset and Re-Init as if from scratch
Frame the clock switch with entering freeze mode
Frame the clock switch with disabling the module
I'm running out of ideas.
Again, I also posted my init code, so if there is something wrong there I would appreciate feedback.
Thanks
I have some order of operations questions:
Can I just request a soft reset at any time?
Should I issue a freeze request before a reset?
I want to ensure that other nodes to not get adversely affected when one node resets. As probably part of my issue is that the clock change over on all of the nodes is not 100% synchronous.