cancel
Showing results for 
Search instead for 
Did you mean: 

The CAN example and how to properly make it work

Orbiter
Senior

Question 1: When I make the mcanconf like described in AN the second mcanconf is named exact the same, it does not autoincrement to mcanconf1 as it is in the example. Is that important? Or how/when do I link a certain mcanconf to a subsystem? They must be linked somehow, or? (My mcanconf1 also does not work when I set it up myself, that's why I ask)

 

Question 2: The code looks like this:

returnvalue = can_lld_transmit(&CAND2, CAN_ANY_TXBUFFER, &txf);
osalThreadDelayMilliseconds(1);
 if (returnvalue != CAN_MSG_OK) {
 for (;;) {
 }
 }

So if I have a error on my CAN transmission the program will be endlessly trapped in the for loop?

Isn´t the automatic resending of invalid frames/messages handled by the transceiver? Or does it have to be taken care of here in the sending call? Or is this just an example for loop that should throw an error? -> I thought of handling that one with the error callback. 

 

Question 3: Maybe the answer is already in Q2 but, having a CAN line open or disturbed for some seconds will end the the transmission completely. It will not start again. So I wonder what I am forgetting. My expectation is that the program tries to send CAN endlessly until some other node starts acknowledging and everything's runs normal. But as it comes I would need to rewrite the program in the debugger to get it working again.

THX

1 ACCEPTED SOLUTION

Accepted Solutions
ATROI
ST Employee

Hi Orbiter, 

For what concern to the first question, I suggest you follow the demo in AutoDevKit Studio "SPC58ECxx_RLA CAN Test Application for Discovery" where you can find the example of two different can configurations used for two can bus.

About the second question there are two different scenarios:
- In polling mode, you should handle CAN error as described in your post:
 
returnvalue = can_lld_transmit(&CAND2, CAN_ANY_TXBUFFER, &txf);
osalThreadDelayMilliseconds(1);
 if (returnvalue != CAN_MSG_OK)
 {
            // <---------you should handle the error here.  
 }
  
 - in no polling mode:
 it is necessary to set the 'error callback' in the configurator and implement it in the main.c. 
 See the "SPC58ECxx_RLA CAN Test Application for Discovery" demo.
 
Third question:
In the CCCR control register, the "DAR" bit is in charge of handling the enabling/disabling of automatic retransmission. This bit is set to 0 for default which means that automatic retransmission of unsuccessfully transmitted messages is enabled. (See the Reference Manual RM 0407 of the SPC58 C Line paragraph 47.3.5.2.6 CC Control Register (CCCR))
ATROI_0-1700477484094.png
     ATROI_1-1700477504622.png

Finally, the following image shows that by default, low-level CAN drivers configure the DAR register to 0.

ATROI_2-1700477593775.png

regards,

Alessandro

View solution in original post

4 REPLIES 4
ATROI
ST Employee

Hi Orbiter, 

For what concern to the first question, I suggest you follow the demo in AutoDevKit Studio "SPC58ECxx_RLA CAN Test Application for Discovery" where you can find the example of two different can configurations used for two can bus.

About the second question there are two different scenarios:
- In polling mode, you should handle CAN error as described in your post:
 
returnvalue = can_lld_transmit(&CAND2, CAN_ANY_TXBUFFER, &txf);
osalThreadDelayMilliseconds(1);
 if (returnvalue != CAN_MSG_OK)
 {
            // <---------you should handle the error here.  
 }
  
 - in no polling mode:
 it is necessary to set the 'error callback' in the configurator and implement it in the main.c. 
 See the "SPC58ECxx_RLA CAN Test Application for Discovery" demo.
 
Third question:
In the CCCR control register, the "DAR" bit is in charge of handling the enabling/disabling of automatic retransmission. This bit is set to 0 for default which means that automatic retransmission of unsuccessfully transmitted messages is enabled. (See the Reference Manual RM 0407 of the SPC58 C Line paragraph 47.3.5.2.6 CC Control Register (CCCR))
ATROI_0-1700477484094.png
     ATROI_1-1700477504622.png

Finally, the following image shows that by default, low-level CAN drivers configure the DAR register to 0.

ATROI_2-1700477593775.png

regards,

Alessandro

Hello Alessandro,

thanks for the answer! 

I have follow up questions:

Q1: Yes it works with the example. I try to reproduce the example, so that I am sure I understood whats happening. How can I link a configuration to a mcan subsystem? Or is it always the first one to subsystem 0 and the second to subsystem1? 

Q2: Polling mode? So when I check for the returnvalue, thats called polling mode? And if I set the error callback that would be no-polling mode. So I can choose one, no need to do both? 

Q3: The automatic resending will set the callback, right? So I am just fine handling transmission losses in the error callback function? 

New question: 

I would like to send several frames, is there a recommended way to organize? Like making a CANstruct for every frame I want to send? Or shall I stick to one struct and just change the ID and Payload and iterate through my whole adress list? Maybe it does not matter? 

Hi Michael,
I'll try to answer to your questions:
 
- 1: To link a subsystem to a configuration you have to use the following function:
 
     can_lld_start(&CAND2, &can_config_mcanconf); /*MCAN SUB  0 CAN 1*/
 
 where the CAN2 is the pointer to the CANDriver object while 
 the can_config_mcanconf is the pointer to the configuration object. There is no automatic assignment of the configuration.
 
Of course, if you want to link the configuration can_config_mcanconf to another subsystem, you have to use the same function changing the CAN Driver Object that belongs to the new subsystem. i.e.
   
    can_lld_start(&CAND7, &can_config_mcanconf); /*MCAN SUB 1 CAN 0*/
   
  Now, to know which CAN driver belongs to a subsystem, you have to:
 
  - select the Pin Map editor
  - The outline Tab shows all CANs, and the label highlights the subsystem it belongs to. See image below.
    ATROI_0-1700670649328.png

 

In the image above, CAN 4 Sys 1 was selected by selecting pins 70 and 71.
 This choice, after the code generation, enables the CAN7 pointer in the can_lld.c. file to be used in the can_lld_start(....) command. 
 
question 2: Polling mode is when checking the return value of the function, therefore there is no need to define the error callback. Polling implies poor performance due to continuous MCU involvement. Instead, if you want to handle the error using the interrupt, you have to configure and implement the error callback.   
 
 question 3: yes.
 
 question 4: it is your choice.

Thank you so much, this solved some great mysteries for me. Now my program works, the first "hello world" on CAN sending and receiving, quite robustly (At least I can´t crash it, no matter what I do on my testbench) Nice!