/** * @ingroup can * @defgroup can_frame Frame pooling * @brief RX frame pooling * @date Oct 29, 2015 * @author jjacobs * @copyright 2015 Dual Inventive Technology Centre B.V. * * CAN frame pooling * @{ */ #ifndef LIBDI_INCLUDE_DI_CAN_FRAME_H_ #define LIBDI_INCLUDE_DI_CAN_FRAME_H_ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include struct di_can_ctx; /** Declare di_can_msg array */ #define DI_CAN_FRAME_RX_DECL_ARRAY(name, elements) \ static struct di_can_frame_rx name[elements] /** CAN-bus frame */ struct di_can_frame_tx { size_t size; uint32_t canid; uint8_t *buf; const struct di_can_ctx *ctx; /** DI CAN context */ }; /** CAN-bus RX frame */ struct di_can_frame_rx { uint64_t timeout; /**< Timeout for GC in milliseconds since di_time_get_uptime() */ uint16_t flags; size_t size; uint32_t canid; uint8_t buf[8]; const struct di_can_ctx *ctx; /**< DI CAN context */ }; /** * CAN frame subsystem */ struct di_can_frame { di_bsem_t lock; struct di_array pool; uint32_t timeout; /**< Garbage collection timeout of frames (milliseconds) */ }; #include /** * Initialize can frame subsystem * @param ctx CAN context * @param list List of can rx frames * @param size Elements of can rx frames in list * @note When the subsystem is already initialized next function calls will be ignored */ void di_can_frame_init(struct di_can_ctx *ctx, struct di_can_frame_rx *list, size_t size); /** * Get unused can frame */ struct di_can_frame_rx *di_can_frame_get_unused(struct di_can_ctx *ctx); /** * Get used + ready can frame for reassembly of message */ struct di_can_frame_rx *di_can_frame_get_ready(struct di_can_ctx *ctx); /** * Return can frame to notify it is ready */ void di_can_frame_return_ready(struct di_can_frame_rx *frame); /** * Destroy and return the can frame so it is free */ void di_can_frame_return_unused(struct di_can_frame_rx *frame); /** * Garbage collect where di_can_frame_rx timeouts are exceeded * This will use the di_time_get_uptime to test against * the message timeout * * When di_can_frame_rx.timeout is set to DI_CAN_TIMEOUT_GC_SKIP it is not garbage collected * * When di_can_frame_rx.timeout is set to DI_CAN_TIMEOUT_GC_IMMEDIATE it is immediate collected * @note This should be run with ~50ms interval from thread with all being freed up */ void di_can_frame_gc(struct di_can_ctx *ctx, enum di_can_gc gc); /** * Get application specific private_data set with * di_can_set_private_data */ void *di_can_frame_rx_get_private_data(const struct di_can_frame_rx *frame); void *di_can_frame_tx_get_private_data(const struct di_can_frame_tx *frame); #ifdef __cplusplus } #endif /** @} */ #endif /* LIBDI_INCLUDE_DI_CAN_FRAME_H_ */