drivers: can: common: document sample point calculation function

Add documentation for the update_sampling_pnt() function and rename a few
internal variables to improve readability.

Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
This commit is contained in:
Henrik Brix Andersen 2023-03-20 15:14:00 +01:00 committed by Carles Cufí
commit 718099607e

View file

@ -78,52 +78,86 @@ int z_impl_can_add_rx_filter_msgq(const struct device *dev, struct k_msgq *msgq,
return api->add_rx_filter(dev, can_msgq_put, msgq, filter);
}
static int update_sampling_pnt(uint32_t ts, uint32_t sp, struct can_timing *res,
/**
* @brief Update the timing given a total number of time quanta and a sample point.
*
* @code{.text}
*
* +---------------------------------------------------+
* | Nominal bit time in time quanta (total_tq) |
* +--------------+----------+------------+------------+
* | sync_seg | prop_seg | phase_seg1 | phase_seg2 |
* +--------------+----------+------------+------------+
* | CAN_SYNG_SEG | tseg1 | tseg2 |
* +--------------+-----------------------+------------+
* ^
* sample_pnt
* @endcode
*
* @see @a can_timing
*
* @param total_tq Total number of time quanta.
* @param sample_pnt Sampling point in permill of the entire bit time.
* @param[out] res Result is written into the @a can_timing struct provided.
* @param max Maximum timing parameters values.
* @param min Minimum timing parameters values.
* @return Absolute sample point error.
*/
static int update_sampling_pnt(uint32_t total_tq, uint32_t sample_pnt,
struct can_timing *res,
const struct can_timing *max,
const struct can_timing *min)
{
uint16_t ts1_max = max->phase_seg1 + max->prop_seg;
uint16_t ts1_min = min->phase_seg1 + min->prop_seg;
uint32_t sp_calc;
uint16_t ts1, ts2;
uint16_t tseg1_max = max->phase_seg1 + max->prop_seg;
uint16_t tseg1_min = min->phase_seg1 + min->prop_seg;
uint32_t sample_pnt_res;
uint16_t tseg1, tseg2;
ts2 = ts - (ts * sp) / 1000;
ts2 = CLAMP(ts2, min->phase_seg2, max->phase_seg2);
ts1 = ts - CAN_SYNC_SEG - ts2;
/* Calculate number of time quanta in tseg2 for given sample point */
tseg2 = total_tq - (total_tq * sample_pnt) / 1000;
tseg2 = CLAMP(tseg2, min->phase_seg2, max->phase_seg2);
if (ts1 > ts1_max) {
ts1 = ts1_max;
ts2 = ts - CAN_SYNC_SEG - ts1;
if (ts2 > max->phase_seg2) {
/* Calculate number of time quanta in tseg1 */
tseg1 = total_tq - CAN_SYNC_SEG - tseg2;
if (tseg1 > tseg1_max) {
/* Sample point location must be decreased */
tseg1 = tseg1_max;
tseg2 = total_tq - CAN_SYNC_SEG - tseg1;
if (tseg2 > max->phase_seg2) {
return -1;
}
} else if (ts1 < ts1_min) {
ts1 = ts1_min;
ts2 = ts - CAN_SYNC_SEG - ts1;
if (ts2 < min->phase_seg2) {
} else if (tseg1 < tseg1_min) {
/* Sample point location must be increased */
tseg1 = tseg1_min;
tseg2 = total_tq - CAN_SYNC_SEG - tseg1;
if (tseg2 < min->phase_seg2) {
return -1;
}
}
res->phase_seg2 = ts2;
res->phase_seg2 = tseg2;
/* Attempt to distribute ts1 evenly between prop_seq and phase_seg1 */
res->prop_seg = CLAMP(ts1 / 2, min->prop_seg, max->prop_seg);
res->phase_seg1 = ts1 - res->prop_seg;
/* Attempt to distribute tseg1 evenly between prop_seq and phase_seg1 */
res->prop_seg = CLAMP(tseg1 / 2, min->prop_seg, max->prop_seg);
res->phase_seg1 = tseg1 - res->prop_seg;
if (res->phase_seg1 > max->phase_seg1) {
/* Even ts1 distribution not possible, decrease phase_seg1 */
/* Even tseg1 distribution not possible, decrease phase_seg1 */
res->phase_seg1 = max->phase_seg1;
res->prop_seg = ts1 - res->phase_seg1;
res->prop_seg = tseg1 - res->phase_seg1;
} else if (res->phase_seg1 < min->phase_seg1) {
/* Even ts1 distribution not possible, increase phase_seg1 */
/* Even tseg1 distribution not possible, increase phase_seg1 */
res->phase_seg1 = min->phase_seg1;
res->prop_seg = ts1 - res->phase_seg1;
res->prop_seg = tseg1 - res->phase_seg1;
}
sp_calc = (CAN_SYNC_SEG + ts1) * 1000 / ts;
/* Calculate the resulting sample point */
sample_pnt_res = (CAN_SYNC_SEG + tseg1) * 1000 / total_tq;
return sp_calc > sp ? sp_calc - sp : sp - sp_calc;
/* Return the absolute sample point error */
return sample_pnt_res > sample_pnt ?
sample_pnt_res - sample_pnt :
sample_pnt - sample_pnt_res;
}
/* Internal function to do the actual calculation */