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:
parent
ffefc6441b
commit
718099607e
1 changed files with 60 additions and 26 deletions
|
@ -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 */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue