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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
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)
|
||||
{
|
||||
struct can_timing timing_data;
|
||||
|
|
|
@ -234,6 +234,11 @@ struct can_bus_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
|
||||
*
|
||||
|
@ -868,25 +873,12 @@ __syscall int can_calc_timing_data(const struct device *dev, struct can_timing *
|
|||
* @retval 0 If successful.
|
||||
* @retval -EBUSY if the CAN controller is not in stopped state.
|
||||
* @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.
|
||||
*/
|
||||
__syscall int can_set_timing_data(const struct device *dev,
|
||||
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
|
||||
*
|
||||
|
@ -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,
|
||||
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.
|
||||
*
|
||||
|
@ -953,19 +940,12 @@ int can_calc_prescaler(const struct device *dev, struct can_timing *timing,
|
|||
*
|
||||
* @retval 0 If successful.
|
||||
* @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.
|
||||
*/
|
||||
__syscall int can_set_timing(const struct device *dev,
|
||||
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
|
||||
*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue