Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions platforms/stm32h563/include/fdcan.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ HAL_StatusTypeDef can_init(can_t *can, FDCAN_HandleTypeDef *hcan);
HAL_StatusTypeDef can_send_msg(can_t *can, can_msg_t *msg);
HAL_StatusTypeDef can_add_filter_standard(can_t *can, uint16_t can_ids[2]);
HAL_StatusTypeDef can_add_filter_extended(can_t *can, uint32_t can_ids[2]);
bool can_is_bus_off(can_t *can);
HAL_StatusTypeDef can_recover_bus_off(can_t *can);

// clang-format on
#endif // FDCAN_H
52 changes: 47 additions & 5 deletions platforms/stm32h563/src/fdcan.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,31 @@ HAL_StatusTypeDef can_init(can_t *can, FDCAN_HandleTypeDef *hcan)
can->extended_filter_index = 0;
can->hcan = hcan;

/* Config interrupts */
/* Config incoming message interrupt. */
HAL_StatusTypeDef status = HAL_FDCAN_ConfigInterruptLines(can->hcan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, FDCAN_INTERRUPT_LINE0);
if (status != HAL_OK)
{
printf("[fdcan.c/can_init()] ERROR: Failed to run HAL_FDCAN_ConfigInterruptLines() (Status: %d).\n", status);
printf("[fdcan.c/can_init()] ERROR: Failed to run HAL_FDCAN_ConfigInterruptLines(can->hcan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, FDCAN_INTERRUPT_LINE0); (Status: %d).\n", status);
return status;
}

/* Activate interrupt notifications */
status = HAL_FDCAN_ActivateNotification(can->hcan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
if (status != HAL_OK)
{
printf("[fdcan.c/can_init()] ERROR: Failed to run HAL_FDCAN_ActivateNotification() (Status: %d).\n", status);
printf("[fdcan.c/can_init()] ERROR: Failed to run HAL_FDCAN_ActivateNotification(can->hcan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0); (Status: %d).\n", status);
return status;
}

/* Config BusOff interrupt. */
status = HAL_FDCAN_ConfigInterruptLines(can->hcan, FDCAN_IT_BUS_OFF, FDCAN_INTERRUPT_LINE1);
if (status != HAL_OK)
{
printf("[fdcan.c/can_init()] ERROR: Failed to run HAL_FDCAN_ConfigInterruptLines(can->hcan, FDCAN_IT_BUS_OFF, FDCAN_INTERRUPT_LINE1); (Status: %d).\n", status);
return status;
}
status = HAL_FDCAN_ActivateNotification(can->hcan, FDCAN_IT_BUS_OFF, 1);
if (status != HAL_OK)
{
printf("[fdcan.c/can_init()] ERROR: Failed to run HAL_FDCAN_ActivateNotification(can->hcan, FDCAN_IT_BUS_OFF, 1); (Status: %d).\n", status);
return status;
}

Expand Down Expand Up @@ -101,6 +113,36 @@ HAL_StatusTypeDef can_add_filter_extended(can_t *can, uint32_t can_ids[2])
return status;
}

/* Returns true if the CAN node is in bus-off state. */
bool can_is_bus_off(can_t *can) {
FDCAN_ProtocolStatusTypeDef status;
HAL_FDCAN_GetProtocolStatus(can->hcan, &status);
return (bool)status.BusOff;
}

/* Recovers from bus-off by stopping and restarting the FDCAN peripheral.
Filters survive Stop/Start but notifications do not, so RX FIFO interrupt is re-enabled. */
HAL_StatusTypeDef can_recover_bus_off(can_t *can) {
HAL_StatusTypeDef status = HAL_FDCAN_Stop(can->hcan);
if (status != HAL_OK) {
printf("[fdcan.c/can_recover_bus_off()] ERROR: HAL_FDCAN_Stop() failed (Status: %d).\n", status);
return status;
}

status = HAL_FDCAN_Start(can->hcan);
if (status != HAL_OK) {
printf("[fdcan.c/can_recover_bus_off()] ERROR: HAL_FDCAN_Start() failed (Status: %d).\n", status);
return status;
}

status = HAL_FDCAN_ActivateNotification(can->hcan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
if (status != HAL_OK) {
printf("[fdcan.c/can_recover_bus_off()] ERROR: HAL_FDCAN_ActivateNotification() failed (Status: %d).\n", status);
}

return status;
}

/* Sends a CAN message. */
HAL_StatusTypeDef can_send_msg(can_t *can, can_msg_t *msg)
{
Expand Down
Loading