Hardware CAN initialization fails
Posted: Thu Apr 09, 2020 6:01 pm
Hi,
I need the CAN in my project, so I decided to start and use the HAL_CAN layer. So far, it is just quick and dirty.
I have cooperated to the development of the HardwareCAN library that was meant to be included in Roger's package. Now that another direction is taken, I have to move on with different means.
I have read the user manual at the top of the core's source file STM32f1xx_hal_can.c. I tried to implement what they say, and I ended up in the following code. I only give here the Init() function, since execution fails here. The code is :
I did not implement the function HAL_CAN_MspInit() so far. What it is supposed to do is included in the code above. The default weak function HAL_CAN_MspInit() does nothing when called from HAL_CAN_Init(). I have inserted a set of println to see where it fails (I do not have a debugger). The initialization fails in the call of HAL_CAN_Init() which returns with a value HAL_ERROR and the state field of the hCAN variable is 5 = HAL_CAN_STATE_ERROR.
In the HAL_CAN_Init code this means a timeout that happens either if the hardware does not enter the initialization state, or if it does not leave the sleep state.
Could it be a missing clock initialization? According to the manual, it is required to call
and nothing else.
In the previous library that works today with Roger's core, the clock initialization is somewhat complicated and involves more actions, including stopping the USB to leave room to the CAN (on the F1 they cannot be used at the same time).
I tried to find examples of code, but I only found two for the F4, and it is not obvious that they work, since those who published them did so to claim for help...
I need the CAN in my project, so I decided to start and use the HAL_CAN layer. So far, it is just quick and dirty.
I have cooperated to the development of the HardwareCAN library that was meant to be included in Roger's package. Now that another direction is taken, I have to move on with different means.
I have read the user manual at the top of the core's source file STM32f1xx_hal_can.c. I tried to implement what they say, and I ended up in the following code. I only give here the Init() function, since execution fails here. The code is :
Code: Select all
CAN_HandleTypeDef hCAN;
........
void CANSetup(void)
{
hCAN.State = HAL_CAN_STATE_RESET ;
SERIAL.println("Initialisation CAN0") ;
if ( Serial )
Serial.end();
can_rx_head = can_rx_tail = can_rx_lost = 0;
SERIAL.println("Initialisation CAN1") ;
CAN_FilterTypeDef sFilterConfig; //declare CAN filter structure
SERIAL.println("Initialisation CAN2") ;
GPIO_InitTypeDef GPIO_InitStruct;
SERIAL.println("Initialisation CAN3") ;
__HAL_RCC_CAN1_CLK_ENABLE() ;
__HAL_RCC_GPIOB_CLK_ENABLE();
// Configuration des pins PB8 (RX) et PB9 (TX)
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
SERIAL.println("Initialisation CAN4") ;
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
SERIAL.println("Initialisation CAN5") ;
hCAN.Instance = CAN1;
hCAN.Init.Prescaler = 16; // 125 000 b/s
hCAN.Init.Mode = CAN_MODE_NORMAL;
hCAN.Init.SyncJumpWidth = CAN_SJW_4TQ;
hCAN.Init.TimeSeg1 = CAN_BS1_12TQ;
hCAN.Init.TimeSeg2 = CAN_BS2_5TQ;
hCAN.Init.TimeTriggeredMode = DISABLE;
hCAN.Init.AutoBusOff = DISABLE;
hCAN.Init.AutoWakeUp = DISABLE;
hCAN.Init.AutoRetransmission = ENABLE;
hCAN.Init.ReceiveFifoLocked = DISABLE;
hCAN.Init.TransmitFifoPriority = DISABLE;
SERIAL.println("Initialisation CAN6") ;
if (HAL_CAN_Init(&hCAN) != HAL_OK)
{
SERIAL.print("Etat CAN : ") ;
SERIAL.println(hCAN.State) ;
Error( 2 ) ;
}
SERIAL.println("Initialisation CAN7") ;
sFilterConfig.FilterFIFOAssignment=CAN_FILTER_FIFO0; //set fifo assignment
sFilterConfig.FilterIdHigh=0x245<<5; //the ID that the filter looks for (switch this for the other microcontroller)
sFilterConfig.FilterIdLow=0;
sFilterConfig.FilterMaskIdHigh=0;
sFilterConfig.FilterMaskIdLow=0;
sFilterConfig.FilterScale=CAN_FILTERSCALE_32BIT; //set filter scale
sFilterConfig.FilterActivation=ENABLE;
HAL_CAN_ConfigFilter(&hCAN, &sFilterConfig); //configure CAN filter
SERIAL.println("Initialisation CAN8") ;
HAL_CAN_Start(&hCAN); //start CAN
SERIAL.println("Initialisation CAN9") ;
HAL_CAN_ActivateNotification(&hCAN, CAN_IT_RX_FIFO0_MSG_PENDING); //enable interrupts
SERIAL.println("Initialisation CAN10") ;
}
In the HAL_CAN_Init code this means a timeout that happens either if the hardware does not enter the initialization state, or if it does not leave the sleep state.
Could it be a missing clock initialization? According to the manual, it is required to call
Code: Select all
__HAL_RCC_CAN1_CLK_ENABLE() ;
In the previous library that works today with Roger's core, the clock initialization is somewhat complicated and involves more actions, including stopping the USB to leave room to the CAN (on the F1 they cannot be used at the same time).
I tried to find examples of code, but I only found two for the F4, and it is not obvious that they work, since those who published them did so to claim for help...