cancel
Showing results for 
Search instead for 
Did you mean: 

CAN example doesn't work between HAL and SPL.

Madhan
Associate II

I have two STM32 based development boards and would like to get CAN example (slightly modified) to work with a simple data packet of 2 bytes sent from one board to the other. But I detect no valid CAN frame on the bus.

The setup is taken from here: 

STM32F756 NUCLEO as CAN network master using HAL:

Code Source:

https://github.com/STMicroelectronics/STM32CubeF7/tree/master/Projects/STM32756G_EVAL/Examples/CAN/CAN_Networking

STM32F407 as CAN network slave using SPL:

Code from example projects of STSW-STM32065

Transceiver used :  TJA1051

The source code used in projects are attached to this thread.

Please let me know where the issue could be, and it would be a great help.

Thanks in advance.

3 REPLIES 3
Madhan
Associate II

Following is the code source for the above-mentioned issue:

/************************** MASTER CODE ********************/
 
#define CANx                            CAN1
#define CANx_CLK_ENABLE()               __HAL_RCC_CAN1_CLK_ENABLE()
#define CANx_GPIO_CLK_ENABLE()          __HAL_RCC_GPIOD_CLK_ENABLE()
 
#define CANx_FORCE_RESET()              __HAL_RCC_CAN1_FORCE_RESET()
#define CANx_RELEASE_RESET()            __HAL_RCC_CAN1_RELEASE_RESET()
 
/* Definition for CANx Pins */
#define CANx_TX_PIN                    GPIO_PIN_1
#define CANx_TX_GPIO_PORT              GPIOD
#define CANx_TX_AF                     GPIO_AF9_CAN1
#define CANx_RX_PIN                    GPIO_PIN_0
#define CANx_RX_GPIO_PORT              GPIOD
#define CANx_RX_AF                     GPIO_AF9_CAN1
 
/* Definition for CAN's NVIC */
#define CANx_RX_IRQn                   CAN1_RX0_IRQn
#define CANx_RX_IRQHandler             CAN1_RX0_IRQHandler
 
 
static void MPU_Config(void);
void SystemClock_Config(void);
static void Error_Handler(void);
static void CPU_CACHE_Enable(void);
 
static void CAN_Config(void);
 
uint8_t               TxData[8];
uint8_t               RxData[8];
uint32_t              TxMailbox;
 
uint8_t ubKeyNumber = 0x0;
CAN_TxHeaderTypeDef   TxHeader;
CAN_RxHeaderTypeDef   RxHeader;
 
