Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:06

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup can
0007  *
0008  * @brief Common CAN baud-rate routines for OCCAN/GRCAN/GRCANFD controllers
0009  *
0010  * Implements common routines for calculating CAN baud-rate parameters from
0011  * a user provided baud-rate speed.
0012  */
0013 
0014 /*
0015  * Copyright (C) 2019, 2020 Cobham Gaisler AB
0016  *
0017  * Redistribution and use in source and binary forms, with or without
0018  * modification, are permitted provided that the following conditions
0019  * are met:
0020  * 1. Redistributions of source code must retain the above copyright
0021  *    notice, this list of conditions and the following disclaimer.
0022  * 2. Redistributions in binary form must reproduce the above copyright
0023  *    notice, this list of conditions and the following disclaimer in the
0024  *    documentation and/or other materials provided with the distribution.
0025  *
0026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0036  * POSSIBILITY OF SUCH DAMAGE.
0037  */
0038 
0039 #include <grlib/canbtrs.h>
0040 
0041 /*#define GRLIB_CANBTRS_DEBUG*/
0042 
0043 /* Calculate CAN baud-rate generation parameters from requested baud-rate */
0044 int grlib_canbtrs_calc_timing(
0045     unsigned int baud,
0046     unsigned int core_hz,
0047     unsigned int sampl_pt,
0048     struct grlib_canbtrs_ranges *br,
0049     struct grlib_canbtrs_timing *timing
0050     )
0051 {
0052     int best_error = 2000000000, best_tseg=0, best_scaler=0;
0053     int tseg=0, tseg1=0, tseg2=0, sc, tmp, error;
0054 
0055     /* Default to 80% sample point */
0056     if ((sampl_pt < 50) || (sampl_pt > 99))
0057         sampl_pt = 80;
0058 
0059     /* step though all TSEG1+TSEG2 values possible */
0060     for (tseg = (br->min_tseg1 + br->min_tseg2);
0061          tseg <= (br->max_tseg1 + br->max_tseg2);
0062          tseg++) {
0063         /* calculate scaler */
0064         tmp = ((br->divfactor + tseg) * baud);
0065         sc = (core_hz * 2)/ tmp - core_hz / tmp;
0066         if (sc <= 0 || sc > br->max_scaler)
0067             continue;
0068         if (br->has_bpr &&
0069             (((sc > 256 * 1) && (sc <= 256 * 2) && (sc & 0x1)) ||
0070             ((sc > 256 * 2) && (sc <= 256 * 4) && (sc & 0x3)) ||
0071             ((sc > 256 * 4) && (sc <= 256 * 8) && (sc & 0x7))))
0072             continue;
0073 
0074         error = baud - core_hz / (sc * (br->divfactor + tseg));
0075 #ifdef GRLIB_CANBTRS_DEBUG
0076         printf("  baud=%d, tseg=%d, sc=%d, error=%d\n",
0077                baud, tseg, sc, error);
0078 #endif
0079         if (error < 0)
0080             error = -error;
0081 
0082         /* tseg is increasing, so we accept higher tseg with the same
0083          * baudrate to get better sampling point.
0084          */
0085         if (error <= best_error) {
0086             best_error = error;
0087             best_tseg = tseg;
0088             best_scaler = sc;
0089 #ifdef GRLIB_CANBTRS_DEBUG
0090             printf("  ! best baud=%d\n",
0091                    core_hz/(sc * (br->divfactor + tseg)));
0092 #endif
0093         }
0094     }
0095 
0096     /* return an error if 5% off baud-rate */
0097     if (best_error && (baud / best_error <= 5)) {
0098         return -2;
0099     } else if (!timing) {
0100         return 0; /* nothing to store result in, but a valid bitrate can be calculated */
0101     }
0102 
0103     tseg2 = (best_tseg + br->divfactor) -
0104             ((sampl_pt * (best_tseg + br->divfactor)) / 100);
0105     if (tseg2 < br->min_tseg2) {
0106         tseg2 = br->min_tseg2;
0107     } else if (tseg2 > br->max_tseg2) {
0108         tseg2 = br->max_tseg2;
0109     }
0110 
0111     tseg1 = best_tseg - tseg2;
0112     if (tseg1 > br->max_tseg1) {
0113         tseg1 = br->max_tseg1;
0114         tseg2 = best_tseg - tseg1;
0115     } else if (tseg1 < br->min_tseg1) {
0116         tseg1 = br->min_tseg1;
0117         tseg2 = best_tseg - tseg1;
0118     }
0119 
0120     /* Get scaler and BPR from pseudo SCALER clock */
0121     if (best_scaler <= 256) {
0122         timing->scaler = best_scaler - 1;
0123         timing->bpr = 0;
0124     } else if (best_scaler <= 256 * 2) {
0125         timing->scaler = ((best_scaler + 1) >> 1) - 1;
0126         timing->bpr = 1;
0127     } else if (best_scaler <= 256 * 4) {
0128         timing->scaler = ((best_scaler + 1) >> 2) - 1;
0129         timing->bpr = 2;
0130     } else {
0131         timing->scaler = ((best_scaler + 1) >> 3) - 1;
0132         timing->bpr = 3;
0133     }
0134 
0135     timing->ps1    = tseg1;
0136     timing->ps2    = tseg2;
0137     timing->rsj    = 1;
0138 
0139 #ifdef GRLIB_CANBTRS_DEBUG
0140     printf("  ! result: sc=%d,bpr=%d,ps1=%d,ps2=%d\n", timing->scaler, timing->bpr, timing->ps1, timing->ps2);
0141 #endif
0142 
0143     return 0;
0144 }