123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977 |
- /**
- * @file
- *
- * @brief Public APIs for the CAN drivers.
- */
- /*
- * Copyright (c) 2018 Alexander Wachter
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- #ifndef ZEPHYR_INCLUDE_DRIVERS_CAN_H_
- #define ZEPHYR_INCLUDE_DRIVERS_CAN_H_
- /**
- * @brief CAN Interface
- * @defgroup can_interface CAN Interface
- * @ingroup io_interfaces
- * @{
- */
- #include <zephyr/types.h>
- #include <device.h>
- #include <string.h>
- #include <sys/util.h>
- #ifdef __cplusplus
- extern "C" {
- #endif
- #define CAN_EX_ID (1 << 31)
- #define CAN_MAX_STD_ID (0x7FF)
- #define CAN_STD_ID_MASK CAN_MAX_STD_ID
- #define CAN_EXT_ID_MASK (0x1FFFFFFF)
- #define CAN_MAX_DLC (8)
- #define CANFD_MAX_DLC CONFIG_CANFD_MAX_DLC
- #ifndef CONFIG_CANFD_MAX_DLC
- #define CAN_MAX_DLEN 8
- #else
- #if CONFIG_CANFD_MAX_DLC <= 8
- #define CAN_MAX_DLEN CONFIG_CANFD_MAX_DLC
- #elif CONFIG_CANFD_MAX_DLC <= 12
- #define CAN_MAX_DLEN CONFIG_CANFD_MAX_DLC + (CONFIG_CANFD_MAX_DLC - 8) * 4
- #elif CONFIG_CANFD_MAX_DLC == 13
- #define CAN_MAX_DLEN 32
- #elif CONFIG_CANFD_MAX_DLC == 14
- #define CAN_MAX_DLEN 48
- #elif CONFIG_CANFD_MAX_DLC == 15
- #define CAN_MAX_DLEN 64
- #endif
- #endif /* CONFIG_CANFD_MAX_DLC */
- /* CAN_TX_* are the error flags from tx_callback and send.*/
- /** send successfully */
- #define CAN_TX_OK (0)
- /** general send error */
- #define CAN_TX_ERR (-2)
- /** bus arbitration lost during sending */
- #define CAN_TX_ARB_LOST (-3)
- /** controller is in bus off state */
- #define CAN_TX_BUS_OFF (-4)
- /** unexpected error */
- #define CAN_TX_UNKNOWN (-5)
- /** invalid parameter */
- #define CAN_TX_EINVAL (-22)
- /** attach_* failed because there is no unused filter left*/
- #define CAN_NO_FREE_FILTER (-1)
- /** operation timed out*/
- #define CAN_TIMEOUT (-1)
- /**
- * @brief Statically define and initialize a can message queue.
- *
- * The message queue's ring buffer contains space for @a size messages.
- *
- * @param name Name of the message queue.
- * @param size Number of can messages.
- */
- #define CAN_DEFINE_MSGQ(name, size) \
- K_MSGQ_DEFINE(name, sizeof(struct zcan_frame), size, 4)
- /**
- * @brief can_ide enum
- * Define if the message has a standard (11bit) or extended (29bit)
- * identifier
- */
- enum can_ide {
- CAN_STANDARD_IDENTIFIER,
- CAN_EXTENDED_IDENTIFIER
- };
- /**
- * @brief can_rtr enum
- * Define if the message is a data or remote frame
- */
- enum can_rtr {
- CAN_DATAFRAME,
- CAN_REMOTEREQUEST
- };
- /**
- * @brief can_mode enum
- * Defines the mode of the can controller
- */
- enum can_mode {
- /*Normal mode*/
- CAN_NORMAL_MODE,
- /*Controller is not allowed to send dominant bits*/
- CAN_SILENT_MODE,
- /*Controller is in loopback mode (receive own messages)*/
- CAN_LOOPBACK_MODE,
- /*Combination of loopback and silent*/
- CAN_SILENT_LOOPBACK_MODE
- };
- /**
- * @brief can_state enum
- * Defines the possible states of the CAN bus
- */
- enum can_state {
- CAN_ERROR_ACTIVE,
- CAN_ERROR_PASSIVE,
- CAN_BUS_OFF,
- CAN_BUS_UNKNOWN
- };
- /*
- * Controller Area Network Identifier structure for Linux compatibility.
- *
- * The fields in this type are:
- *
- * bit 0-28 : CAN identifier (11/29 bit)
- * bit 29 : error message frame flag (0 = data frame, 1 = error message)
- * bit 30 : remote transmission request flag (1 = rtr frame)
- * bit 31 : frame format flag (0 = standard 11 bit, 1 = extended 29 bit)
- */
- typedef uint32_t canid_t;
- /**
- * @brief CAN frame structure that is compatible with Linux. This is mainly
- * used by Socket CAN code.
- *
- * @details Used to pass CAN messages from userspace to the socket CAN and vice
- * versa.
- */
- struct can_frame {
- /** 32 bit CAN_ID + EFF/RTR/ERR flags */
- canid_t can_id;
- /** The length of the message */
- uint8_t can_dlc;
- /** @cond INTERNAL_HIDDEN */
- uint8_t pad; /* padding */
- uint8_t res0; /* reserved / padding */
- uint8_t res1; /* reserved / padding */
- /** @endcond */
- /** The message data */
- uint8_t data[CAN_MAX_DLEN];
- };
- /**
- * @brief CAN filter that is compatible with Linux. This is mainly used by
- * Socket CAN code.
- *
- * @details A filter matches, when "received_can_id & mask == can_id & mask"
- */
- struct can_filter {
- canid_t can_id;
- canid_t can_mask;
- };
- /**
- * @brief CAN message structure
- *
- * Used to pass can messages from userspace to the driver and
- * from driver to userspace
- *
- */
- struct zcan_frame {
- /** Message identifier*/
- uint32_t id : 29;
- /** Frame is in the CAN-FD frame format */
- uint32_t fd : 1;
- /** Set the message to a transmission request instead of data frame
- * use can_rtr enum for assignment
- */
- uint32_t rtr : 1;
- /** Indicates the identifier type (standard or extended)
- * use can_ide enum for assignment
- */
- uint32_t id_type : 1;
- /** The length of the message (max. 8) in byte */
- uint8_t dlc;
- /** Baud Rate Switch. Frame transfer with different timing during
- * the data phase. Only valid for CAN-FD
- */
- uint8_t brs : 1;
- /** Reserved for future flags */
- uint8_t res : 7;
- #if defined(CONFIG_CAN_RX_TIMESTAMP)
- /** Timer value of the CAN free-running timer.
- * The timer is incremented every bit time and captured at the start
- * of frame bit (SOF).
- */
- uint16_t timestamp;
- #else
- /** @cond INTERNAL_HIDDEN */
- uint8_t res0; /* reserved / padding */
- uint8_t res1; /* reserved / padding */
- /** @endcond */
- #endif
- /** The frame payload data. */
- union {
- uint8_t data[CAN_MAX_DLEN];
- uint32_t data_32[ceiling_fraction(CAN_MAX_DLEN, sizeof(uint32_t))];
- };
- };
- /**
- * @brief CAN filter structure
- *
- * Used to pass can identifier filter information to the driver.
- * rtr_mask and *_id_mask are used to mask bits of the rtr and id fields.
- * If the mask bit is 0, the value of the corresponding bit in the id or rtr
- * field don't care for the filter matching.
- *
- */
- struct zcan_filter {
- /** target state of the identifier */
- uint32_t id : 29;
- uint32_t res0 : 1;
- /** target state of the rtr bit */
- uint32_t rtr : 1;
- /** Indicates the identifier type (standard or extended)
- * use can_ide enum for assignment
- */
- uint32_t id_type : 1;
- /** identifier mask*/
- uint32_t id_mask : 29;
- uint32_t res1 : 1;
- /** rtr bit mask */
- uint32_t rtr_mask : 1;
- uint32_t res2 : 1;
- };
- /**
- * @brief can bus error count structure
- *
- * Used to pass the bus error counters to userspace
- */
- struct can_bus_err_cnt {
- uint8_t tx_err_cnt;
- uint8_t rx_err_cnt;
- };
- /** SWJ value to indicate that the SJW should not be changed */
- #define CAN_SJW_NO_CHANGE 0
- /**
- * @brief canbus timings
- *
- * Used to pass bus timing values to the config and bitrate calculator function.
- *
- * The propagation segment represents the time of the signal propagation.
- * Phase segment 1 and phase segment 2 define the sampling point.
- * prop_seg and phase_seg1 affect the sampling-point in the same way and some
- * controllers only have a register for the sum of those two. The sync segment
- * always has a length of 1 tq
- * +---------+----------+------------+------------+
- * |sync_seg | prop_seg | phase_seg1 | phase_seg2 |
- * +---------+----------+------------+------------+
- * ^
- * Sampling-Point
- * 1 tq (time quantum) has the length of 1/(core_clock / prescaler)
- * The bitrate is defined by the core clock divided by the prescaler and the
- * sum of the segments.
- * br = (core_clock / prescaler) / (1 + prop_seg + phase_seg1 + phase_seg2)
- * The resynchronization jump width (SJW) defines the amount of time quantum
- * the sample point can be moved.
- * The sample point is moved when resynchronization is needed.
- */
- struct can_timing {
- /** Synchronisation jump width*/
- uint16_t sjw;
- /** Propagation Segment */
- uint16_t prop_seg;
- /** Phase Segment 1 */
- uint16_t phase_seg1;
- /** Phase Segment 2 */
- uint16_t phase_seg2;
- /** Prescaler value */
- uint16_t prescaler;
- };
- /**
- * @typedef can_tx_callback_t
- * @brief Define the application callback handler function signature
- *
- * @param error_flags status of the performed send operation
- * @param arg argument that was passed when the message was sent
- */
- typedef void (*can_tx_callback_t)(uint32_t error_flags, void *arg);
- /**
- * @typedef can_rx_callback_t
- * @brief Define the application callback handler function signature
- * for receiving.
- *
- * @param msg received message
- * @param arg argument that was passed when the filter was attached
- */
- typedef void (*can_rx_callback_t)(struct zcan_frame *msg, void *arg);
- /**
- * @typedef can_state_change_isr_t
- * @brief Defines the state change isr handler function signature
- *
- * @param state state of the node
- * @param err_cnt struct with the error counter values
- */
- typedef void(*can_state_change_isr_t)(enum can_state state,
- struct can_bus_err_cnt err_cnt);
- typedef int (*can_set_timing_t)(const struct device *dev,
- const struct can_timing *timing,
- const struct can_timing *timing_data);
- typedef int (*can_set_mode_t)(const struct device *dev, enum can_mode mode);
- typedef int (*can_send_t)(const struct device *dev,
- const struct zcan_frame *msg,
- k_timeout_t timeout, can_tx_callback_t callback_isr,
- void *callback_arg);
- typedef int (*can_attach_msgq_t)(const struct device *dev,
- struct k_msgq *msg_q,
- const struct zcan_filter *filter);
- typedef int (*can_attach_isr_t)(const struct device *dev,
- can_rx_callback_t isr,
- void *callback_arg,
- const struct zcan_filter *filter);
- typedef void (*can_detach_t)(const struct device *dev, int filter_id);
- typedef int (*can_recover_t)(const struct device *dev, k_timeout_t timeout);
- typedef enum can_state (*can_get_state_t)(const struct device *dev,
- struct can_bus_err_cnt *err_cnt);
- typedef void(*can_register_state_change_isr_t)(const struct device *dev,
- can_state_change_isr_t isr);
- typedef int (*can_get_core_clock_t)(const struct device *dev, uint32_t *rate);
- #ifndef CONFIG_CAN_WORKQ_FRAMES_BUF_CNT
- #define CONFIG_CAN_WORKQ_FRAMES_BUF_CNT 4
- #endif
- struct can_frame_buffer {
- struct zcan_frame buf[CONFIG_CAN_WORKQ_FRAMES_BUF_CNT];
- uint16_t head;
- uint16_t tail;
- };
- /**
- * @brief CAN work structure
- *
- * Used to attach a work queue to a filter.
- */
- struct zcan_work {
- struct k_work work_item;
- struct k_work_q *work_queue;
- struct can_frame_buffer buf;
- can_rx_callback_t cb;
- void *cb_arg;
- };
- __subsystem struct can_driver_api {
- can_set_mode_t set_mode;
- can_set_timing_t set_timing;
- can_send_t send;
- can_attach_isr_t attach_isr;
- can_detach_t detach;
- #ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
- can_recover_t recover;
- #endif
- can_get_state_t get_state;
- can_register_state_change_isr_t register_state_change_isr;
- can_get_core_clock_t get_core_clock;
- /* Min values for the timing registers */
- struct can_timing timing_min;
- /* Max values for the timing registers */
- struct can_timing timing_max;
- #ifdef CONFIG_CAN_FD_MODE
- /* Min values for the timing registers during the data phase */
- struct can_timing timing_min_data;
- /* Max values for the timing registers during the data phase */
- struct can_timing timing_max_data;
- #endif
- };
- /**
- * @brief Convert the DLC to the number of bytes
- *
- * This function converts a the Data Length Code to the number of bytes.
- *
- * @param dlc The Data Length Code
- *
- * @retval Number of bytes
- */
- static inline uint8_t can_dlc_to_bytes(uint8_t dlc)
- {
- static const uint8_t dlc_table[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 12,
- 16, 20, 24, 32, 48, 64};
- return dlc > 0x0F ? 64 : dlc_table[dlc];
- }
- /**
- * @brief Convert a number of bytes to the DLC
- *
- * This function converts a number of bytes to the Data Length Code
- *
- * @param num_bytes The number of bytes
- *
- * @retval The DLC
- */
- static inline uint8_t can_bytes_to_dlc(uint8_t num_bytes)
- {
- return num_bytes <= 8 ? num_bytes :
- num_bytes <= 12 ? 9 :
- num_bytes <= 16 ? 10 :
- num_bytes <= 20 ? 11 :
- num_bytes <= 24 ? 12 :
- num_bytes <= 32 ? 13 :
- num_bytes <= 48 ? 14 :
- 15;
- }
- /**
- * @brief Perform data transfer to CAN bus.
- *
- * This routine provides a generic interface to perform data transfer
- * to the can bus. Use can_write() for simple write.
- * *
- * @param dev Pointer to the device structure for the driver instance.
- * @param msg Message to transfer.
- * @param timeout Waiting for empty tx mailbox timeout or K_FOREVER.
- * @param callback_isr Is called when message was sent or a transmission error
- * occurred. If NULL, this function is blocking until
- * message is sent. This must be NULL if called from user
- * mode.
- * @param callback_arg This will be passed whenever the isr is called.
- *
- * @retval 0 If successful.
- * @retval CAN_TX_* on failure.
- */
- __syscall int can_send(const struct device *dev, const struct zcan_frame *msg,
- k_timeout_t timeout, can_tx_callback_t callback_isr,
- void *callback_arg);
- static inline int z_impl_can_send(const struct device *dev,
- const struct zcan_frame *msg,
- k_timeout_t timeout,
- can_tx_callback_t callback_isr,
- void *callback_arg)
- {
- const struct can_driver_api *api =
- (const struct can_driver_api *)dev->api;
- return api->send(dev, msg, timeout, callback_isr, callback_arg);
- }
- /*
- * Derived can APIs -- all implemented in terms of can_send()
- */
- /**
- * @brief Write a set amount of data to the can bus.
- *
- * This routine writes a set amount of data synchronously.
- *
- * @param dev Pointer to the device structure for the driver instance.
- * @param data Data to send.
- * @param length Number of bytes to write (max. 8).
- * @param id Identifier of the can message.
- * @param rtr Send remote transmission request or data frame
- * @param timeout Waiting for empty tx mailbox timeout or K_FOREVER
- *
- * @retval 0 If successful.
- * @retval -EIO General input / output error.
- * @retval -EINVAL if length > 8.
- */
- static inline int can_write(const struct device *dev, const uint8_t *data,
- uint8_t length,
- uint32_t id, enum can_rtr rtr, k_timeout_t timeout)
- {
- struct zcan_frame msg;
- if (length > 8) {
- return -EINVAL;
- }
- msg.id = id;
- if (id > CAN_MAX_STD_ID) {
- msg.id_type = CAN_EXTENDED_IDENTIFIER;
- } else {
- msg.id_type = CAN_STANDARD_IDENTIFIER;
- }
- msg.dlc = length;
- msg.rtr = rtr;
- memcpy(msg.data, data, length);
- return can_send(dev, &msg, timeout, NULL, NULL);
- }
- /**
- * @brief Attach a CAN work queue to a single or group of identifiers.
- *
- * This routine attaches a work queue to identifiers specified by a filter.
- * Whenever the filter matches, the message is pushed to the buffer
- * of the zcan_work structure and the work element is put to the workqueue.
- * If a message passes more than one filter the priority of the match
- * is hardware dependent.
- * A CAN work queue can be attached to more than one filter.
- * The work queue must be initialized before and the caller must have
- * appropriate permissions on it.
- *
- * @param dev Pointer to the device structure for the driver instance.
- * @param work_q Pointer to the already initialized work queue.
- * @param work Pointer to a zcan_work. The work will be initialized.
- * @param callback This function is called by workq whenever a message arrives.
- * @param callback_arg Is passed to the callback when called.
- * @param filter Pointer to a zcan_filter structure defining the id
- * filtering.
- *
- * @retval filter_id on success.
- * @retval CAN_NO_FREE_FILTER if there is no filter left.
- */
- int can_attach_workq(const struct device *dev, struct k_work_q *work_q,
- struct zcan_work *work,
- can_rx_callback_t callback, void *callback_arg,
- const struct zcan_filter *filter);
- /**
- * @brief Attach a message queue to a single or group of identifiers.
- *
- * This routine attaches a message queue to identifiers specified by
- * a filter. Whenever the filter matches, the message is pushed to the queue
- * If a message passes more than one filter the priority of the match
- * is hardware dependent.
- * A message queue can be attached to more than one filter.
- * The message queue must me initialized before, and the caller must have
- * appropriate permissions on it.
- *
- * @param dev Pointer to the device structure for the driver instance.
- * @param msg_q Pointer to the already initialized message queue.
- * @param filter Pointer to a zcan_filter structure defining the id
- * filtering.
- *
- * @retval filter_id on success.
- * @retval CAN_NO_FREE_FILTER if there is no filter left.
- */
- __syscall int can_attach_msgq(const struct device *dev, struct k_msgq *msg_q,
- const struct zcan_filter *filter);
- /**
- * @brief Attach an isr callback function to a single or group of identifiers.
- *
- * This routine attaches an isr callback to identifiers specified by
- * a filter. Whenever the filter matches, the callback function is called
- * with isr context.
- * If a message passes more than one filter the priority of the match
- * is hardware dependent.
- * A callback function can be attached to more than one filter.
- * *
- * @param dev Pointer to the device structure for the driver instance.
- * @param isr Callback function pointer.
- * @param callback_arg This will be passed whenever the isr is called.
- * @param filter Pointer to a zcan_filter structure defining the id
- * filtering.
- *
- * @retval filter_id on success.
- * @retval CAN_NO_FREE_FILTER if there is no filter left.
- */
- static inline int can_attach_isr(const struct device *dev,
- can_rx_callback_t isr,
- void *callback_arg,
- const struct zcan_filter *filter)
- {
- const struct can_driver_api *api =
- (const struct can_driver_api *)dev->api;
- return api->attach_isr(dev, isr, callback_arg, filter);
- }
- /**
- * @brief Detach an isr or message queue from the identifier filtering.
- *
- * This routine detaches an isr callback or message queue from the identifier
- * filtering.
- * *
- * @param dev Pointer to the device structure for the driver instance.
- * @param filter_id filter id returned by can_attach_isr or can_attach_msgq.
- *
- * @retval none
- */
- __syscall void can_detach(const struct device *dev, int filter_id);
- static inline void z_impl_can_detach(const struct device *dev, int filter_id)
- {
- const struct can_driver_api *api =
- (const struct can_driver_api *)dev->api;
- return api->detach(dev, filter_id);
- }
- /**
- * @brief Read the core clock value
- *
- * Returns the core clock value. One time quantum is 1/core clock.
- *
- * @param dev Pointer to the device structure for the driver instance.
- * @param[out] rate controller clock rate
- *
- * @retval 0 on success
- * @retval negative on error
- */
- __syscall int can_get_core_clock(const struct device *dev, uint32_t *rate);
- static inline int z_impl_can_get_core_clock(const struct device *dev,
- uint32_t *rate)
- {
- const struct can_driver_api *api =
- (const struct can_driver_api *)dev->api;
- return api->get_core_clock(dev, rate);
- }
- /**
- * @brief Calculate timing parameters from bitrate and sample point
- *
- * Calculate the timing parameters from a given bitrate in bits/s and the
- * sampling point in permill (1/1000) of the entire bit time.
- * The bitrate must alway match perfectly. If no result can be given for the,
- * give parameters, -EINVAL is returned.
- * The sample_pnt does not always match perfectly. The algorithm tries to find
- * the best match possible.
- *
- * @param dev Pointer to the device structure for the driver instance.
- * @param res Result is written into the can_timing struct provided.
- * @param bitrate Target bitrate in bits/s
- * @param sample_pnt Sampling point in permill of the entire bit time.
- *
- * @retval Positive sample point error on success
- * @retval -EINVAL if there is no solution for the desired values
- * @retval -EIO if core_clock is not available
- */
- int can_calc_timing(const struct device *dev, struct can_timing *res,
- uint32_t bitrate, uint16_t sample_pnt);
- #ifdef CONFIG_CAN_FD_MODE
- /**
- * @brief Calculate timing parameters for the data phase
- *
- * Same as can_calc_timing but with the max and min values from the data phase.
- *
- * @param dev Pointer to the device structure for the driver instance.
- * @param res Result is written into the can_timing struct provided.
- * @param bitrate Target bitrate for the data phase in bits/s
- * @param sample_pnt Sampling point data phase in permille of the entire bit time.
- *
- * @retval Positive sample point error on success
- * @retval -EINVAL if there is no solution for the desired values
- * @retval -EIO if core_clock is not available
- */
- int can_calc_timing_data(const struct device *dev, struct can_timing *res,
- uint32_t bitrate, uint16_t sample_pnt);
- #endif
- /**
- * @brief Fill in the prescaler value for a given bitrate and timing
- *
- * Fill the prescaler value in the timing struct.
- * sjw, prop_seg, phase_seg1 and phase_seg2 must be given.
- * The returned bitrate error is reminder of the devision of the clockrate by
- * the bitrate times the timing segments.
- *
- * @param dev Pointer to the device structure for the driver instance.
- * @param timing Result is written into the can_timing struct provided.
- * @param bitrate Target bitrate.
- *
- * @retval bitrate error
- * @retval negative on error
- */
- int can_calc_prescaler(const struct device *dev, struct can_timing *timing,
- uint32_t bitrate);
- /**
- * @brief Set the controller to the given mode
- *
- * @param dev Pointer to the device structure for the driver instance.
- * @param mode Operation mode
- *
- * @retval 0 If successful.
- * @retval -EIO General input / output error, failed to configure device.
- */
- __syscall int can_set_mode(const struct device *dev, enum can_mode mode);
- static inline int z_impl_can_set_mode(const struct device *dev,
- enum can_mode mode)
- {
- const struct can_driver_api *api =
- (const struct can_driver_api *)dev->api;
- return api->set_mode(dev, mode);
- }
- /**
- * @brief Configure timing of a host controller.
- *
- * If the sjw equals CAN_SJW_NO_CHANGE, the sjw parameter is not changed.
- *
- * The second parameter timing_data is only relevant for CAN-FD.
- * If the controller does not support CAN-FD or the FD mode is not enabled,
- * this parameter is ignored.
- *
- * @param dev Pointer to the device structure for the driver instance.
- * @param timing Bus timings
- * @param timing_data Bus timings for data phase (CAN-FD only)
- *
- * @retval 0 If successful.
- * @retval -EIO General input / output error, failed to configure device.
- */
- __syscall int can_set_timing(const struct device *dev,
- const struct can_timing *timing,
- const struct can_timing *timing_data);
- static inline int z_impl_can_set_timing(const struct device *dev,
- const struct can_timing *timing,
- const struct can_timing *timing_data)
- {
- const struct can_driver_api *api =
- (const struct can_driver_api *)dev->api;
- return api->set_timing(dev, timing, timing_data);
- }
- /**
- * @brief Set the bitrate of the CAN controller
- *
- * The second parameter bitrate_data is only relevant for CAN-FD.
- * If the controller does not support CAN-FD or the FD mode is not enabled,
- * this parameter is ignored.
- * The sample point is set to the CiA DS 301 reccommended value of 87.5%
- *
- * @param dev Pointer to the device structure for the driver instance.
- * @param bitrate Desired arbitration phase bitrate
- * @param bitrate_data Desired data phase bitrate
- *
- * @retval 0 If successful.
- * @retval -EINVAL bitrate cannot be reached.
- * @retval -EIO General input / output error, failed to set bitrate.
- */
- static inline int can_set_bitrate(const struct device *dev,
- uint32_t bitrate,
- uint32_t bitrate_data)
- {
- struct can_timing timing;
- #ifdef CONFIG_CAN_FD_MODE
- struct can_timing timing_data;
- #endif
- int ret;
- ret = can_calc_timing(dev, &timing, bitrate, 875);
- if (ret < 0) {
- return -EINVAL;
- }
- timing.sjw = CAN_SJW_NO_CHANGE;
- #ifdef CONFIG_CAN_FD_MODE
- ret = can_calc_timing_data(dev, &timing_data, bitrate_data, 875);
- if (ret < 0) {
- return -EINVAL;
- }
- timing_data.sjw = CAN_SJW_NO_CHANGE;
- return can_set_timing(dev, &timing, &timing_data);
- #else
- return can_set_timing(dev, &timing, NULL);
- #endif /* CONFIG_CAN_FD_MODE */
- }
- /**
- * @brief Configure operation of a host controller.
- *
- * @param dev Pointer to the device structure for the driver instance.
- * @param mode Operation mode
- * @param bitrate bus-speed in Baud/s
- *
- * @retval 0 If successful.
- * @retval -EIO General input / output error, failed to configure device.
- */
- static inline int can_configure(const struct device *dev, enum can_mode mode,
- uint32_t bitrate)
- {
- if (bitrate > 0) {
- int err = can_set_bitrate(dev, bitrate, 0);
- if (err != 0) {
- return err;
- }
- }
- return can_set_mode(dev, mode);
- }
- /**
- * @brief Get current state
- *
- * Returns the actual state of the CAN controller.
- *
- * @param dev Pointer to the device structure for the driver instance.
- * @param err_cnt Pointer to the err_cnt destination structure or NULL.
- *
- * @retval state
- */
- __syscall enum can_state can_get_state(const struct device *dev,
- struct can_bus_err_cnt *err_cnt);
- static inline
- enum can_state z_impl_can_get_state(const struct device *dev,
- struct can_bus_err_cnt *err_cnt)
- {
- const struct can_driver_api *api =
- (const struct can_driver_api *)dev->api;
- return api->get_state(dev, err_cnt);
- }
- /**
- * @brief Recover from bus-off state
- *
- * Recover the CAN controller from bus-off state to error-active state.
- *
- * @param dev Pointer to the device structure for the driver instance.
- * @param timeout Timeout for waiting for the recovery or K_FOREVER.
- *
- * @retval 0 on success.
- * @retval CAN_TIMEOUT on timeout.
- */
- #ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
- __syscall int can_recover(const struct device *dev, k_timeout_t timeout);
- static inline int z_impl_can_recover(const struct device *dev,
- k_timeout_t timeout)
- {
- const struct can_driver_api *api =
- (const struct can_driver_api *)dev->api;
- return api->recover(dev, timeout);
- }
- #else
- /* This implementation prevents inking errors for auto recovery */
- static inline int z_impl_can_recover(const struct device *dev,
- k_timeout_t timeout)
- {
- return 0;
- }
- #endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
- /**
- * @brief Register an ISR callback for state change interrupt
- *
- * Only one callback can be registered per controller.
- * Calling this function again, overrides the previous call.
- *
- * @param dev Pointer to the device structure for the driver instance.
- * @param isr Pointer to ISR
- */
- static inline
- void can_register_state_change_isr(const struct device *dev,
- can_state_change_isr_t isr)
- {
- const struct can_driver_api *api =
- (const struct can_driver_api *)dev->api;
- return api->register_state_change_isr(dev, isr);
- }
- /**
- * @brief Converter that translates between can_frame and zcan_frame structs.
- *
- * @param frame Pointer to can_frame struct.
- * @param zframe Pointer to zcan_frame struct.
- */
- static inline void can_copy_frame_to_zframe(const struct can_frame *frame,
- struct zcan_frame *zframe)
- {
- zframe->id_type = (frame->can_id & BIT(31)) >> 31;
- zframe->rtr = (frame->can_id & BIT(30)) >> 30;
- zframe->id = frame->can_id & BIT_MASK(29);
- zframe->dlc = frame->can_dlc;
- memcpy(zframe->data, frame->data, sizeof(zframe->data));
- }
- /**
- * @brief Converter that translates between zcan_frame and can_frame structs.
- *
- * @param zframe Pointer to zcan_frame struct.
- * @param frame Pointer to can_frame struct.
- */
- static inline void can_copy_zframe_to_frame(const struct zcan_frame *zframe,
- struct can_frame *frame)
- {
- frame->can_id = (zframe->id_type << 31) | (zframe->rtr << 30) |
- zframe->id;
- frame->can_dlc = zframe->dlc;
- memcpy(frame->data, zframe->data, sizeof(frame->data));
- }
- /**
- * @brief Converter that translates between can_filter and zcan_frame_filter
- * structs.
- *
- * @param filter Pointer to can_filter struct.
- * @param zfilter Pointer to zcan_frame_filter struct.
- */
- static inline
- void can_copy_filter_to_zfilter(const struct can_filter *filter,
- struct zcan_filter *zfilter)
- {
- zfilter->id_type = (filter->can_id & BIT(31)) >> 31;
- zfilter->rtr = (filter->can_id & BIT(30)) >> 30;
- zfilter->id = filter->can_id & BIT_MASK(29);
- zfilter->rtr_mask = (filter->can_mask & BIT(30)) >> 30;
- zfilter->id_mask = filter->can_mask & BIT_MASK(29);
- }
- /**
- * @brief Converter that translates between zcan_filter and can_filter
- * structs.
- *
- * @param zfilter Pointer to zcan_filter struct.
- * @param filter Pointer to can_filter struct.
- */
- static inline
- void can_copy_zfilter_to_filter(const struct zcan_filter *zfilter,
- struct can_filter *filter)
- {
- filter->can_id = (zfilter->id_type << 31) |
- (zfilter->rtr << 30) | zfilter->id;
- filter->can_mask = (zfilter->rtr_mask << 30) |
- (zfilter->id_type << 31) | zfilter->id_mask;
- }
- #ifdef __cplusplus
- }
- #endif
- /**
- * @}
- */
- #include <syscalls/can.h>
- #endif /* ZEPHYR_INCLUDE_DRIVERS_CAN_H_ */
|