drivers: can: check timing parameters
Check the requested CAN timing parameters against the min/max values supported by the driver and return an error if they are out of range. Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
This commit is contained in:
parent
9dc9f0a0fd
commit
d5672c9ee3
2 changed files with 62 additions and 27 deletions
|
@ -250,6 +250,41 @@ static uint16_t sample_point_for_bitrate(uint32_t bitrate)
|
||||||
return sample_pnt;
|
return sample_pnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int check_timing_in_range(const struct can_timing *timing,
|
||||||
|
const struct can_timing *min,
|
||||||
|
const struct can_timing *max)
|
||||||
|
{
|
||||||
|
if (timing->sjw != CAN_SJW_NO_CHANGE &&
|
||||||
|
!IN_RANGE(timing->sjw, min->sjw, max->sjw)) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IN_RANGE(timing->prop_seg, min->prop_seg, max->prop_seg) ||
|
||||||
|
!IN_RANGE(timing->phase_seg1, min->phase_seg1, max->phase_seg1) ||
|
||||||
|
!IN_RANGE(timing->phase_seg2, min->phase_seg2, max->phase_seg2) ||
|
||||||
|
!IN_RANGE(timing->prescaler, min->prescaler, max->prescaler)) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int z_impl_can_set_timing(const struct device *dev,
|
||||||
|
const struct can_timing *timing)
|
||||||
|
{
|
||||||
|
const struct can_driver_api *api = (const struct can_driver_api *)dev->api;
|
||||||
|
const struct can_timing *min = can_get_timing_min(dev);
|
||||||
|
const struct can_timing *max = can_get_timing_max(dev);
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = check_timing_in_range(timing, min, max);
|
||||||
|
if (err != 0) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return api->set_timing(dev, timing);
|
||||||
|
}
|
||||||
|
|
||||||
int z_impl_can_set_bitrate(const struct device *dev, uint32_t bitrate)
|
int z_impl_can_set_bitrate(const struct device *dev, uint32_t bitrate)
|
||||||
{
|
{
|
||||||
struct can_timing timing;
|
struct can_timing timing;
|
||||||
|
@ -285,6 +320,26 @@ int z_impl_can_set_bitrate(const struct device *dev, uint32_t bitrate)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_CAN_FD_MODE
|
#ifdef CONFIG_CAN_FD_MODE
|
||||||
|
int z_impl_can_set_timing_data(const struct device *dev,
|
||||||
|
const struct can_timing *timing_data)
|
||||||
|
{
|
||||||
|
const struct can_driver_api *api = (const struct can_driver_api *)dev->api;
|
||||||
|
const struct can_timing *min = can_get_timing_data_min(dev);
|
||||||
|
const struct can_timing *max = can_get_timing_data_max(dev);
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (api->set_timing_data == NULL) {
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = check_timing_in_range(timing_data, min, max);
|
||||||
|
if (err != 0) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return api->set_timing_data(dev, timing_data);
|
||||||
|
}
|
||||||
|
|
||||||
int z_impl_can_set_bitrate_data(const struct device *dev, uint32_t bitrate_data)
|
int z_impl_can_set_bitrate_data(const struct device *dev, uint32_t bitrate_data)
|
||||||
{
|
{
|
||||||
struct can_timing timing_data;
|
struct can_timing timing_data;
|
||||||
|
|
|
@ -234,6 +234,11 @@ struct can_bus_err_cnt {
|
||||||
uint8_t rx_err_cnt;
|
uint8_t rx_err_cnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Synchronization Jump Width (SJW) value to indicate that the SJW should not
|
||||||
|
* be changed by the timing calculation.
|
||||||
|
*/
|
||||||
|
#define CAN_SJW_NO_CHANGE 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief CAN bus timing structure
|
* @brief CAN bus timing structure
|
||||||
*
|
*
|
||||||
|
@ -868,25 +873,12 @@ __syscall int can_calc_timing_data(const struct device *dev, struct can_timing *
|
||||||
* @retval 0 If successful.
|
* @retval 0 If successful.
|
||||||
* @retval -EBUSY if the CAN controller is not in stopped state.
|
* @retval -EBUSY if the CAN controller is not in stopped state.
|
||||||
* @retval -EIO General input/output error, failed to configure device.
|
* @retval -EIO General input/output error, failed to configure device.
|
||||||
|
* @retval -ENOTSUP if the timing parameters are not supported by the driver.
|
||||||
* @retval -ENOSYS if CAN-FD support is not implemented by the driver.
|
* @retval -ENOSYS if CAN-FD support is not implemented by the driver.
|
||||||
*/
|
*/
|
||||||
__syscall int can_set_timing_data(const struct device *dev,
|
__syscall int can_set_timing_data(const struct device *dev,
|
||||||
const struct can_timing *timing_data);
|
const struct can_timing *timing_data);
|
||||||
|
|
||||||
#ifdef CONFIG_CAN_FD_MODE
|
|
||||||
static inline int z_impl_can_set_timing_data(const struct device *dev,
|
|
||||||
const struct can_timing *timing_data)
|
|
||||||
{
|
|
||||||
const struct can_driver_api *api = (const struct can_driver_api *)dev->api;
|
|
||||||
|
|
||||||
if (api->set_timing_data == NULL) {
|
|
||||||
return -ENOSYS;
|
|
||||||
}
|
|
||||||
|
|
||||||
return api->set_timing_data(dev, timing_data);
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_CAN_FD_MODE */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the bitrate for the data phase of the CAN-FD controller
|
* @brief Set the bitrate for the data phase of the CAN-FD controller
|
||||||
*
|
*
|
||||||
|
@ -936,11 +928,6 @@ __syscall int can_set_bitrate_data(const struct device *dev, uint32_t bitrate_da
|
||||||
int can_calc_prescaler(const struct device *dev, struct can_timing *timing,
|
int can_calc_prescaler(const struct device *dev, struct can_timing *timing,
|
||||||
uint32_t bitrate);
|
uint32_t bitrate);
|
||||||
|
|
||||||
/** Synchronization Jump Width (SJW) value to indicate that the SJW should not
|
|
||||||
* be changed by the timing calculation.
|
|
||||||
*/
|
|
||||||
#define CAN_SJW_NO_CHANGE 0
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Configure the bus timing of a CAN controller.
|
* @brief Configure the bus timing of a CAN controller.
|
||||||
*
|
*
|
||||||
|
@ -953,19 +940,12 @@ int can_calc_prescaler(const struct device *dev, struct can_timing *timing,
|
||||||
*
|
*
|
||||||
* @retval 0 If successful.
|
* @retval 0 If successful.
|
||||||
* @retval -EBUSY if the CAN controller is not in stopped state.
|
* @retval -EBUSY if the CAN controller is not in stopped state.
|
||||||
|
* @retval -ENOTSUP if the timing parameters are not supported by the driver.
|
||||||
* @retval -EIO General input/output error, failed to configure device.
|
* @retval -EIO General input/output error, failed to configure device.
|
||||||
*/
|
*/
|
||||||
__syscall int can_set_timing(const struct device *dev,
|
__syscall int can_set_timing(const struct device *dev,
|
||||||
const struct can_timing *timing);
|
const struct can_timing *timing);
|
||||||
|
|
||||||
static inline int z_impl_can_set_timing(const struct device *dev,
|
|
||||||
const struct can_timing *timing)
|
|
||||||
{
|
|
||||||
const struct can_driver_api *api = (const struct can_driver_api *)dev->api;
|
|
||||||
|
|
||||||
return api->set_timing(dev, timing);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the supported modes of the CAN controller
|
* @brief Get the supported modes of the CAN controller
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue