cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F105 CAN Bus unable to Init and/or Start. INAK bit not cleared. [SOLVED]

jingra
Associate

Hi all,

I'm hoping you're able to help me with a problem I'm having when trying to enable CAN on the STM32F105.

Overview

Bit of an overview first for context.

The idea behind the project is to enable both CAN buses on the MCU so that they're able to transmit and receive packets between each other for a proof of concept.

The development board I'm using has two TJA1050 transceivers on it and exposes both of the CAN-L and CAN-H pins from these transceivers via screw terminal connectors. These also have a set of jumpers that allow the connection or disconnection of a 120ohm resistor on each. I've connected these, effectively terminating the bus at both nodes, and connected CAN-L1 and CAN-L2 together, and CAN-H1 and CAN-H2 together via a twisted pair.

At the moment I'm just trying to get CAN1 up and running.

Issues

  1. Calling HAL_CAN_Init(&hcan1) returns HAL_ERROR when the timeout is not extended for leaving sleep mode, and entering initialisation. If I multiply the CAN_TIMEOUT_VALUE by 100 or step through debug the code, this function then returns HAL_OK.
  2. Calling HAL_CAN_Start(&hcan1) returns HAL_ERROR as the INAK bit is not cleared before the timeout is reached, however extending the CAN_TIMEOUT_VALUE does not affect the outcome as it did with HAL_CAN_Init(&hcan1).

I'm effectively stuck at the HAL_CAN_Start call. My thought's were that the bus is waiting for 11 consecutive recessive bits to have been monitored on CANRX to ensure it's syncronised before entering "normal" mode and so I attempted to pull-up PA11, unfortunately still no difference.

Extra Notes

  • STM32 clock is setup at 72Mhz, with the CAN bus setup at 500kbps.
  • The call to HAL_CAN_ConfigFilter(...) returns HAL_OK given the HAL_CAN_Init(&hcan1) also returns HAL_OK
  • Implementing the same code on an STM32F103 target works perfectly fine, however this is without the transceiver and CAN_RX is pulled up to 3V3.

Code

/* Includes ------------------------------------------------------------------*/
#include "main.h"
 
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */
 
/* Private variables ---------------------------------------------------------*/
CAN_HandleTypeDef hcan1;
 
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_CAN1_Init(void);
 
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
 
int _write(int file, char *ptr, int len) {
  /* Implement your write code here, this is used by puts and printf for example */
  for (int i = 0; i < len; i++)
	ITM_SendChar((*ptr++));
  return len;
}
 
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) {
    CAN_RxHeaderTypeDef rxmsg;
    uint8_t rxData[8];
 
    if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rxmsg, rxData) != HAL_OK) {
        Error_Handler();
    }
}
/* USER CODE END 0 */
 
/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_CAN1_Init();
  /* USER CODE BEGIN 2 */
 
  CAN_TxHeaderTypeDef msg;
 
  msg.StdId = 127; // 11 bit ID
  msg.ExtId = 1; // 29 bit ID
  msg.IDE = CAN_ID_STD; // choose between 11 or 29 bit ID
  msg.RTR = CAN_RTR_DATA; // signifies a data frame
  msg.DLC = 8; // length of message
  msg.TransmitGlobalTime = DISABLE;
 
  uint8_t txData[8];
  uint32_t mb; // this doesn't matter too much
 
  if (HAL_CAN_AddTxMessage(&hcan1, &msg, txData, &mb) != HAL_OK) {
      Error_Handler();
      printf("HAL_CAN_AddTxMessage");
  }
  else
  {
	  printf("HAL_CAN_AddTxMessage success");
  }
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  while (1)
  {
  }
}
 
/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.Prediv1Source = RCC_PREDIV1_SOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  RCC_OscInitStruct.PLL2.PLL2State = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** 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_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure the Systick interrupt time 
  */
  __HAL_RCC_PLLI2S_ENABLE();
}
 
/**
  * @brief CAN1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_CAN1_Init(void)
{
 
  /* USER CODE BEGIN CAN1_Init 0 */
 
  /* USER CODE END CAN1_Init 0 */
 
  /* USER CODE BEGIN CAN1_Init 1 */
 
  /* USER CODE END CAN1_Init 1 */
  hcan1.Instance = CAN1;
  hcan1.Init.Prescaler = 9;
  hcan1.Init.Mode = CAN_MODE_NORMAL;
  hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan1.Init.TimeSeg1 = CAN_BS1_3TQ;
  hcan1.Init.TimeSeg2 = CAN_BS2_4TQ;
  hcan1.Init.TimeTriggeredMode = DISABLE;
  hcan1.Init.AutoBusOff = DISABLE;
  hcan1.Init.AutoWakeUp = DISABLE;
  hcan1.Init.AutoRetransmission = DISABLE;
  hcan1.Init.ReceiveFifoLocked = DISABLE;
  hcan1.Init.TransmitFifoPriority = DISABLE;
  if (HAL_CAN_Init(&hcan1) != HAL_OK)
  {
    Error_Handler();
    printf("HAL_CAN_Init");
  }
  else
  {
	  printf("HAL_CAN_Init success");
  }
  /* USER CODE BEGIN CAN1_Init 2 */
  CAN_FilterTypeDef sf;
  sf.FilterBank = 0;
  sf.FilterMode = CAN_FILTERMODE_IDMASK;
  sf.FilterScale = CAN_FILTERSCALE_16BIT;
  sf.FilterIdLow = 0xffff;
  sf.FilterIdHigh = 0x1fff;
  sf.FilterMaskIdLow = 0x0000;
  sf.FilterMaskIdHigh = 0x0000;
  sf.FilterFIFOAssignment = CAN_RX_FIFO0;
  sf.SlaveStartFilterBank = 0;
  sf.FilterActivation = ENABLE;
  if (HAL_CAN_ConfigFilter(&hcan1, &sf) != HAL_OK) {
      Error_Handler();
      printf("HAL_CAN_ConfigFilter");
  }
  else
  {
	  printf("HAL_CAN_ConfigFilter success");
  }
 
  if (HAL_CAN_Start(&hcan1) != HAL_OK) {
      Error_Handler();
      printf("HAL_CAN_Start");
  }
  else
  {
	  printf("HAL_CAN_Start success");
  }
 
  if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK) {
      Error_Handler();
      printf("HAL_CAN_ActivateNotification");
  }
  else
  {
	  printf("HAL_CAN_ActivateNotification success");
  }
  /* USER CODE END CAN1_Init 2 */
 
}
 
/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
 
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
 
}
 
/* USER CODE BEGIN 4 */
 
/* USER CODE END 4 */
 
/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
	printf("ERROR\n");
  /* USER CODE END Error_Handler_Debug */
}
 
#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{ 
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
 
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

Thanks!

Solution

Turns out the development board that was being used had the CAN1 pins set to PB8 and PB9. Enabling the USB functionality (which will be needed anyway) moved the CAN1 pins from PA11 and PA12 over to the actual pins connected to the transceiver and all works well.

Hopefully this helps someone else in future.

Cheers.

2 REPLIES 2
Amel NASRI
ST Employee

Hi @jingra​ ,

Thanks for the detailed presentation of the issue and its context and especially for the update you provided when the solution was found. Really appreciating this.

You have already identified the root cause of your problem. You find an explanation on this article's content.

-Amel

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Amel NASRI
ST Employee

Hi @jingra​ ,

May I ask you to re-write the solution you found in a new reply to your own initial post ?

I would like to select it as a Best Answer in order to close the discussion and to make your post more helpful for others.

-Amel

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.