Author Topic: CAN Initialization Timeout Error in STM32F4  (Read 1895 times)

0 Members and 1 Guest are viewing this topic.

Offline vamoiridTopic starter

  • Newbie
  • Posts: 1
  • Country: gr
CAN Initialization Timeout Error in STM32F4
« on: January 30, 2018, 03:00:36 pm »
I am using an STM32F446ZET6U Nucleo Board (programmed with CubeMx and Keil uVision 5) and I try to use some of the ST's examples in order to learn about its peripherals. I am stuck with the CAN peripheral. The problem is that when the code enters the

Code: [Select]
HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef* hcan)
it returns a HAL_TIMEOUT so the CAN can't be initialized. I want to use CAN in the LOOPBACK mode (without an external transceiver connected) in order to test the functions. As I traced the bug of the program with the KEIL Debugger the code seems to be stuck in the

Code: [Select]
/* Wait the acknowledge */
while((hcan->Instance->MSR & CAN_MSR_INAK) == CAN_MSR_INAK)
{
 if((HAL_GetTick() - tickstart ) > CAN_TIMEOUT_VALUE)
  {
    hcan->State= HAL_CAN_STATE_TIMEOUT;
    /* Process unlocked */
    __HAL_UNLOCK(hcan);
    return HAL_TIMEOUT;
  }
}

Which is in the stm32f4xx_hal_can.c file.

So I searched the datasheet and I found this

Quote
30.4.1 Initialization mode The software initialization can be done while the hardware is in Initialization mode. To enter this mode the software sets the INRQ bit in the CAN_MCR register and waits until the hardware has confirmed the request by setting the INAK bit in the CAN_MSR register. To leave Initialization mode, the software clears the INQR bit. bxCAN has left Initialization mode once the INAK bit has been cleared by hardware.

and also because it is the 0 bit of the CAN_MSR register it also states

Quote
Bit 0 INRQ: Initialization request The software clears this bit to switch the hardware into normal mode. Once 11 consecutive recessive bits have been monitored on the Rx signal the CAN hardware is synchronized and ready for transmission and reception. Hardware signals this event by clearing the INAK bit in the CAN_MSR register. Software sets this bit to request the CAN hardware to enter initialization mode. Once the software has set the INRQ bit, the CAN hardware waits until the current CAN activity (transmission or reception) is completed before entering the initialization mode. Hardware signals this event by setting the INAK bit in the CAN_MSR register.

So after this, I can understand that the problem is that the CAN_RX doesn't receive the 11 recessive bits so the Hardware does not clear the INAK Bit in the CAN_MSR Register so the CAN cannot be initialized. I feel that the problem might be the fact that I don't use a transceiver so somehow the CAN_RX can't receive the 11 recessive bits that it needs but if it is not this then I don't know how to fix it. (I have already ordered some transceivers and I am going to test it when they arrive.)This is also the code implementation:

The clock is set to the internal HSI at 16 MHz and APB1 Prescaler to 1 so the CAN gets 16MHz clock.

Code: [Select]
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

    /**Configure the main internal regulator output voltage
    */
  __HAL_RCC_PWR_CLK_ENABLE();

  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);

    /**Initializes the CPU, AHB and APB busses clocks
    */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = 16;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Initializes the CPU, AHB and APB busses clocks
    */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Configure the Systick interrupt time
    */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick
    */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

Here is the CAN Initialization Procedure. With 16MHz clock and a prescaler of 2 then the SJW = 1, BS1 = 11, BS2 = 4 gives you a baudrate of 500kbps with the sample point in 75%.

Code: [Select]
static void MX_CAN1_Init(void)
{
    CAN_FilterConfTypeDef  sFilterConfig;
  static CanTxMsgTypeDef        TxMessage;
  static CanRxMsgTypeDef        RxMessage;

  hcan1.Instance = CAN1;
    hcan1.pTxMsg = &TxMessage;
  hcan1.pRxMsg = &RxMessage;

  hcan1.Init.Prescaler = 2;
  hcan1.Init.Mode = CAN_MODE_LOOPBACK;
  hcan1.Init.SJW = CAN_SJW_1TQ;
  hcan1.Init.BS1 = CAN_BS1_11TQ;
  hcan1.Init.BS2 = CAN_BS2_4TQ;
  hcan1.Init.TTCM = DISABLE;
  hcan1.Init.ABOM = DISABLE;
  hcan1.Init.AWUM = DISABLE;
  hcan1.Init.NART = DISABLE;
  hcan1.Init.RFLM = DISABLE;
  hcan1.Init.TXFP = DISABLE;
  if (HAL_CAN_Init(&hcan1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

     /*##-2- Configure the CAN Filter ###########################################*/
  sFilterConfig.FilterNumber = 0;
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
  sFilterConfig.FilterIdHigh = 0x0000;
  sFilterConfig.FilterIdLow = 0x0000;
  sFilterConfig.FilterMaskIdHigh = 0x0000;
  sFilterConfig.FilterMaskIdLow = 0x0000;
  sFilterConfig.FilterFIFOAssignment = 0;
  sFilterConfig.FilterActivation = ENABLE;
  sFilterConfig.BankNumber = 14;

  if(HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
  {
    /* Filter configuration Error */
    Error_Handler();
  }

}

So, can the problem be the fact that I don't have an external transceiver or is it something else?
 

Offline vaualbus

  • Frequent Contributor
  • **
  • Posts: 352
  • Country: it
Re: CAN Initialization Timeout Error in STM32F4
« Reply #1 on: February 07, 2018, 04:03:58 pm »
I think so. I basicly have the same problem write some CAN code but don't have the can transciver on board (I'm using a stm32f769 disco board) and the init fail.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf