Hi, all
When I use the flexCAN of K60Dx512, I encounter a problem that make me crazy.
Firstly, I set the flexCAN as global masking
canx->MCR &= ~CAN_MCR_IRMQ_MASK; //global
And then I use two MCU as TX & RX.
The ID is 29bits extension.
In the TX MCU I use one MSG object as TX mode and set the 29bits, 8 bytes;
In another RX MCU I use one MSG object as RX mode and set the same 29bits ID;
When I begin to send message, I can use oscilloscope to get signal from the can bus. But the RX terminal can't receive message which I use interrupt to get message.
I set break point in the Interrupt code in order to use debug to trace it. But it doesn't stop on the break point.
So I change the flexCAN as individual masking.
canx->MCR |= CAN_MCR_IRMQ_MASK; //individual
I also use two MCU testing just like above.
This time the RX terminal can receive message but it can't receive continuously when the TX send continuously.
It seem to lost message and I set the baud as 500kps.
this is Initiate function for flexCAN
void initcan()
{
OSC->CR |= OSC_CR_ERCLKEN_MASK | OSC_CR_EREFSTEN_MASK;
SIM->SCGC6 |= SIM_SCGC6_FLEXCAN0_MASK;
canx->MCR |= CAN_MCR_MDIS_MASK;
canx->CTRL1 |= CAN_CTRL1_CLKSRC_MASK;
canx->MCR |= CAN_MCR_HALT_MASK;
canx->MCR |= CAN_MCR_FRZ_MASK;
canx->MCR &= ~CAN_MCR_MDIS_MASK;
while(!(canx->MCR & CAN_MCR_LPMACK_MASK));
canx->MCR ^= CAN_MCR_SOFTRST_MASK;
while(canx->MCR & CAN_MCR_SOFTRST_MASK);
while(!(canx->MCR & CAN_MCR_FRZACK_MASK));
if(mask_mode == CAN_MSGOBJ_GLOBAL_MASKING)
{
canx->MCR &= ~CAN_MCR_IRMQ_MASK;
}
else
{
canx->MCR |= CAN_MCR_IRMQ_MASK;
}
canx->MCR |= CAN_MCR_SUPV_MASK ;
canx->MCR |= CAN_MCR_SRXDIS_MASK ;
canx->MCR &= ~CAN_MCR_WRNEN_MASK;
canx->MCR &= ~CAN_MCR_RFEN_MASK ;
canx->MCR &= ~CAN_MCR_AEN_MASK;
canx->MCR &= ~CAN_MCR_LPRIOEN_MASK;
canx->CTRL2 |= CAN_CTRL2_EACEN_MASK;
canx->CTRL2 &= ~CAN_CTRL2_RRS_MASK;
canx->CTRL2 |= CAN_CTRL2_MRP_MASK;
//canx->CTRL1 |= CAN_CTRL1_LBUF_MASK;
canx->CTRL1 &= ~CAN_CTRL1_LBUF_MASK;
//canx->CTRL1 |= CAN_CTRL1_LPB_MASK; //loop
canx->CTRL1 &= ~CAN_CTRL1_LPB_MASK;
//set baud
prescale = CAN_GET_PRESCALE(g_bus_clock,baud,20); | |
// | |
canx->CTRL1 |= CAN_CTRL1_RJW(2) | |
| CAN_CTRL1_PROPSEG(6) | |
| CAN_CTRL1_PSEG1(6) | |
| CAN_CTRL1_PSEG2(4) | |
| CAN_CTRL1_PRESDIV(prescale); |
canx->TIMER = 0x0000;
for(i = 0;i < MSG_MAX_NO; i++)
{
canx->MB[i].CS = 0x00000000;
canx->MB[i].ID = 0x00000000;
canx->MB[i].WORD0 = 0x00000000;
canx->MB[i].WORD1 = 0x00000000;
}
canx->IFLAG1 = 0xFFFFFFFF;
canx->IFLAG2 = 0xFFFFFFFF;
canx->IMASK1 = 0x00000000;
canx->IMASK2 = 0x00000000;
for(i = 0;i < MSG_MAX_NO; i++)
{
canx->RXIMR[i] = 0x1FFFFFFF;
}
canx->RXMGMASK = 0x1FFFFFFF;
canx->RX14MASK = 0x1FFFFFFF;
canx->RX15MASK = 0x1FFFFFFF;
canx->MCR &= ~CAN_MCR_FRZ_MASK;
while( canx->MCR & CAN_MCR_FRZACK_MASK);
canx->MCR &= ~(CAN_MCR_HALT_MASK);
while( canx->MCR & CAN_MCR_NOTRDY_MASK);
canx->MCR &= ~CAN_MCR_MDIS_MASK;
}
this my send function
void send(.......)
{
if( CAN_GetMsgCode(canx_ptr,msg_num_temp) != CAN_MSGOBJ_TX_UNCONDITIONAL)
{
//CODE INACTIVE
canx_ptr->MB[msg_num_temp].CS |= CAN_MB_CS_CODE(CAN_MSGOBJ_TX_INACTIVE);
//ID
CAN_SetMsgID(canx_ptr,msg_num_temp,message_id);
//Msg data
CAN_WriteData(canx_ptr,msg_num_temp,in_data_length,in_data_buffer);
//Msg length
CAN_SetMsgLength(canx_ptr,msg_num_temp,in_data_length);
//Msg CODE TX_UNCONDITIONAL wait to send
canx_ptr->MB[msg_num_temp].CS |= CAN_MB_CS_CODE(CAN_MSGOBJ_TX_UNCONDITIONAL);
}}
this my receive funtion
void receive(....)
{
message_code = CAN_GetMsgCode(canx,msg_num);
if ((message_code != CAN_MSGOBJ_RX_BUSY) &&
(message_code != CAN_MSGOBJ_RX_OVERRUN))
{
//ID
msg_id = LPLD_CAN_GetMsgID(canx, msg_num);
//read Msg len
data_length = (uint8_t)LPLD_CAN_GetMsgLength(canx, msg_num);
//read data
CAN_GetData(canx, msg_num,data_length,rx_data);
//get time stamp
time_stamp = LPLD_CAN_GetMsgTimeStamp(canx, msg_num);
for(i = data_length; i < 8; i++)
{
rx_data[i] = 0;
}
//save data to can_rx_msg
can_rx_msg->CAN_MsgID = msg_id;
can_rx_msg->CAN_MsgDataLength = data_length;
can_rx_msg->CAN_MsgTimeStamp = time_stamp;
memcpy(can_rx_msg->CAN_MsgDataBuffer,rx_data,data_length);
//unlock msg
timer = CAN_UnlockMsg(canx);
//
CAN_Interrupt_ClearPending(canx,msg_num);
//write code to empty msg
CAN_SetMsgCode(canx,msg_num,CAN_MSGOBJ_RX_EMPTY);
}
}
thank you
Best Regards
Laplenden
Solved! Go to Solution.
The CANx_CTRL1 register [CLKSRC] bit can only be written in Disable mode as it is blocked by hardware in other modes.
And you will find in <can.c> file line 128 with below code to exit the Disable mode (Exit from this mode is done by negating the MDIS bit in the MCR Register.):
// Enable CAN module
pFlexCANReg->MCR |= FLEXCAN_MCR_FRZ; // enable HALT feature
pFlexCANReg->MCR &= ~FLEXCAN_MCR_MDIS;
So the code in configure bit rate does not modify CANx_CTRL1 register [CLKSRC] bit.
Wish it helps.
Yes, filtering would also prevent a CAN1 RX interrupt, BUT at the 'basic packet receive level' of CAN ALL receivers participate in the ACK/NAK handshake for EVERY message that goes by (unless such nodes are in a 'ListenOnlyMode' like CANx_CTRL1_LOM). Only if 'perfectly received' will the packet be 'further processed'.
The fact that CAN0 TX is 'continuous packets', and CAN0 TX MB is not 'freed', tells me that the pulse you see on CAN1 TX is a NAK, meaning you have NOT gotten 'perfect' bit interchange. One of the RX parameters I have mentioned is NOT correct.
You seem to want a 'one sentence answer', but there ISN'T one -- CAN is VERY complex, and has to work 'near perfect' or it won't work at ALL. Hence the whole apnote AN1798.
Yet you fail to confirm or deny ANY of my assumptions on your 'setup'. Are the Rs and AB pins of your driver chips 'near zero volts'? Is the FlexCAN baud-clock-source a crystal, say 12MHz? You should certainly try a lower baud rate than 1M for these initial experiments -- 125K would give you 'more leeway' on all parameters.
I am trying to walk us thru a diagnostic sequence that will, hopefully, eventually answer the simple question 'why no RX interrupt'...
hi,
Yes i can view the full waveform on both RX pin of transceivers .But receiver interrupt is not occuring in CAN1 even if CAN0 transmitted frame is continously sent on bus lines.Is this 'ACK pulse' on the destination's TX line of CAN1 will be auotmatically generated when it recognise a frame or any CAN settings to be done for having ACK pulse??
regrds
sruthy uk
I am not quite catching the 'drift' of your latest statements. And you didn't mention whether or not you see ANY kind of 'pulse' on CAN1 'TX' at the end of the message, which would tell us if CAN1 sees anything even 'close' to a packet to ACK or NAK. Certainly, all the receive settings need to be fully proper in CAN1 to get the whole message properly received, starting of course with the bit rate (at a speed the transceivers can handle! Can I assume your driver AB and Rs pins are held near 0V?) which MUST be driven from a crystal clock (at both ends!), and more particularly the 'segment' settings of RX that determine the synchronization and sample-point for each bit-time. May I assume you have read AN1798?
TX frames continuously sent is an indication that CAN0 is not seeing an ACK, and automatic retries carry on. You are not going to get any CAN1 RX interrupt until CAN1 'likes' the packet and sends an ACK, at which point the CAN0 TX will cease and the send MB will be freed.
I have seen a pulse on CAN1 TX pin at the end of received message.My doubt is that whether ACK pulse will no be generated when the receive buffer id does not match with the message frame identifier?? If occur so then the RX interrupt is not getting on CAN1 or any error flag is set by the transmit CAN controller.What be the reason for this??
hi,
While i tried to test CAN in loopback mode both the transmit and receive interrupts are generated and routines were executed. But when i tested CAN networks by connecting two CAN nodes interrupt routines are not executing even if the IMASK bit is enabled for message buffer. How can i test the interrupt routines??
with regards,
sruthy uk
I might guess you don't have a 'net 60 ohms' between the CAN differential wires from the transceivers on the two now-interconnected-nodes?
hi,
Yes you r right.i am not using any net 60 ohm across these bus lines.What is the purpose for using it?? i have attached the schematic of transceiver circuit. For testing communication between two CAN nodes i interconnected CANH pins and CANL pins of both transceivers.Also i can view the transmitted signals from CAN0 on Receiver pin of second transceiver in CAN1 for reception.But still CAN1 interrupt is not working.
Best regards,
sruthy uk
In one sense the 'ideal bus' is 120ohms, terminated at both ends with such 120ohms, as a 'true transmission line'. BUT more importantly for CAN, the drivers are 'open collector/emitter' and can only create a + differential voltage in what is called the 'dominant' state, and the RETURN to 'near 0V differential' for the 'recessive state' is supplied ENTIRELY by said resistors. The net resistance MUST be there, although for a 'short collection of wires' (<2m overall for 250Kb/s) it can just be one 50 to 70 ohm resistance 'anywhere'.
hi,
As per your suggestion i terminated the bus ends.Even also the interrupt routine is not executing in CAN network.This interrupt flags is simply set while CAN loopback mode is enabled. What may be the reason for this?? Whether the transmitted message will not store in any of the message buffer except in loopback mode?? i am using the same code of can_loopback code (attached here)for testing CAN network by changing the loopback mode settings and flexcan_read function for CAN1.
Best Regards,
sruthy uk
So I might assume your overall system is using CAN1 on PTC16&17, which may or may not be thru a TWR-SER board (if so, are the jumpers installed to enable?). Have you confirmed that your #defines in InitTarget() make it so? Do the pin-mux options STAY that way thru the rest of the code?
What revs of these TWR cards are you working with? Are there 'other' uses of PTC16&17 'in your way', like NAND flash? It wouldn't hurt to see here a scope-shot of a 'whole message' on CAN_RX1 (PTC16) from BOTH ends of the link.
I might also assume the extra while(1); in CAN_Loopback() is a test?
hi,
Here am using MK60FX512VLQ12 processor in my design board for testing two CAN network.Am not using any external TWR -SER board and all. The schematic of CAN node network is already attached for your ref along with that proper termination is also added to circuit. I just want to know that why interrupt is not generated when the loopback mode disabled?? Also the transmitted message is stored in the FLEXCAN_TX_MB_START (message buffer 7 ), but the flag bit will not set even transmitting message can be viewed in the CAN_TX pin.
best regards,
sruthy uk
To be a 'completed TX mailbox' the message must be 'acknowledged' by another node, which means there must be complete RX, TX at both ends AND proper bit timing (rate with VERY small tolerance and limited jitter allowed, PLUS sample point).
Earlier you mentioned the TWR main board, so I assumed a 'whole tower' as your hardware. In any case, your 'schematic picture' fails to identify what CPU pins you use for this CAN. I will simply assume you have verified that your 'port pin mux' controls ARE correct for your pins, at the time of attempted CAN communication.
Do you see the SAME 'full message waveform' (as you see on that TX pin) on BOTH RX pins at both ends of the link? If the message IS 'accepted' by the destination hardware, you should see an 'ACK pulse' on the destination's TX line right at the 'tail end', or if 'received but with error' a NAK (error flag) pulse instead. If there is NOTHING THERE then your CAN hardware is NOT recognizing a 'frame' at ALL.
Hi,
The FlexCAN module's Loop-Back mode:
The module enters this mode when the LPB field in the Control 1 Register is asserted. In this mode, FlexCAN performs an internal loop back that can be used for self-test operation. The bit stream output of the transmitter is internally fed back to the receiver input. The Rx CAN input pin is ignored and the Tx CAN output goes to
the recessive state (logic '1'). FlexCAN behaves as it normally does when transmitting and treats its own transmitted message as a message received from a remote node. In this mode, FlexCAN ignores the bit sent during the ACK slot in the CAN frame acknowledge field to ensure proper reception of its own message. Both transmit and receive interrupts are generated.
There doesn't need to connect CAN TXD with RXD pin, which is internal loop back .
The reference code, please check my previous thread answer attached K60_100MHz source code, which using the same FlexCAN module with K60_120MHz product.
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
Is there any sample code to refer me for testing two CAN module communication?? Here I have already tested both CAN0 & CAN1 modules in TWR-K60F120M using loopback mode and its working fine.Now i am trying to test communication between these CAN modules like CAN0 used for transmitting data and CAN1 for receiving that data.
with regards
sruthy uk
Hi Laplenden,
I would recommend to refer FlexCAN example of K60 from attached.
Please read below info before start two CAN nodes communications:
This project is a simple can_loopback_node example. It requires at least two CAN nodes:
Node A is running sci2can or any other CAN application with internal loopback disabled;
Node B is running can_loopback_node code.
The example echoes all messages to the remote node (Node A).
The default CAN bit rate is 83.33K.
By default the serial port on the tower serial card is used for
the terminal output. The terminal should be configured for 115200 8-N-1.
Supported platforms:
- TWR_K40X256
- TWR_K60N512
The can_loopback_node.eww file will open the project for all of the supported platforms.
Pick the specific project that corresponds to your hardware.
NOTE: if switching between platforms it is a good idea to do a make clean to make sure the code
is properly configured for the new platform.
Instructions on how to play with sci2can node (Node A):
1) Open sci2can.eww workspace, and change both FLEXCAN_SELF_RECEPTION and FLEXCAN_LOOP_BACK macro values to 0 in can_config.h as below:
#define FLEXCAN_SELF_RECEPTION 0
#define FLEXCAN_LOOP_BACK 0
2) Select "FLASH_256KB_PFLASH_256KB_DFLASH" as the active configuration for the project;
3) Rebuild the whole project;
4) Select "Project->download and debug";
5) Select "Debug->Go" to run the code;
6) Switch off the power to the tower system Node A and disconnect the JTAG connection from the emulator and PC to the Node A;
7) Connect one end of the CAN cable to J7 on TWR-SER module of the Node A tower system ,
the other end to the J7 on another set of TWR-SER module of K40 or K60 tower system (Node B);
8) Connect JTAG connector from the emulator to the tower system Node B and PC;
9) switch on the power to the tower system Node B;
10) open can_loopback_node workspace by double-clicking on can_loopback_node.eww
11) Select "FLASH_256KB_PFLASH_256KB_DFLASH" as the active configuration for the project;
12) Rebuild the whole project and then select "Project->download & debug";
13) Select "Debug->Go" to run the code on the tower system Node B;
14) switch on the power to the tower system Node A to run sci2can demo;
15) follow aforementioned instructions to play with sci2can demo;
Wish it helps.
Hello,Hui_Ma
I test the code KINETIS_SC_100MHz's FlexCAN demo. It's perform great!
I have a question about the code.
Question:
the demo has used bus clock as the source of CAN
pFlexCANReg->CTRL1 |= FLEXCAN_CTRL_CLK_SRC;
However,why dose it use "pFlexCANReg->CTRL1 = 0 | ....." to clear the FLEXCAN_CTRL_CLK_SRC bit?
if(pFlexCANReg->CTRL1 & FLEXCAN_CTRL_CLK_SRC) | |
{ | |
/* | |
** 48M/120= 400k sclock, 12Tq | |
** PROPSEG = 3, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 1 | |
** RJW = 3, PSEG1 = 4, PSEG2 = 4,PRESDIV = 120 | |
*/ | |
pFlexCANReg->CTRL1 = (0 | FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(2) | |
| FLEXCAN_CTRL_PSEG1(3) | FLEXCAN_CTRL_PSEG2(3) | |
| FLEXCAN_CTRL_PRESDIV(119)); | |
} |
Thank you very much
Aaron
Hi friend,
I test the can_loopback_code KINETIS_SC_100MHz's FlexCAN demo.I tried to change the code by writing the CAN first using UART5 and then reading it to check the transmitted character in the consoleflexcan testing in TWR-K60F120M.Here i have used PTA13/12 for FlexCAN0 by connecting TXD and RXD pins in TWR-K60F120M tower module.But the code is not working at all.What may be the reason??
Best Regards,
sruthy uk
Hi,
For the can_loopback_code KINETIS_SC_100MHz's FlexCAN demo is based on Kinetis_100MHz product family, it need to modify related setting, such as MCG setting to make the FlexCAN module works.
Please download the Kinetis 120MHz bare metal sample code from here and use that <make_new_ project> batch to create an platform project to develop related FlexCAN application.
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,
i tested can loopback mode and its working fine.how can i test can communication between two can nodes in two different tower board???
with regards,
sruthy uk
Hi,
Whether i can do the flexcan testing in the KDS project itself??What modifications had to be done in the can_loopback_code KINETIS_SC_100MHz's
FlexCAN demo to test the CAN??Is there MCG settings provided in any of the code files in can_loopback project??
Best Regards,
sruthy uk