firmware
IEM Firmware Documentation
Loading...
Searching...
No Matches
can_rtos.c File Reference

FreeRTOS CAN receive and transmit tasks for STM32H7xx. More...

#include "can_rtos.h"
#include "iem_utils.h"
#include "iem_types.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "timers.h"
#include "stm32h7xx_hal.h"
#include <string.h>
Include dependency graph for can_rtos.c:

Data Structures

struct  can_tx_params
struct  msg_timeout
struct  can_rx_params

Macros

#define MSG_RX_NOTIF_IDX   0
#define MSG_TX_NOTIF_IDX   0
#define CAN_STD_ID_MAX   0x7FF
#define CAN_EXT_ID_MAX   0x1FFFFFFF
#define MS_PER_S   1000
#define TIMESTAMP_PRESCALER   16U
#define TIMESTAMP_PRESCALER_HAL   FDCAN_TIMESTAMP_PRESC_16
#define FIFO_FULL_BLOCK_TIMEOUT   pdTICKS_TO_MS(25)

Functions

static void task_can_tx (void *task_params_ptr)
 Implements the CAN transmit task.
static void task_can_rx (void *task_params_ptr)
 Implements the CAN receive task.
static void can_rx_pending_callback (FDCAN_HandleTypeDef *hfdcan, uint32_t rx_its)
 CAN message receive pending ISR. Unblocks the CAN receive task for the bus/peripheral through a direct-to-task notification.
static void can_rx_wraparound_callback (FDCAN_HandleTypeDef *hfdcan)
 FDCAN peripheral timestamp counter wraparound ISR. Increments the timestamp_ovf_since_last_rx field for each tracked message for the peripheral/task.
static void can_tx_cplt_callback (FDCAN_HandleTypeDef *hfdcan, uint32_t buffer_idxs)
 CAN message transmit complete ISR. Unblocks the CAN transmit task for the bus/peripheral through a direct-to-task notification if the task is waiting for free space the hardware Tx FIFO.
static void can_tx_periodic_msg_callback (TimerHandle_t timer_hdl)
 Scheduled CAN message FreeRTOS timer callback. Timer created and started in canlib_register_scheduled_msgs()
static void can_error_status_callback (FDCAN_HandleTypeDef *hfdcan, uint32_t error_status_its)
static void update_msg_timeout (struct can_rx_params *params_ptr, uint32_t msg_id, uint16_t rx_timestamp)
 Updates the timeout timestamp for a CAN ID. Called after a message is received by the CAN receive task.
static void insertion_sort (uint32_t arr_ptr[], unsigned length)
 Sorts a uint32_t array in ascending order.
static __always_inline enum can_bus get_bus (FDCAN_HandleTypeDef *hfdcan)
 Gets the CAN bus associated with an FDCAN peripheral.
static __always_inline FDCAN_HandleTypeDef * get_hfdcan (enum can_bus bus)
 Gets the FDCAN peripheral associated with a CAN bus.
void canlib_tx_task_init (Task_Init_t *init_ptr, enum can_bus bus, FDCAN_HandleTypeDef *hfdcan, uint16_t tx_queue_length)
 Initializes a FreeRTOS CAN transmit task for bus and creates a transmit queue with capacity tx_queue_length.
void canlib_rx_task_init (Task_Init_t *init_ptr, enum can_bus bus, FDCAN_HandleTypeDef *hfdcan, uint32_t rx_location, CAN_Rx_Handler_t handler)
 Initializes a FreeRTOS CAN receive task for bus that receives messages from rx_location. Calls callback when a new message is received.
void canlib_start ()
 Starts all STM32 FDCAN peripherals that were registered to a CAN transmit or receive task.
bool canlib_tx_generic (const CAN_Msg_t *msg_ptr, TickType_t block_time, bool is_critical)
 Queues a CAN message for transmission.
TimerHandle_t canlib_register_scheduled_msgs (struct canlib_scheduled_msg_params *params_ptr)
 Registers an array of CAN messages for periodic transmission on a set interval with a FreeRTOS software timer.
void canlib_register_timeout_ids (enum can_bus bus, FDCAN_HandleTypeDef *hfdcan, uint32_t timeout_ids_ptr[], unsigned timeout_ids_cnt)
 Registers CAN messages for timeout tracking by the CAN receive task for a CAN bus (also sorts the array of CAN IDs in ascending order, lol)
uint32_t canlib_get_msg_timeout (enum can_bus bus, uint32_t msg_id)
 Get the time since a message with ID msg_id was received on bus. If the CAN ID wasn't registered with canlib_register_timeout_ids() first on initialization, the returned value will be CANLIB_TIMEOUT_INVALID (UINT32_MAX)
bool canlib_is_bus_ok (enum can_bus bus)
 Checks for protocol errors on bus.

Variables

static TaskHandle_t g_can_tx_hdls [CAN_BUS_CNT]
static struct can_tx_params g_can_tx_params [CAN_BUS_CNT]
static TaskHandle_t g_can_rx_hdls [CAN_BUS_CNT]
static struct can_rx_params g_can_rx_params [CAN_BUS_CNT]

Detailed Description

FreeRTOS CAN receive and transmit tasks for STM32H7xx.

Author
Jamie Pruett :)
Date
2025-01-14

Macro Definition Documentation

◆ CAN_EXT_ID_MAX

#define CAN_EXT_ID_MAX   0x1FFFFFFF

◆ CAN_STD_ID_MAX

#define CAN_STD_ID_MAX   0x7FF

◆ FIFO_FULL_BLOCK_TIMEOUT

#define FIFO_FULL_BLOCK_TIMEOUT   pdTICKS_TO_MS(25)

