Skip to main content
n.serina
Associate III
May 8, 2018
Solved

HAL_CAN_Init() is failing

  • May 8, 2018
  • 12 replies
  • 8743 views
Posted on May 08, 2018 at 14:00

Hi, 

I was just started with CAN peripheral on my stm32f446re nucleo board. 

The problem i am facing is HAL_CAN_Init()  added by cubeMx code generation software is failing at the below line of code 

it is returning HAL_ERROR in CAN1 LOOP BACK MODE

That means the controller has not set SLAK to zero even if we clear the SLEEP bit 

i believe that CAN TX is internally connected to can rx and can rx is not sampled . 

on the board i have made no connection to the can tx and can rx. its just a single board. 

Please let me know what i am doing wrong . 

/* Exit from sleep mode */

CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_SLEEP);

/* Get tick */

tickstart = HAL_GetTick();

/* Check Sleep mode leave acknowledge */

while ((hcan->Instance->MSR & CAN_MSR_SLAK) != RESET)

{

if ((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE)

{

/* Update error code */

hcan->ErrorCode |= HAL_CAN_ERROR_TIMEOUT;

/* Change CAN state */

hcan->State = HAL_CAN_STATE_ERROR;

return HAL_ERROR;

}

here is picture of all reg contents 

0690X0000060B1YQAU.png

#stm32f4-nucleo #smt32f407-can-bus #stm32f4
This topic has been closed for replies.
Best answer by T J

any value except <2V on the pin ...

100K would probably work, just...

12 replies

n.serina
n.serinaAuthor
Associate III
May 9, 2018
Posted on May 09, 2018 at 12:29

Turvey.Clive.002

Waclawek.Jan

Could you please help ?

T J
Senior III
May 9, 2018
Posted on May 09, 2018 at 12:59

You must be running without a transceiver chip.

so therefore you need a pullup on the CAN Rx pin.       <- your fix

Also,

make sure ABOM is enabled.

no two cards are allowed to transmit the same MsgID.

n.serina
n.serinaAuthor
Associate III
May 9, 2018
Posted on May 09, 2018 at 13:40

 ,

 ,

Hello T J , ,

Thanks for replying . yes after pulling up rx line with 3.3k resistor the above problem got resolved. ,

But still i am not able to rcv the same packet sent in loop back mode. ,

The RX is not getting any packets . ,

basically in the code ,

/* ♯ ♯ -5- Start the Reception process ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ */

 ,

if(HAL_CAN_GetRxFifoFillLevel(&,hcan1, CAN_RX_FIFO0) != 1)

 ,

{

 ,

/* Reception Missing */

 ,

Error_Handler(),

 ,

}

it is going in to error_handler . ,

i am taking ref code from here ,

STM32Cube_FW_F4_V1.21.0\Projects\STM32469I_EVAL\Examples\CAN\CAN_Loopback\Src

T J
Senior III
May 9, 2018
Posted on May 09, 2018 at 13:53

I use the interrupts for Receive but not transmit.

 __HAL_CAN_ENABLE_IT(&hcan, CAN_IT_FMP1);
 __HAL_CAN_ENABLE_IT(&hcan, CAN_IT_FMP0);
 
void CEC_CAN_IRQHandler(void) {
 /* USER CODE BEGIN CEC_CAN_IRQn 0 */
 CAN_IRQFlag = true;
 checkCanRxFifos();
 /* USER CODE END CEC_CAN_IRQn 0 */
 HAL_CAN_IRQHandler(&hcan);
 /* USER CODE BEGIN CEC_CAN_IRQn 1 */
 /* USER CODE END CEC_CAN_IRQn 1 */
}

void checkCanRxFifos(void) {
 int readCanBytecount;
 char canFifo1FullFlag = CAN->RF1R & CAN_RF1R_FMP1;
 if (canFifo1FullFlag) {
 {
 readCanBytecount = (CAN->sFIFOMailBox[1].RDTR & 0x0f); 
 canRxMsgBottomWord[canRxMsgIN] = CAN->sFIFOMailBox[1].RDLR;
 canRxMsgTopWord[canRxMsgIN] = CAN->sFIFOMailBox[1].RDHR;

 canRxMsgID[canRxMsgIN] = CAN->sFIFOMailBox[1].RIR >> 21;
 CAN->RF1R |= CAN_RF1R_RFOM1; // release FIFO

 canRxMsgLength[canRxMsgIN] = readCanBytecount; 

 canRxMsgIN++;
 canRxMsgIN &= 0x3F; // 64 entries only
 canRxMsgTableEMPTY = false;
 if (canRxMsgIN == canRxMsgOUT) canRxMsgTableFULL = true;
 }
 CAN->IER |= CAN_IER_FMPIE1; // (11) Set FIFO1 message pending IT enable
 }
 
 char canFifo0FullFlag = CAN->RF0R & CAN_RF0R_FMP0;
 if (canFifo0FullFlag) {
 {
 readCanBytecount = (CAN->sFIFOMailBox[0].RDTR & 0x0f); 

 canRxMsgBottomWord[canRxMsgIN] = CAN->sFIFOMailBox[0].RDLR;
 canRxMsgTopWord[canRxMsgIN] = CAN->sFIFOMailBox[0].RDHR;

 uint32_t canRxmsgID = CAN->sFIFOMailBox[0].RIR >> 21;
 CAN->RF0R |= CAN_RF0R_RFOM0; // release FIFO

 if(canRxMsgTableFULL) { 
 canRxMsgTableOverflow = true; // now dump new frame...
 }else {
 canRxMsgID[canRxMsgIN] = canRxmsgID;
 canRxMsgLength[canRxMsgIN] = readCanBytecount; 
 canRxMsgIN++;
 canRxMsgIN &= 0x3F; // 64 entries only
 canRxMsgTableEMPTY = false;
 if (canRxMsgIN == canRxMsgOUT)
 canRxMsgTableFULL = true;
 }
 
 //length = sprintf(string + length,'%08X, %08X :W',canFifoBuf.d32[0],canFifoBuf.d32[1]);
 // for( int i = 0; i < readCanBytecount; i++){ 
 // canRxBuffer[canRxpointerIN++] = canFifoBuf.d8[i]; 
 // canRxpointerIN &= 0xFF;
 // if (canRxpointerIN == canRxpointerOUT ) CanRxbufferOverrun = true;
 // //length += sprintf(string + length,'%02X, ',canFifoBuf.d8[i]);
 // }
 //sprintf(string + length -2,'

'); // remove 2 bytes, the last comma and space
 
 }
 CAN->IER |= CAN_IER_FMPIE0; // (11) Set FIFO0 message pending IT enable
 }
 // if (length >0) puts(string);

}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

AMerz
Visitor II
August 28, 2018

Greetings.

I am having the same issue. As i understand it -- pull-up resistor is when you connect CAN Rx to 3.3V or 5V on your STM board through a resistor. I wonder why did you use exactly 3.3k resistor and not 5k Ohm or something. And I would like to know to what voltage should the Rx pin been pulled-up -- 3.3V or 5V exactly, my STM board has both of them.

Thank you for your answers.

RN_it
Associate III
August 28, 2018

if you are not using transceiver chip and wan to test CAN loopback mode, pullup can_rx to 3.3v via resistor. otherwise can_init() will fail .

AMerz
Visitor II
August 28, 2018

Thank you. Do I have to use 3.3kOhm resistor, or some other value may suffice?

T J
T JBest answer
Senior III
August 28, 2018

any value except <2V on the pin ...

100K would probably work, just...

AMerz
Visitor II
August 28, 2018

Thank you, I think I'll use 10k as I have it handy.

GS1
Senior III
January 24, 2020

Hi all,

Even though this thread is already a year old, the following solution might be helpful for others:

I had the same issue in my new project and found out, that the timeout error can be fixed by simply setting the wait time to

5 * CAN_TIMEOUT_VALUE:

in HAL_CAN_Init:

...

 /* Exit from sleep mode */

 CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_SLEEP);

 /* Get tick */

 tickstart = HAL_GetTick();

 /* Check Sleep mode leave acknowledge */

 while ((hcan->Instance->MSR & CAN_MSR_SLAK) != 0U)

 {

   if ((HAL_GetTick() - tickstart) > 5*CAN_TIMEOUT_VALUE)

   {

     /* Update error code */

     hcan->ErrorCode |= HAL_CAN_ERROR_TIMEOUT;

     /* Change CAN state */

     hcan->State = HAL_CAN_STATE_ERROR;

     return HAL_ERROR;

   }

 }

Then the timeout is not happening.

JoniS
Senior
January 24, 2020

Maybe a better solution would be to just change the value "CAN_TIMEOUT_VALUE" to be higher.

Adding magic numbers in the code is never great idea.​

GS1
Senior III
January 24, 2020

You are right and you are free to do so!

My answer was simply to show, where the problem is located and to supply a working solution.

CAN_TIMEOUT_VALUE however is used in more other places and I did not want to change the other behaviours. Then please declare a second value for the special timeout location and place that in place.