uint8_t count=0;
 
 
CAN_HandleTypeDef     Can1Handle;
 
 
void main(void){
 
  MPU_Config();
 
  CPU_CACHE_Enable();
 
  HAL_Init();
 
  SystemClock_Config();
 
  while (1)
  {
 
        /* Set the data to be transmitted */
        TxData[0] = count++;
        
 
        HAL_StatusTypeDef status;
 
        /* Start the Transmission process */
        status = HAL_CAN_AddTxMessage(&Can1Handle, &TxHeader, TxData, &TxMailbox);
 
        if ( status!= HAL_OK){
        //Debug code
        }
        else if(status ==HAL_OK){
        //Debug code
        }
        HAL_Delay(10);
 
  }
}
 
 
static void CAN_Config(void){
 
  GPIO_InitTypeDef   GPIO_InitStruct;
 
  CANx_CLK_ENABLE();
 
  CANx_GPIO_CLK_ENABLE();
 
  GPIO_InitStruct.Pin = CANx_TX_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Alternate =  CANx_TX_AF;
 
  HAL_GPIO_Init(CANx_TX_GPIO_PORT, &GPIO_InitStruct);
 
  GPIO_InitStruct.Pin = CANx_RX_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Alternate =  CANx_RX_AF;
 
  HAL_GPIO_Init(CANx_RX_GPIO_PORT, &GPIO_InitStruct);
 
/******************* CAN **********************/
 
  CAN_FilterTypeDef  sFilterConfig;
 
 
  Can1Handle.Instance = CANx;
 
  Can1Handle.Init.TimeTriggeredMode = DISABLE;
  Can1Handle.Init.AutoBusOff = DISABLE;
  Can1Handle.Init.AutoWakeUp = DISABLE;
  Can1Handle.Init.AutoRetransmission = ENABLE;
  Can1Handle.Init.ReceiveFifoLocked = DISABLE;
  Can1Handle.Init.TransmitFifoPriority = DISABLE;
  Can1Handle.Init.Mode = CAN_MODE_NORMAL;
  Can1Handle.Init.SyncJumpWidth = CAN_SJW_1TQ;
  Can1Handle.Init.TimeSeg1 = CAN_BS1_6TQ;
  Can1Handle.Init.TimeSeg2 = CAN_BS2_2TQ;
  Can1Handle.Init.Prescaler = 6;
 
  if (HAL_CAN_Init(&Can1Handle) != HAL_OK){
 
    Error_Handler();
  }
 
  sFilterConfig.FilterBank = 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 = CAN_RX_FIFO0;
  sFilterConfig.FilterActivation = ENABLE;
  sFilterConfig.SlaveStartFilterBank = 14;
 
  if (HAL_CAN_ConfigFilter(&Can1Handle, &sFilterConfig) != HAL_OK){
    Error_Handler();
  }
 
  if (HAL_CAN_Start(&Can1Handle) != HAL_OK){
    Error_Handler();
  }
 
 
  if (HAL_CAN_ActivateNotification(&Can1Handle, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK){
    Error_Handler();
  }
 
 
  TxHeader.StdId = 0x321;
  TxHeader.ExtId = 0x01;
  TxHeader.RTR = CAN_RTR_DATA;
  TxHeader.IDE = CAN_ID_STD;
  TxHeader.DLC = 1;
  TxHeader.TransmitGlobalTime = DISABLE;
}
/************* SLAVE CODE ***************/
 
#define CANx                       CAN1
#define CAN_CLK                    RCC_APB1Periph_CAN1
#define CAN_RX_PIN                 GPIO_Pin_0
#define CAN_TX_PIN                 GPIO_Pin_1
#define CAN_GPIO_PORT              GPIOD
#define CAN_GPIO_CLK               RCC_AHB1Periph_GPIOD
#define CAN_AF_PORT                GPIO_AF_CAN1
#define CAN_RX_SOURCE              GPIO_PinSource0
#define CAN_TX_SOURCE              GPIO_PinSource1 
 
CAN_InitTypeDef        CAN_InitStructure;
CAN_FilterInitTypeDef  CAN_FilterInitStructure;
CanTxMsg TxMessage;
CanRxMsg RxMessage;
uint8_t ubKeyNumber = 0x0;
 
static void CAN_Config(void);
 
void main(void){
 
  CAN_Config();
 
  /* Infinite loop */
 
  while (1){
  }
}
 
static void CAN_Config(void){
 
 
  NVIC_InitTypeDef  NVIC_InitStructure;
 
  NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  
  GPIO_InitTypeDef  GPIO_InitStructure;
  
  /* CAN GPIOs configuration **************************************************/
 
  /* Enable GPIO clock */
  RCC_AHB1PeriphClockCmd(CAN_GPIO_CLK, ENABLE);
 
  /* Connect CAN pins to AF9 */
  GPIO_PinAFConfig(CAN_GPIO_PORT, CAN_RX_SOURCE, CAN_AF_PORT);
  GPIO_PinAFConfig(CAN_GPIO_PORT, CAN_TX_SOURCE, CAN_AF_PORT); 
  
  /* Configure CAN RX and TX pins */
  GPIO_InitStructure.GPIO_Pin = CAN_RX_PIN | CAN_TX_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
  GPIO_Init(CAN_GPIO_PORT, &GPIO_InitStructure);
 
  /* CAN configuration ********************************************************/  
  /* Enable CAN clock */
  RCC_APB1PeriphClockCmd(CAN_CLK, ENABLE);
  
  /* CAN register init */
  CAN_DeInit(CANx);
 
  /* CAN cell init */
  CAN_InitStructure.CAN_TTCM = DISABLE;
  CAN_InitStructure.CAN_ABOM = DISABLE;
  CAN_InitStructure.CAN_AWUM = DISABLE;
  CAN_InitStructure.CAN_NART = DISABLE;
  CAN_InitStructure.CAN_RFLM = DISABLE;
  CAN_InitStructure.CAN_TXFP = DISABLE;
  CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
  CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
    
  /* CAN Baudrate = 1 MBps (CAN clocked at 30 MHz) */
  CAN_InitStructure.CAN_BS1 = CAN_BS1_6tq;
  CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq;
  CAN_InitStructure.CAN_Prescaler = 2;
  CAN_Init(CANx, &CAN_InitStructure);
 
  /* CAN filter init */
  CAN_FilterInitStructure.CAN_FilterNumber = 0;
  CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
  CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
  CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
  CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
  CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
  CAN_FilterInit(&CAN_FilterInitStructure);
  
  
  /* Enable FIFO 0 message pending Interrupt */
  CAN_ITConfig(CANx, CAN_IT_FMP0, ENABLE);
}
 
void CAN1_RX0_IRQHandler(void){
  CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
  
  if ((RxMessage.StdId == 0x321)&&(RxMessage.IDE == CAN_ID_STD) && (RxMessage.DLC == 2))
  {
    ubKeyNumber = RxMessage.Data[0];
  }
}

I have tried analyzing the bus using MICROCHIP's CAN ANALYZER tool, but it doesn't see any valid frame. Also the F756's HAL code returns  hcan->ErrorCode:HAL_CAN_ERROR_TIMEOUT and hcan->State: HAL_CAN_STATE_ERROR by the function HAL_CAN_Start(&CanHandle). This occurs only when HAL based CAN code tries communicating with SPL based CAN code.

Get the data rates consistent, ie via APB clock and prescaler and ​then via bit quanta.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Hi Tesla DeLorean,

The time quanta for both the master and slave were wrong in the previous code snippet and are corrected to the following values,

F407 Dicovery Board (SLAVE)

SYS-CLK     : 168MHz

APB1 CLK   : 42MHz

CAN Prescalar : 2

TImeSeg1   : CAN_BS1_15TQ

TImeSeg2   : CAN_BS2_5TQ

SyncJumpWidth : CAN_SJW_1TQ

Sampling Point : 75%

BAUDRATE   : 1MBps 

CALCULATION:

tq = 1/(42MHz/2) = 47.619 nS

tBS1 = 15 x tq = 714.29 nS

tBS1 = 5 x tq = 238.1 nS

NominalBitTime = 1 tq + tBS1 + tBS2 = 1uS

Baudrate = 1/NominalBitTime = 1Mbps

samplingpoint (%) = tBS1/(tBS1 + tBS2)*100

(15/20)*100= 75%

F756 Nucleo Board (MASTER)

SYS-CLK     : 216MHz

APB1 CLK   : 54MHz

CAN Prescalar : 6

TImeSeg1   : CAN_BS1_6TQ

TImeSeg2   : CAN_BS2_2TQ

SyncJumpWidth : CAN_SJW_1TQ

Sampling Point : 75%

BAUDRATE   : 1MBps

CALCULATION:

tq = 1/(54MHz/6) = 111.111 nS

tBS1 = 6 x tq = 666.667 nS

tBS1 = 2 x tq = 222.222 nS

NominalBitTime = 1 tq + tBS1 + tBS2 = 1uS

Baudrate = 1/NominalBitTime = 1Mbps

samplingpoint (%) = tBS1/(tBS1 + tBS2)*100

(6/8)*100= 75% 

Based on the return status from the function HAL_CAN_AddTxMessage(&CanHandle, &TxHeader, TxData, &TxMailbox) (in master code), the status seems to be OK for the first three times (the three mailboxes getting filled) then the status becomes HAL_ERROR.

During the entire operation, no valid or no CAN message frames are seen on the bus.

Please help me out in solving this issue.