◆ MS_PER_S

#define MS_PER_S   1000

◆ MSG_RX_NOTIF_IDX

#define MSG_RX_NOTIF_IDX   0

◆ MSG_TX_NOTIF_IDX

#define MSG_TX_NOTIF_IDX   0

◆ TIMESTAMP_PRESCALER

#define TIMESTAMP_PRESCALER   16U

◆ TIMESTAMP_PRESCALER_HAL

#define TIMESTAMP_PRESCALER_HAL   FDCAN_TIMESTAMP_PRESC_16

Function Documentation

◆ can_error_status_callback()

void can_error_status_callback ( FDCAN_HandleTypeDef * hfdcan,
uint32_t error_status_its )
static
Parameters
hfdcan
error_status_its
Here is the call graph for this function:
Here is the caller graph for this function:

◆ can_rx_pending_callback()

void can_rx_pending_callback ( FDCAN_HandleTypeDef * hfdcan,
uint32_t rx_its )
static

CAN message receive pending ISR. Unblocks the CAN receive task for the bus/peripheral through a direct-to-task notification.

Registered through HAL in canlib_rx_task_init() Called when a new CAN message is received and stored in the hardware Rx FIFO

Parameters
hfdcanFDCAN peripheral triggering the message pending IRQ
rx_its(unused, but part of the HAL callback function signature)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ can_rx_wraparound_callback()

void can_rx_wraparound_callback ( FDCAN_HandleTypeDef * hfdcan)
static

FDCAN peripheral timestamp counter wraparound ISR. Increments the timestamp_ovf_since_last_rx field for each tracked message for the peripheral/task.

Registered through HAL in canlib_register_timeout_ids() This means for a message that's timed out, we'll get a false negative every ~2 days rather than every ~2 seconds

Parameters
hfdcanFDCAN peripheral triggering the timestamp counter wraparound IRQ
Here is the call graph for this function:
Here is the caller graph for this function:

◆ can_tx_cplt_callback()

void can_tx_cplt_callback ( FDCAN_HandleTypeDef * hfdcan,
uint32_t buffer_idxs )
static

CAN message transmit complete ISR. Unblocks the CAN transmit task for the bus/peripheral through a direct-to-task notification if the task is waiting for free space the hardware Tx FIFO.

Registered through HAL in canlib_tx_task_init() Called when a CAN message is successfully transmitted

Parameters
hfdcanFDCAN peripheral triggering the transmit complete IRQ
buffer_idxs(unused, but part of the HAL callback function signature)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ can_tx_periodic_msg_callback()

void can_tx_periodic_msg_callback ( TimerHandle_t timer_hdl)
static

Scheduled CAN message FreeRTOS timer callback. Timer created and started in canlib_register_scheduled_msgs()

Parameters
timer_hdlFreeRTOS timer handle. The timer ID points to the canlib_scheduled_msg_params struct for this set of periodic messages
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_bus()

__always_inline enum can_bus get_bus ( FDCAN_HandleTypeDef * hfdcan)
static

Gets the CAN bus associated with an FDCAN peripheral.

Returns
CAN bus (or -1 if the FDCAN handle pointer is NULL or isn't associated with a bus)
Here is the caller graph for this function:

◆ get_hfdcan()

__always_inline FDCAN_HandleTypeDef * get_hfdcan ( enum can_bus bus)
static

Gets the FDCAN peripheral associated with a CAN bus.

Returns
FDCAN peripheral handle pointer (or NULL if the specified bus is invalid or not configured)
Here is the caller graph for this function:

◆ insertion_sort()

void insertion_sort ( uint32_t arr_ptr[],
unsigned length )
static

Sorts a uint32_t array in ascending order.

Used to sort CAN IDs for timeout checks during initialization RIP CAN library quicksort 2025-2025 :(

Parameters
arr_ptrArray to sort
lengthLength of array
Here is the caller graph for this function:

◆ task_can_rx()

void task_can_rx ( void * task_params_ptr)
static

Implements the CAN receive task.

Parameters
task_params_ptrPointer to the CAN receive task parameter struct

This task is scheduled when a CAN message is received by an enabled FDCAN peripheral. It reads pending messages from the hardware FIFO queue for the peripheral and calls th

Here is the call graph for this function:
Here is the caller graph for this function:

◆ task_can_tx()

void task_can_tx ( void * task_params_ptr)
static

Implements the CAN transmit task.

Parameters
task_params_ptrPointer to the CAN transmit task parameter struct

This task is scheduled whenever there are pending messages in the transmit queue. It sends messages on the correct CAN bus and handles full FIFO queues and other hardware errors (bus disconnected, etc.)

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_msg_timeout()

void update_msg_timeout ( struct can_rx_params * params_ptr,
uint32_t msg_id,
uint16_t rx_timestamp )
static

Updates the timeout timestamp for a CAN ID. Called after a message is received by the CAN receive task.

Parameters
params_ptrCAN receive task parameter struct
msg_idTarget CAN ID
rx_timestampTimestamp (captured by FDCAN peripheral at SOF, units of TIMESTAMP_PRESCALER * nominal bit time)
Here is the caller graph for this function:

Variable Documentation

◆ g_can_rx_hdls

TaskHandle_t g_can_rx_hdls[CAN_BUS_CNT]
static

◆ g_can_rx_params

struct can_rx_params g_can_rx_params[CAN_BUS_CNT]
static

◆ g_can_tx_hdls

TaskHandle_t g_can_tx_hdls[CAN_BUS_CNT]
static

◆ g_can_tx_params

struct can_tx_params g_can_tx_params[CAN_BUS_CNT]
static