2023-04-04 05:30 AM
Hello,
when I try to receive a CAN-Frame it is not received by the Microcontroller, it is within the range, I have no idea what the issue is.
Thanks to everybody in advance, Best Regards, Seppel
void FDCAN_Config(FDCAN_HandleTypeDef *pHfdcan)
{
pHandleToFdCan = pHfdcan;
/* Configure Rx filter */
sFilterConfig.IdType = FDCAN_STANDARD_ID;
sFilterConfig.FilterIndex = 0;
sFilterConfig.FilterType = FDCAN_FILTER_RANGE;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
sFilterConfig.FilterID1 = 0x700;
sFilterConfig.FilterID2 = 0x7FF;
if (HAL_FDCAN_ConfigFilter(pHandleToFdCan, &sFilterConfig) != HAL_OK)
{
Error_Handler();
}
/* Configure global filter:
Filter all remote frames with STD and EXT ID
Reject non matching frames with STD ID and EXT ID */
if (HAL_FDCAN_ConfigGlobalFilter(pHandleToFdCan, FDCAN_REJECT, FDCAN_REJECT, FDCAN_REJECT, FDCAN_REJECT) != HAL_OK)
{
Error_Handler();
}
/* Start the FDCAN module */
if (HAL_FDCAN_Start(pHandleToFdCan) != HAL_OK)
{
Error_Handler();
}
if (HAL_FDCAN_ActivateNotification(pHandleToFdCan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
{
Error_Handler();
}
}
P.S. TX works perfectly fine, as you can see it Ack's the 0x701 Frame that was received.
2023-04-04 08:02 AM
This one?
Call:
/* FDCAN2 init function */
void MX_FDCAN2_Init(void)
{
/* USER CODE BEGIN FDCAN2_Init 0 */
/* USER CODE END FDCAN2_Init 0 */
/* USER CODE BEGIN FDCAN2_Init 1 */
/* USER CODE END FDCAN2_Init 1 */
hfdcan2.Instance = FDCAN2;
hfdcan2.Init.ClockDivider = FDCAN_CLOCK_DIV1;
hfdcan2.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
hfdcan2.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan2.Init.AutoRetransmission = DISABLE;
hfdcan2.Init.TransmitPause = DISABLE;
hfdcan2.Init.ProtocolException = DISABLE;
hfdcan2.Init.NominalPrescaler = 4;
hfdcan2.Init.NominalSyncJumpWidth = 1;
hfdcan2.Init.NominalTimeSeg1 = 59;
hfdcan2.Init.NominalTimeSeg2 = 20;
hfdcan2.Init.DataPrescaler = 8;
hfdcan2.Init.DataSyncJumpWidth = 1;
hfdcan2.Init.DataTimeSeg1 = 29;
hfdcan2.Init.DataTimeSeg2 = 10;
hfdcan2.Init.StdFiltersNbr = 0;
hfdcan2.Init.ExtFiltersNbr = 0;
hfdcan2.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
if (HAL_FDCAN_Init(&hfdcan2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN FDCAN2_Init 2 */
/* USER CODE END FDCAN2_Init 2 */
}
2023-04-04 08:03 AM
/**
* @brief Initializes the FDCAN peripheral according to the specified
* parameters in the FDCAN_InitTypeDef structure.
* @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
* the configuration information for the specified FDCAN.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_FDCAN_Init(FDCAN_HandleTypeDef *hfdcan)
{
uint32_t tickstart;
/* Check FDCAN handle */
if (hfdcan == NULL)
{
return HAL_ERROR;
}
/* Check function parameters */
assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));
if (hfdcan->Instance == FDCAN1)
{
assert_param(IS_FDCAN_CKDIV(hfdcan->Init.ClockDivider));
}
assert_param(IS_FDCAN_FRAME_FORMAT(hfdcan->Init.FrameFormat));
assert_param(IS_FDCAN_MODE(hfdcan->Init.Mode));
assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.AutoRetransmission));
assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.TransmitPause));
assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.ProtocolException));
assert_param(IS_FDCAN_NOMINAL_PRESCALER(hfdcan->Init.NominalPrescaler));
assert_param(IS_FDCAN_NOMINAL_SJW(hfdcan->Init.NominalSyncJumpWidth));
assert_param(IS_FDCAN_NOMINAL_TSEG1(hfdcan->Init.NominalTimeSeg1));
assert_param(IS_FDCAN_NOMINAL_TSEG2(hfdcan->Init.NominalTimeSeg2));
if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)
{
assert_param(IS_FDCAN_DATA_PRESCALER(hfdcan->Init.DataPrescaler));
assert_param(IS_FDCAN_DATA_SJW(hfdcan->Init.DataSyncJumpWidth));
assert_param(IS_FDCAN_DATA_TSEG1(hfdcan->Init.DataTimeSeg1));
assert_param(IS_FDCAN_DATA_TSEG2(hfdcan->Init.DataTimeSeg2));
}
assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.StdFiltersNbr, SRAMCAN_FLS_NBR));
assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.ExtFiltersNbr, SRAMCAN_FLE_NBR));
assert_param(IS_FDCAN_TX_FIFO_QUEUE_MODE(hfdcan->Init.TxFifoQueueMode));
#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
if (hfdcan->State == HAL_FDCAN_STATE_RESET)
{
/* Allocate lock resource and initialize it */
hfdcan->Lock = HAL_UNLOCKED;
/* Reset callbacks to legacy functions */
hfdcan->TxEventFifoCallback = HAL_FDCAN_TxEventFifoCallback; /* Legacy weak TxEventFifoCallback */
hfdcan->RxFifo0Callback = HAL_FDCAN_RxFifo0Callback; /* Legacy weak RxFifo0Callback */
hfdcan->RxFifo1Callback = HAL_FDCAN_RxFifo1Callback; /* Legacy weak RxFifo1Callback */
hfdcan->TxFifoEmptyCallback = HAL_FDCAN_TxFifoEmptyCallback; /* Legacy weak TxFifoEmptyCallback */
hfdcan->TxBufferCompleteCallback = HAL_FDCAN_TxBufferCompleteCallback; /* Legacy weak
TxBufferCompleteCallback */
hfdcan->TxBufferAbortCallback = HAL_FDCAN_TxBufferAbortCallback; /* Legacy weak
TxBufferAbortCallback */
hfdcan->HighPriorityMessageCallback = HAL_FDCAN_HighPriorityMessageCallback; /* Legacy weak
HighPriorityMessageCallback */
hfdcan->TimestampWraparoundCallback = HAL_FDCAN_TimestampWraparoundCallback; /* Legacy weak
TimestampWraparoundCallback */
hfdcan->TimeoutOccurredCallback = HAL_FDCAN_TimeoutOccurredCallback; /* Legacy weak
TimeoutOccurredCallback */
hfdcan->ErrorCallback = HAL_FDCAN_ErrorCallback; /* Legacy weak ErrorCallback */
hfdcan->ErrorStatusCallback = HAL_FDCAN_ErrorStatusCallback; /* Legacy weak ErrorStatusCallback */
if (hfdcan->MspInitCallback == NULL)
{
hfdcan->MspInitCallback = HAL_FDCAN_MspInit; /* Legacy weak MspInit */
}
/* Init the low level hardware: CLOCK, NVIC */
hfdcan->MspInitCallback(hfdcan);
}
#else
if (hfdcan->State == HAL_FDCAN_STATE_RESET)
{
/* Allocate lock resource and initialize it */
hfdcan->Lock = HAL_UNLOCKED;
/* Init the low level hardware: CLOCK, NVIC */
HAL_FDCAN_MspInit(hfdcan);
}
#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
/* Exit from Sleep mode */
CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CSR);
/* Get tick */
tickstart = HAL_GetTick();
/* Check Sleep mode acknowledge */
while ((hfdcan->Instance->CCCR & FDCAN_CCCR_CSA) == FDCAN_CCCR_CSA)
{
if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)
{
/* Update error code */
hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
/* Change FDCAN state */
hfdcan->State = HAL_FDCAN_STATE_ERROR;
return HAL_ERROR;
}
}
/* Request initialisation */
SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);
/* Get tick */
tickstart = HAL_GetTick();
/* Wait until the INIT bit into CCCR register is set */
while ((hfdcan->Instance->CCCR & FDCAN_CCCR_INIT) == 0U)
{
/* Check for the Timeout */
if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)
{
/* Update error code */
hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
/* Change FDCAN state */
hfdcan->State = HAL_FDCAN_STATE_ERROR;
return HAL_ERROR;
}
}
/* Enable configuration change */
SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CCE);
/* Check FDCAN instance */
if (hfdcan->Instance == FDCAN1)
{
/* Configure Clock divider */
FDCAN_CONFIG->CKDIV = hfdcan->Init.ClockDivider;
}
/* Set the no automatic retransmission */
if (hfdcan->Init.AutoRetransmission == ENABLE)
{
CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);
}
else
{
SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);
}
/* Set the transmit pause feature */
if (hfdcan->Init.TransmitPause == ENABLE)
{
SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);
}
else
{
CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);
}
/* Set the Protocol Exception Handling */
if (hfdcan->Init.ProtocolException == ENABLE)
{
CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);
}
else
{
SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);
}
/* Set FDCAN Frame Format */
MODIFY_REG(hfdcan->Instance->CCCR, FDCAN_FRAME_FD_BRS, hfdcan->Init.FrameFormat);
/* Reset FDCAN Operation Mode */
CLEAR_BIT(hfdcan->Instance->CCCR, (FDCAN_CCCR_TEST | FDCAN_CCCR_MON | FDCAN_CCCR_ASM));
CLEAR_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);
/* Set FDCAN Operating Mode:
| Normal | Restricted | Bus | Internal | External
| | Operation | Monitoring | LoopBack | LoopBack
CCCR.TEST | 0 | 0 | 0 | 1 | 1
CCCR.MON | 0 | 0 | 1 | 1 | 0
TEST.LBCK | 0 | 0 | 0 | 1 | 1
CCCR.ASM | 0 | 1 | 0 | 0 | 0
*/
if (hfdcan->Init.Mode == FDCAN_MODE_RESTRICTED_OPERATION)
{
/* Enable Restricted Operation mode */
SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_ASM);
}
else if (hfdcan->Init.Mode != FDCAN_MODE_NORMAL)
{
if (hfdcan->Init.Mode != FDCAN_MODE_BUS_MONITORING)
{
/* Enable write access to TEST register */
SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TEST);
/* Enable LoopBack mode */
SET_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);
if (hfdcan->Init.Mode == FDCAN_MODE_INTERNAL_LOOPBACK)
{
SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);
}
}
else
{
/* Enable bus monitoring mode */
SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);
}
}
else
{
/* Nothing to do: normal mode */
}
/* Set the nominal bit timing register */
hfdcan->Instance->NBTP = ((((uint32_t)hfdcan->Init.NominalSyncJumpWidth - 1U) << FDCAN_NBTP_NSJW_Pos) | \
(((uint32_t)hfdcan->Init.NominalTimeSeg1 - 1U) << FDCAN_NBTP_NTSEG1_Pos) | \
(((uint32_t)hfdcan->Init.NominalTimeSeg2 - 1U) << FDCAN_NBTP_NTSEG2_Pos) | \
(((uint32_t)hfdcan->Init.NominalPrescaler - 1U) << FDCAN_NBTP_NBRP_Pos));
/* If FD operation with BRS is selected, set the data bit timing register */
if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)
{
hfdcan->Instance->DBTP = ((((uint32_t)hfdcan->Init.DataSyncJumpWidth - 1U) << FDCAN_DBTP_DSJW_Pos) | \
(((uint32_t)hfdcan->Init.DataTimeSeg1 - 1U) << FDCAN_DBTP_DTSEG1_Pos) | \
(((uint32_t)hfdcan->Init.DataTimeSeg2 - 1U) << FDCAN_DBTP_DTSEG2_Pos) | \
(((uint32_t)hfdcan->Init.DataPrescaler - 1U) << FDCAN_DBTP_DBRP_Pos));
}
/* Select between Tx FIFO and Tx Queue operation modes */
SET_BIT(hfdcan->Instance->TXBC, hfdcan->Init.TxFifoQueueMode);
/* Calculate each RAM block address */
FDCAN_CalcultateRamBlockAddresses(hfdcan);
/* Initialize the Latest Tx request buffer index */
hfdcan->LatestTxFifoQRequest = 0U;
/* Initialize the error code */
hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;
/* Initialize the FDCAN state */
hfdcan->State = HAL_FDCAN_STATE_READY;
/* Return function status */
return HAL_OK;
}
2023-04-04 08:07 AM
Not quite. FDCAN_InitTypeDef structure declaration.
This is the type for your Init above.
2023-04-04 08:10 AM
In the "FDCAN_HandleTypeDef" struct is a member " FDCAN_MsgRamAddressTypeDef msgRam; "
I have no idea how that is used and I have not seen it in any example,... .
/**
* @brief FDCAN handle structure definition
*/
#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
typedef struct __FDCAN_HandleTypeDef
#else
typedef struct
#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
{
FDCAN_GlobalTypeDef *Instance; /*!< Register base address */
FDCAN_InitTypeDef Init; /*!< FDCAN required parameters */
FDCAN_MsgRamAddressTypeDef msgRam; /*!< FDCAN Message RAM blocks */
uint32_t LatestTxFifoQRequest; /*!< FDCAN Tx buffer index
of latest Tx FIFO/Queue request */
__IO HAL_FDCAN_StateTypeDef State; /*!< FDCAN communication state */
HAL_LockTypeDef Lock; /*!< FDCAN locking object */
__IO uint32_t ErrorCode; /*!< FDCAN Error code */
#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
void (* TxEventFifoCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TxEventFifoITs); /*!< FDCAN Tx Event Fifo callback */
void (* RxFifo0Callback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs); /*!< FDCAN Rx Fifo 0 callback */
void (* RxFifo1Callback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo1ITs); /*!< FDCAN Rx Fifo 1 callback */
void (* TxFifoEmptyCallback)(struct __FDCAN_HandleTypeDef *hfdcan); /*!< FDCAN Tx Fifo Empty callback */
void (* TxBufferCompleteCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes); /*!< FDCAN Tx Buffer complete callback */
void (* TxBufferAbortCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes); /*!< FDCAN Tx Buffer abort callback */
void (* HighPriorityMessageCallback)(struct __FDCAN_HandleTypeDef *hfdcan); /*!< FDCAN High priority message callback */
void (* TimestampWraparoundCallback)(struct __FDCAN_HandleTypeDef *hfdcan); /*!< FDCAN Timestamp wraparound callback */
void (* TimeoutOccurredCallback)(struct __FDCAN_HandleTypeDef *hfdcan); /*!< FDCAN Timeout occurred callback */
void (* ErrorCallback)(struct __FDCAN_HandleTypeDef *hfdcan); /*!< FDCAN Error callback */
void (* ErrorStatusCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs); /*!< FDCAN Error status callback */
void (* MspInitCallback)(struct __FDCAN_HandleTypeDef *hfdcan); /*!< FDCAN Msp Init callback */
void (* MspDeInitCallback)(struct __FDCAN_HandleTypeDef *hfdcan); /*!< FDCAN Msp DeInit callback */
#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
} FDCAN_HandleTypeDef;
2023-04-04 08:19 AM
I mean this guy:
typedef struct
{
uint32_t FrameFormat; /*!< Specifies the FDCAN frame format.
This parameter can be a value of @ref FDCAN_frame_format */
uint32_t Mode; /*!< Specifies the FDCAN mode.
This parameter can be a value of @ref FDCAN_operating_mode */
FunctionalState AutoRetransmission; /*!< Enable or disable the automatic retransmission mode.
This parameter can be set to ENABLE or DISABLE */
FunctionalState TransmitPause; /*!< Enable or disable the Transmit Pause feature.
This parameter can be set to ENABLE or DISABLE */
FunctionalState ProtocolException; /*!< Enable or disable the Protocol Exception Handling.
This parameter can be set to ENABLE or DISABLE */
uint32_t NominalPrescaler; /*!< Specifies the value by which the oscillator frequency is
divided for generating the nominal bit time quanta.
This parameter must be a number between 1 and 512 */
uint32_t NominalSyncJumpWidth; /*!< Specifies the maximum number of time quanta the FDCAN
hardware is allowed to lengthen or shorten a bit to perform
resynchronization.
This parameter must be a number between 1 and 128 */
uint32_t NominalTimeSeg1; /*!< Specifies the number of time quanta in Bit Segment 1.
This parameter must be a number between 2 and 256 */
uint32_t NominalTimeSeg2; /*!< Specifies the number of time quanta in Bit Segment 2.
This parameter must be a number between 2 and 128 */
uint32_t DataPrescaler; /*!< Specifies the value by which the oscillator frequency is
divided for generating the data bit time quanta.
This parameter must be a number between 1 and 32 */
uint32_t DataSyncJumpWidth; /*!< Specifies the maximum number of time quanta the FDCAN
hardware is allowed to lengthen or shorten a data bit to
perform resynchronization.
This parameter must be a number between 1 and 16 */
uint32_t DataTimeSeg1; /*!< Specifies the number of time quanta in Data Bit Segment 1.
This parameter must be a number between 1 and 32 */
uint32_t DataTimeSeg2; /*!< Specifies the number of time quanta in Data Bit Segment 2.
This parameter must be a number between 1 and 16 */
uint32_t MessageRAMOffset; /*!< Specifies the message RAM start address.
This parameter must be a number between 0 and 2560 */
uint32_t StdFiltersNbr; /*!< Specifies the number of standard Message ID filters.
This parameter must be a number between 0 and 128 */
uint32_t ExtFiltersNbr; /*!< Specifies the number of extended Message ID filters.
This parameter must be a number between 0 and 64 */
uint32_t RxFifo0ElmtsNbr; /*!< Specifies the number of Rx FIFO0 Elements.
This parameter must be a number between 0 and 64 */
uint32_t RxFifo0ElmtSize; /*!< Specifies the Data Field Size in an Rx FIFO 0 element.
This parameter can be a value of @ref FDCAN_data_field_size */
uint32_t RxFifo1ElmtsNbr; /*!< Specifies the number of Rx FIFO 1 Elements.
This parameter must be a number between 0 and 64 */
uint32_t RxFifo1ElmtSize; /*!< Specifies the Data Field Size in an Rx FIFO 1 element.
This parameter can be a value of @ref FDCAN_data_field_size */
uint32_t RxBuffersNbr; /*!< Specifies the number of Dedicated Rx Buffer elements.
This parameter must be a number between 0 and 64 */
uint32_t RxBufferSize; /*!< Specifies the Data Field Size in an Rx Buffer element.
This parameter can be a value of @ref FDCAN_data_field_size */
uint32_t TxEventsNbr; /*!< Specifies the number of Tx Event FIFO elements.
This parameter must be a number between 0 and 32 */
uint32_t TxBuffersNbr; /*!< Specifies the number of Dedicated Tx Buffers.
This parameter must be a number between 0 and 32 */
uint32_t TxFifoQueueElmtsNbr; /*!< Specifies the number of Tx Buffers used for Tx FIFO/Queue.
This parameter must be a number between 0 and 32 */
uint32_t TxFifoQueueMode; /*!< Tx FIFO/Queue Mode selection.
This parameter can be a value of @ref FDCAN_txFifoQueue_Mode */
uint32_t TxElmtSize; /*!< Specifies the Data Field Size in a Tx Element.
This parameter can be a value of @ref FDCAN_data_field_size */
} FDCAN_InitTypeDef;
2023-04-04 08:28 AM
Are you working for ST. Is there someone who knows that CAN-Controller and knows how to set up the behaviour of the RX-Queue etc. ? That fancy presentation, nice for marketing, but useless for engineers with no references to HAL function: STM32G4-Peripheral-Flexible_Datarate_Controller_Area_Network_FDCAN.pdf
/**
* @brief FDCAN Init structure definition
*/
typedef struct
{
uint32_t ClockDivider; /*!< Specifies the FDCAN kernel clock divider.
The clock is common to all FDCAN instances.
This parameter is applied only at initialisation of
first FDCAN instance.
This parameter can be a value of @ref FDCAN_clock_divider. */
uint32_t FrameFormat; /*!< Specifies the FDCAN frame format.
This parameter can be a value of @ref FDCAN_frame_format */
uint32_t Mode; /*!< Specifies the FDCAN mode.
This parameter can be a value of @ref FDCAN_operating_mode */
FunctionalState AutoRetransmission; /*!< Enable or disable the automatic retransmission mode.
This parameter can be set to ENABLE or DISABLE */
FunctionalState TransmitPause; /*!< Enable or disable the Transmit Pause feature.
This parameter can be set to ENABLE or DISABLE */
FunctionalState ProtocolException; /*!< Enable or disable the Protocol Exception Handling.
This parameter can be set to ENABLE or DISABLE */
uint32_t NominalPrescaler; /*!< Specifies the value by which the oscillator frequency is
divided for generating the nominal bit time quanta.
This parameter must be a number between 1 and 512 */
uint32_t NominalSyncJumpWidth; /*!< Specifies the maximum number of time quanta the FDCAN
hardware is allowed to lengthen or shorten a bit to perform
resynchronization.
This parameter must be a number between 1 and 128 */
uint32_t NominalTimeSeg1; /*!< Specifies the number of time quanta in Bit Segment 1.
This parameter must be a number between 2 and 256 */
uint32_t NominalTimeSeg2; /*!< Specifies the number of time quanta in Bit Segment 2.
This parameter must be a number between 2 and 128 */
uint32_t DataPrescaler; /*!< Specifies the value by which the oscillator frequency is
divided for generating the data bit time quanta.
This parameter must be a number between 1 and 32 */
uint32_t DataSyncJumpWidth; /*!< Specifies the maximum number of time quanta the FDCAN
hardware is allowed to lengthen or shorten a data bit to
perform resynchronization.
This parameter must be a number between 1 and 16 */
uint32_t DataTimeSeg1; /*!< Specifies the number of time quanta in Data Bit Segment 1.
This parameter must be a number between 1 and 32 */
uint32_t DataTimeSeg2; /*!< Specifies the number of time quanta in Data Bit Segment 2.
This parameter must be a number between 1 and 16 */
uint32_t StdFiltersNbr; /*!< Specifies the number of standard Message ID filters.
This parameter must be a number between 0 and 28 */
uint32_t ExtFiltersNbr; /*!< Specifies the number of extended Message ID filters.
This parameter must be a number between 0 and 8 */
uint32_t TxFifoQueueMode; /*!< Tx FIFO/Queue Mode selection.
This parameter can be a value of @ref FDCAN_txFifoQueue_Mode */
} FDCAN_InitTypeDef;
2023-04-04 08:50 AM
I am just another user who has FDCAN working on a somewhat similar MPU, that's all.
2023-04-04 08:52 AM
Did you get the RX Callback working? How did you set it up, could you share some screenshts and code-snippets?
2023-04-04 09:04 AM
I don't know how similar G4 / H7 FDCANs are, so all of the following might only apply to the H7.
The H7 has some 10 kB SRAM reserved for FDCAN.
This "CAN-RAM" is used for:
The RAM layout depends on your INIT settings, how many filters, buffers, etcpp you assign.
Then it calculates the RAM (starting) addresses / pointers from that.
First thing I see in your init:
StdFiltersNbr = 0; ExtFiltersNbr = 0;
Which means you have no filters assigned to memory.
Comparing to my H7 source, I also miss the settings for RX & TX buffers & FIFO, so my H7 init looks like this:
void MX_FDCAN1_Init(uint32_t u32DataRate)
{
FDCAN_HandleTypeDef *phCan = &hCan1;
FDCAN_FilterTypeDef sFilterConfig = { 0 };
phCan->Instance = FDCAN1;
phCan->Init.FrameFormat = FDCAN_FRAME_FD_BRS;
phCan->Init.Mode = FDCAN_MODE_NORMAL;//FDCAN_MODE_EXTERNAL_LOOPBACK;//
phCan->Init.AutoRetransmission = ENABLE;
phCan->Init.TransmitPause = ENABLE;
phCan->Init.ProtocolException = ENABLE;
/* clock / timing */
/* nominal = arbitration phase
* NBTP
* 80 MHz: tq = NominalPrescaler x (1/fdcan_ker_ck)
* -> tq = 12.5 ns
* data rate = 1 / ((SyncSeg + Seg1 + Seg2) * tq)
* with SyncSeg = 1
* 0.5 Mbps = 160 * tq
* -> TimeSeg1 + TimeSeg2 = 157
*/
phCan->Init.NominalPrescaler = 1; /* tq = NominalPrescaler x (1/fdcan_ker_ck) */
#if( 1 )
/* 5000 ppm */
phCan->Init.NominalTimeSeg1 = 138; /* NTSEG1 1..256, NominalTimeSeg1 = Propagation_segment + Phase_segment_1 */
phCan->Init.NominalTimeSeg2 = 21; /* NTSEG2 1..128 */
phCan->Init.NominalSyncJumpWidth = 20; /* NSJW 1..128 should be < NTSEG2 */
#else
/* 500 ppm */
phCan->Init.NominalTimeSeg1 = 155; /* NTSEG1 1..256, NominalTimeSeg1 = Propagation_segment + Phase_segment_1 */
phCan->Init.NominalTimeSeg2 = 4; /* NTSEG2 1..128 */
phCan->Init.NominalSyncJumpWidth = 3; /* NSJW 1..128 should be < NTSEG2 */
#endif
/* data = data phase with bit rate switching
* DBTP
* 80 MHz: tq = DataPrescaler x (1/fdcan_ker_ck)
* -> tq = 12.5 ns
* data rate = 1 / ((SyncSeg + Seg1 + Seg2) * tq)
* with SyncSeg = 1
*/
phCan->Init.DataPrescaler = 1; /* DBRP 1..32 */
CanInitBsrDataRate(phCan, u32DataRate);
/* RAM: filters, buffers */
/* start pos in RAM of 2560 32-bit words */
phCan->Init.MessageRAMOffset = 0;
phCan->Init.StdFiltersNbr = 16;
phCan->Init.ExtFiltersNbr = 16;
phCan->Init.RxFifo0ElmtsNbr = 16;
phCan->Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_64;
phCan->Init.RxFifo1ElmtsNbr = 16;
phCan->Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_64;
phCan->Init.RxBuffersNbr = 16;
phCan->Init.RxBufferSize = FDCAN_DATA_BYTES_64;
phCan->Init.TxEventsNbr = 0;
phCan->Init.TxBuffersNbr = 4;
phCan->Init.TxFifoQueueElmtsNbr = 4;
phCan->Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
phCan->Init.TxElmtSize = FDCAN_DATA_BYTES_64;
if( HAL_FDCAN_Init(phCan) != HAL_OK ) Error_Handler_FL(__FILE__, __LINE__);
/* Filters - STANDARD */
sFilterConfig.FilterType = 0; /* ignored for FDCAN_FILTER_TO_RXBUFFER */
sFilterConfig.FilterID2 = 0; /* ignored for FDCAN_FILTER_TO_RXBUFFER */
/* Configure standard ID reception filter to Rx buffer 0 */
sFilterConfig.IdType = FDCAN_STANDARD_ID;
sFilterConfig.FilterIndex = 0;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXBUFFER;
sFilterConfig.RxBufferIndex = 0; /* store ID1 to this RX buffer */
sFilterConfig.FilterID1 = CAN_FILTER_STD_TEST_RXB_ID1; /* MessageID and FilterID1 must match exactly */
HAL_FDCAN_ConfigFilter(phCan, &sFilterConfig);
/* Configure standard ID reception filter to Rx buffer 1 */
sFilterConfig.IdType = FDCAN_STANDARD_ID;
sFilterConfig.FilterIndex = 1;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXBUFFER;
sFilterConfig.RxBufferIndex = 1; /* store ID1 to this RX buffer */
sFilterConfig.FilterID1 = CAN_FILTER_STD_TEST_RXB_ID2; /* MessageID and FilterID1 must match exactly */
HAL_FDCAN_ConfigFilter(phCan, &sFilterConfig);
/* Configure standard ID reception filter to Rx buffer 2 */
sFilterConfig.IdType = FDCAN_STANDARD_ID;
sFilterConfig.FilterIndex = 2;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXBUFFER;
sFilterConfig.RxBufferIndex = 2; /* store ID1 to this RX buffer */
sFilterConfig.FilterID1 = CAN_FILTER_STD_TEST_RXB_ID3; /* MessageID and FilterID1 must match exactly */
HAL_FDCAN_ConfigFilter(phCan, &sFilterConfig);
/* Configure standard ID reception filter to Rx buffer 3 */
sFilterConfig.IdType = FDCAN_STANDARD_ID;
sFilterConfig.FilterIndex = 3;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXBUFFER;
sFilterConfig.RxBufferIndex = 3; /* store ID1 to this RX buffer */
sFilterConfig.FilterID1 = CAN_FILTER_STD_TEST_RXB_ID4; /* MessageID and FilterID1 must match exactly */
HAL_FDCAN_ConfigFilter(phCan, &sFilterConfig);
/* Filters - EXTENDED */
sFilterConfig.RxBufferIndex = 0; /* ignored if not FDCAN_FILTER_TO_RXBUFFER */
/* Configure extended ID reception filter to Rx FIFO 0 */
sFilterConfig.IdType = FDCAN_EXTENDED_ID;
sFilterConfig.FilterIndex = 0;
sFilterConfig.FilterType = FDCAN_FILTER_RANGE_NO_EIDM; /* Range from FilterID1 to FilterID2, no EIDM mask */
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
sFilterConfig.FilterID1 = CAN_FILTER_EXT_TEST_RXF_ID1;
sFilterConfig.FilterID2 = CAN_FILTER_EXT_TEST_RXF_ID2;
HAL_FDCAN_ConfigFilter(phCan, &sFilterConfig);
/* Configure extended ID reception filter to Rx FIFO 1 */
sFilterConfig.IdType = FDCAN_EXTENDED_ID;
sFilterConfig.FilterIndex = 1;
sFilterConfig.FilterType = FDCAN_FILTER_RANGE_NO_EIDM; /* Range from FilterID1 to FilterID2, no EIDM mask */
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
sFilterConfig.FilterID1 = CAN_FILTER_EXT_TEST_RXF_ID3;
sFilterConfig.FilterID2 = CAN_FILTER_EXT_TEST_RXF_ID4;
HAL_FDCAN_ConfigFilter(phCan, &sFilterConfig);
/* Configure global filter to reject all non-matching frames */
HAL_FDCAN_ConfigGlobalFilter(phCan, FDCAN_REJECT, FDCAN_REJECT, FDCAN_REJECT_REMOTE, FDCAN_REJECT_REMOTE);
#if( 0 )
/* Configure Rx FIFO 0 watermark to 2 */
HAL_FDCAN_ConfigFifoWatermark(phCan, FDCAN_CFG_RX_FIFO0, 2);
/* Activate Rx FIFO 0 watermark notification */
HAL_FDCAN_ActivateNotification(phCan, FDCAN_IT_RX_FIFO0_WATERMARK, 0);
#endif
/* timestamp enable, bit time, no prescaler */
phCan->Instance->TSCC = 1;
/* enable TDC = transmitter delay compensation
* this is a MUST for high data rates
*/
/* configure Tx Delay Compensation : TdcOffset = DataTimeSeg1 * DataPrescaler */
uint32_t u32TdcOffs = ((uint32_t)phCan->Instance->DBTP >> FDCAN_DBTP_DTSEG1_Pos) + 1;
uint32_t u32TdcFltWdw = 0;
/* set TDC filter window */
phCan->Instance->TDCR = (u32TdcFltWdw << FDCAN_TDCR_TDCF_Pos);
/* set TDC offset */
phCan->Instance->TDCR |= (u32TdcOffs << FDCAN_TDCR_TDCO_Pos);
/* enable TDC */
phCan->Instance->DBTP |= FDCAN_DBTP_TDC;
/* start FDCAN */
HAL_FDCAN_Start(phCan);
}
2023-04-04 09:12 AM
Don't forget that CubeMX is just a basic setup-thingy.
So use the debugger or the UART to check register settings, like interrupt enable, memory addresses, ...
I just see that I had to put some interrupt enables in the MSP init with direct register settings.
I usually don't use HAL for the important stuff, but until now FDCAN was only a feasability check.
And yes, it works, although I had some problems getting the 8 Mbps running...
static uint32_t HAL_RCC_FDCAN_CLK_ENABLED = 0;
void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* phCan)
{
GPIO_InitTypeDef GPIO_InitStruct = { 0 };
if( phCan->Instance == FDCAN1 )
{
/* FDCAN1 clock enable */
HAL_RCC_FDCAN_CLK_ENABLED++;
if( HAL_RCC_FDCAN_CLK_ENABLED == 1 )
{
__HAL_RCC_FDCAN_CLK_ENABLE();
}
__HAL_RCC_GPIOH_CLK_ENABLE();
/** FDCAN1 GPIO Configuration
PH14 ------> FDCAN1_RX
PH13 ------> FDCAN1_TX
*/
GPIO_InitStruct.Pin = FDCAN1_RX_Pin | FDCAN1_TX_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF9_FDCAN1;
HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
/* FDCAN1 interrupt Init */
HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, 10, 0);
HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn);
HAL_NVIC_SetPriority(FDCAN1_IT1_IRQn, 10, 0);
HAL_NVIC_EnableIRQ(FDCAN1_IT1_IRQn);
/* interrupt enable, all lines to 0 */
phCan->Instance->ILS = 0;
phCan->Instance->IE = (FDCAN_IE_DRXE | FDCAN_IE_RF1NE | FDCAN_IE_RF0NE );
phCan->Instance->ILE = FDCAN_ILE_EINT0;
phCan->Instance->IR = 0xFFFFFFFF;
}
}