-
Notifications
You must be signed in to change notification settings - Fork 1k
Description
So, while testing the CANFD interfaces of STM32G0B1CB and CC on this core i found a rather strange bug, i am not sure what cause this : When initializing the CANFD interfaces, 2 interfaces in the case of this variant, for some reason the HAL_FDCAN_MspInit function is only called for the first instance, but it should be called for each instance, otherwise the GPIOs are not initialized correctly (at the very least), the second instance won't work at all.
Below is my test code, which simply set the two CANFD ports up for a local test, port 1 to port 2 and port2 to port1 etc. As you can see, in HAL_FDCAN_MspInit i had to disable the condition on the CANFD2 init so that it is executed at the first call (when CANFD1 is initialized) because HAL_FDCAN_MspInit will never be called again when CANFD2 is initialized, despite HAL_FDCAN_Start(phfdcan2) is correctly called in my code.
As a side note, could you please clarify what is the best practice to override the default clock init from the sketch because i noticed the default clock init from variants sets the system clock to 48M from the HSI, not optimal when we have an HSE and want to run at max speed (64M for the G0B1).
Thanks.
#include <Arduino.h>
#include "stm32g0xx_hal.h"
#include "stm32g0xx_hal_fdcan.h"
#define CAN1_VCC PB10
#define CAN1_TX PA12
#define CAN1_RX PA11
#define CAN1_MODE PC7
#define CAN2_VCC PB12
#define CAN2_TX PB1
#define CAN2_RX PB0
#define CAN2_MODE PB15
#define RX5 PD2 // DBG RX
#define TX5 PD3 // DBG TX
#define LED1 PA6 // LED blue
#define LED2 PA7 // LED purple
FDCAN_HandleTypeDef *phfdcan1;
FDCAN_HandleTypeDef *phfdcan2;
FDCAN_TxHeaderTypeDef TxHeader;
FDCAN_RxHeaderTypeDef RxHeader;
uint8_t TxData[8];
uint8_t RxData[8];
static uint32_t HAL_RCC_FDCAN_CLK_ENABLED=0;
// void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) {
// if ((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET) {
// // Retrieve Rx messages from RX FIFO0
// if (HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader, RxData) == HAL_OK) {
// Serial.print("Received message ID: ");
// Serial.println(RxHeader.Identifier, HEX);
// Serial.print("Data: ");
// printHexData(RxData, RxHeader.DataLength);
// } else {
// error_handler_();
// }
// }
// }
void error_handler_(void) {
Serial.println("Error");
}
void fdcan1Init() {
phfdcan1 = new FDCAN_HandleTypeDef;
Serial.println("FDCAN1 init");
digitalWrite(CAN1_MODE, LOW);
phfdcan1->Instance = FDCAN1;
phfdcan1->Init.ClockDivider = FDCAN_CLOCK_DIV1;
phfdcan1->Init.FrameFormat = FDCAN_FRAME_FD_BRS;
phfdcan1->Init.Mode = FDCAN_MODE_NORMAL;
phfdcan1->Init.AutoRetransmission = ENABLE;
phfdcan1->Init.TransmitPause = ENABLE;
phfdcan1->Init.ProtocolException = DISABLE;
phfdcan1->Init.NominalPrescaler = 1;
phfdcan1->Init.NominalSyncJumpWidth = 16;
phfdcan1->Init.NominalTimeSeg1 = 63;
phfdcan1->Init.NominalTimeSeg2 = 16;
phfdcan1->Init.DataPrescaler = 1;
phfdcan1->Init.DataSyncJumpWidth = 4;
phfdcan1->Init.DataTimeSeg1 = 5;
phfdcan1->Init.DataTimeSeg2 = 4;
phfdcan1->Init.StdFiltersNbr = 0;
phfdcan1->Init.ExtFiltersNbr = 0;
phfdcan1->Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
if (HAL_FDCAN_Init(phfdcan1) != HAL_OK) {
error_handler_();
}
FDCAN_FilterTypeDef sFilterConfig;
sFilterConfig.IdType = FDCAN_STANDARD_ID;
sFilterConfig.FilterIndex = 0;
sFilterConfig.FilterType = FDCAN_FILTER_MASK;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
sFilterConfig.FilterID1 = 0x000;
sFilterConfig.FilterID2 = 0x000;
// sFilterConfig.IdType = FDCAN_STANDARD_ID;
// sFilterConfig.FilterIndex = 0;
// sFilterConfig.FilterType = FDCAN_FILTER_MASK;
// sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
// sFilterConfig.FilterID1 = 0x321;
// sFilterConfig.FilterID2 = 0x7FF;
// if (HAL_FDCAN_ConfigFilter(phfdcan1, &sFilterConfig) != HAL_OK) {
// error_handler_();
// }
// if (HAL_FDCAN_ConfigGlobalFilter(phfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK)
// {
// Error_Handler();
// }
if (HAL_FDCAN_Start(phfdcan1) != HAL_OK) {
error_handler_();
}
if (HAL_FDCAN_ActivateNotification(phfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK) {
error_handler_();
}
}
void fdcan2Init() {
digitalWrite(CAN2_MODE, LOW);
Serial.println("FDCAN2 init");
phfdcan2 = new FDCAN_HandleTypeDef;
// phfdcan2->Instance = FDCAN2;
// phfdcan2->Init.FrameFormat = FDCAN_FRAME_FD_NO_BRS;
// phfdcan2->Init.Mode = FDCAN_MODE_NORMAL;
// phfdcan2->Init.AutoRetransmission = DISABLE;
// phfdcan2->Init.TransmitPause = DISABLE;
// phfdcan2->Init.ProtocolException = DISABLE;
// phfdcan2->Init.NominalPrescaler = 8;
// phfdcan2->Init.NominalSyncJumpWidth = 4;
// phfdcan2->Init.NominalTimeSeg1 = 11;
// phfdcan2->Init.NominalTimeSeg2 = 4;
// phfdcan2->Init.DataPrescaler = 2;
// phfdcan2->Init.DataSyncJumpWidth = 1;
// phfdcan2->Init.DataTimeSeg1 = 15;
// phfdcan2->Init.DataTimeSeg2 = 4;
phfdcan2->Instance = FDCAN2;
phfdcan2->Init.ClockDivider = FDCAN_CLOCK_DIV1;
phfdcan2->Init.FrameFormat = FDCAN_FRAME_FD_BRS;
phfdcan2->Init.Mode = FDCAN_MODE_NORMAL;
phfdcan2->Init.AutoRetransmission = ENABLE;
phfdcan2->Init.TransmitPause = ENABLE;
phfdcan2->Init.ProtocolException = DISABLE;
phfdcan2->Init.NominalPrescaler = 1;
phfdcan2->Init.NominalSyncJumpWidth = 16;
phfdcan2->Init.NominalTimeSeg1 = 63;
phfdcan2->Init.NominalTimeSeg2 = 16;
phfdcan2->Init.DataPrescaler = 1;
phfdcan2->Init.DataSyncJumpWidth = 4;
phfdcan2->Init.DataTimeSeg1 = 5;
phfdcan2->Init.DataTimeSeg2 = 4;
phfdcan2->Init.StdFiltersNbr = 0;
phfdcan2->Init.ExtFiltersNbr = 0;
phfdcan2->Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
if (HAL_FDCAN_Init(phfdcan2) != HAL_OK) {
error_handler_();
}
FDCAN_FilterTypeDef sFilterConfig;
sFilterConfig.IdType = FDCAN_STANDARD_ID;
sFilterConfig.FilterIndex = 0;
sFilterConfig.FilterType = FDCAN_FILTER_MASK;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
sFilterConfig.FilterID1 = 0x000;
sFilterConfig.FilterID2 = 0x000;
// sFilterConfig.IdType = FDCAN_STANDARD_ID;
// sFilterConfig.FilterIndex = 0;
// sFilterConfig.FilterType = FDCAN_FILTER_MASK;
// sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
// sFilterConfig.FilterID1 = 0x321;
// sFilterConfig.FilterID2 = 0x7FF;
// if (HAL_FDCAN_ConfigFilter(phfdcan2, &sFilterConfig) != HAL_OK) {
// error_handler_();
// }
// if (HAL_FDCAN_ConfigGlobalFilter(phfdcan2, FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK)
// {
// Error_Handler();
// }
if (HAL_FDCAN_Start(phfdcan2) != HAL_OK) {
error_handler_();
}
}
void checkCANErrors(FDCAN_HandleTypeDef* phfdcan) {
FDCAN_ProtocolStatusTypeDef protocolStatus;
HAL_FDCAN_GetProtocolStatus(phfdcan, &protocolStatus);
Serial.print("Code: ");
Serial.print(protocolStatus.LastErrorCode); // Last Error Code (LEC)
Serial.print(" Protocol: ");
if (protocolStatus.ErrorPassive) {
Serial.print("Error Passive");
} else {
Serial.print("Error Active");
}
Serial.print(" Bus Off: ");
if (protocolStatus.BusOff) {
Serial.print("Yes");
} else {
Serial.print("No");
}
Serial.print(" Warning Status: ");
if (protocolStatus.Warning) {
Serial.println("Warning");
} else {
Serial.println("Normal");
}
}
void printHexData(const uint8_t *data, size_t length) {
for (size_t i = 0; i < length; ++i) {
if (data[i] < 0x10) { Serial.print("0"); }
Serial.print(data[i], HEX);
}
Serial.println();
}
void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* hfdcan){
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
if(hfdcan->Instance==FDCAN1)
{
Serial.println("MspInit FDCAN1");
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_FDCAN;
PeriphClkInit.FdcanClockSelection = RCC_FDCANCLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
HAL_RCC_FDCAN_CLK_ENABLED++;
if(HAL_RCC_FDCAN_CLK_ENABLED==1){
__HAL_RCC_FDCAN_CLK_ENABLE();
}
__HAL_RCC_GPIOA_CLK_ENABLE();
/**FDCAN1 GPIO Configuration
PA11 [PA9] ------> FDCAN1_RX
PA12 [PA10] ------> FDCAN1_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF3_FDCAN1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
//else if(hfdcan->Instance==FDCAN2)
{
Serial.println("MspInit FDCAN2");
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_FDCAN;
PeriphClkInit.FdcanClockSelection = RCC_FDCANCLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
HAL_RCC_FDCAN_CLK_ENABLED++;
if(HAL_RCC_FDCAN_CLK_ENABLED==1){
__HAL_RCC_FDCAN_CLK_ENABLE();
}
__HAL_RCC_GPIOB_CLK_ENABLE();
/**FDCAN2 GPIO Configuration
PB0 ------> FDCAN2_RX
PB1 ------> FDCAN2_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF3_FDCAN2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
}
void setup() {
Serial.setTx(TX5);
Serial.setRx(RX5);
Serial.begin(115200);
delay(2000);
pinMode(CAN1_MODE, OUTPUT);
pinMode(CAN2_MODE, OUTPUT);
pinMode(CAN1_VCC, OUTPUT);
pinMode(CAN2_VCC, OUTPUT);
digitalWrite(CAN1_VCC, HIGH);
digitalWrite(CAN2_VCC, HIGH);
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
fdcan1Init();
fdcan2Init();
}
void loop() {
// Set up transmission message
// TxHeader.Identifier = 0x123;
// TxHeader.IdType = FDCAN_STANDARD_ID;
// TxHeader.TxFrameType = FDCAN_DATA_FRAME;
// TxHeader.DataLength = FDCAN_DLC_BYTES_8;
// TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
// TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
// TxHeader.FDFormat = FDCAN_FRAME_FD_NO_BRS;
// TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
// TxHeader.MessageMarker = 0;
TxHeader.Identifier = 0x321;
TxHeader.IdType = FDCAN_STANDARD_ID;
TxHeader.TxFrameType = FDCAN_DATA_FRAME;
TxHeader.DataLength = FDCAN_DLC_BYTES_8;
TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
TxHeader.FDFormat = FDCAN_CLASSIC_CAN;
TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
TxHeader.MessageMarker = 0;
TxData[0] = 0x01; TxData[1] = 0x02; TxData[2] = 0x03; TxData[3] = 0x04;
TxData[4] = 0x05; TxData[5] = 0x06; TxData[6] = 0x07; TxData[7] = 0x08;
if (HAL_FDCAN_AddMessageToTxFifoQ(phfdcan1, &TxHeader, TxData) != HAL_OK) {
error_handler_();
} else {
Serial.println("> FDCAN1 TX 0102030405060708");
}
//while ((phfdcan1->Instance->IR & FDCAN_IR_TFE) != FDCAN_IR_TFE) {} //wait fifo empty
//phfdcan1->Instance->IR &= FDCAN_IR_TFE; //clear complete flag
if (HAL_FDCAN_GetRxMessage(phfdcan2, FDCAN_RX_FIFO0, &RxHeader, RxData) == HAL_OK) {
Serial.print("< FDCAN2 RX ");
printHexData(RxData, 8);
}
else checkCANErrors(phfdcan2);
delay(10);
if (HAL_FDCAN_AddMessageToTxFifoQ(phfdcan2, &TxHeader, TxData) != HAL_OK) {
error_handler_();
} else {
Serial.println("> FDCAN2 TX 0102030405060708");
}
if (HAL_FDCAN_GetRxMessage(phfdcan1, FDCAN_RX_FIFO0, &RxHeader, RxData) == HAL_OK) {
Serial.print("< FDCAN1 RX ");
printHexData(RxData, 8);
}
else checkCANErrors(phfdcan1);
delay(1000);
}