#!/usr/bin/env python3 # # Copyright (c) 2015, Freescale Semiconductor, Inc. # Copyright 2016-2021 NXP # Copyright 2022 Kristian Sloth Lauszus # All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # # Python port of the "FLEXCAN_CalculateImprovedTimingValues" function from the NXP SDK import sys def FLEXCAN_GetSegments(bitRate, tqNum): IDEAL_SP_LOW = 750 IDEAL_SP_MID = 800 IDEAL_SP_HIGH = 875 IDEAL_SP_FACTOR = 1000 MIN_TIME_SEGMENT1 = 2 MIN_TIME_SEGMENT2 = 2 # TODO: These should ideally not be hardcoded, as they are MCU dependent seg1Max = (0x380000 >> 19) + 1 # MAX_PSEG1 proSegMax = 7 + 1 # MAX_PROPSEG sjwMAX = (0xC00000 >> 22) + 1 # MAX_RJW if bitRate == 1000000: ideal_sp = IDEAL_SP_LOW elif bitRate >= 800000: ideal_sp = IDEAL_SP_MID else: ideal_sp = IDEAL_SP_HIGH # Calculates phaseSeg2 phaseSeg2 = tqNum - (tqNum * ideal_sp) // IDEAL_SP_FACTOR if phaseSeg2 < MIN_TIME_SEGMENT2: phaseSeg2 = MIN_TIME_SEGMENT2 elif phaseSeg2 > seg1Max: phaseSeg2 = seg1Max # Calculates phaseSeg1 and propSeg seg1Temp = tqNum - phaseSeg2 - 1 if seg1Temp > (seg1Max + proSegMax): phaseSeg2 += seg1Temp - seg1Max - proSegMax propSeg = proSegMax phaseSeg1 = seg1Max elif seg1Temp > proSegMax: propSeg = proSegMax phaseSeg1 = seg1Temp - proSegMax else: propSeg = seg1Temp - 1 phaseSeg1 = 1 # Try to make phaseSeg1 equal to phaseSeg2 if phaseSeg1 < phaseSeg2: seg1Temp = proSegMax - propSeg if (phaseSeg2 - phaseSeg1) > (proSegMax - propSeg) else phaseSeg2 - phaseSeg1 propSeg -= seg1Temp phaseSeg1 += seg1Temp else: seg1Temp = proSegMax - propSeg if (phaseSeg1 - phaseSeg2) > (proSegMax - propSeg) else phaseSeg1 - phaseSeg2 propSeg += seg1Temp phaseSeg1 -= seg1Temp # rJumpwidth (SJW) is the minimum value of phaseSeg1 and phaseSeg2 rJumpwidth = phaseSeg2 if phaseSeg1 > phaseSeg2 else phaseSeg1 if rJumpwidth > sjwMAX: rJumpwidth = sjwMAX phaseSeg1 -= 1 phaseSeg2 -= 1 propSeg -= 1 rJumpwidth -= 1 return propSeg, phaseSeg1, phaseSeg2, rJumpwidth def print_timing(bitRate, sourceClock_Hz, propSeg, phaseSeg1, phaseSeg2, rJumpwidth, preDivider): tq = (preDivider + 1) / sourceClock_Hz * 1e9 quantum = 1 + (propSeg + 1) + (phaseSeg1 + 1) + (phaseSeg2 + 1) sample_point_percent = (1 + (propSeg + 1) + (phaseSeg1 + 1)) / quantum * 100. print('Bit-rate: {} kbit/s, clock source: {} MHz, TQ: {:.1f} ns, quantum: {}, Prs: {}, PhS1: {}, PhS2: {}, SJW: {}, BRP: {}, sample point: {:.1f} %'.format(bitRate // 1000, sourceClock_Hz * 1e-6, tq, quantum, propSeg + 1, phaseSeg1 + 1, phaseSeg2 + 1, rJumpwidth + 1, preDivider + 1, sample_point_percent)) def FLEXCAN_CalculateImprovedTimingValues(bitRate, sourceClock_Hz): spTemp = 1000 pdivMAX = 255 tqMin = 8 # CTRL1_MIN_TIME_QUANTA tqNum = 25 # CTRL1_MAX_TIME_QUANTA fgRet = False while tqNum >= tqMin: clk = bitRate * tqNum if clk > sourceClock_Hz: tqNum -= 1 continue if (sourceClock_Hz // clk * clk) != sourceClock_Hz: tqNum -= 1 continue preDividerTemp = (sourceClock_Hz // clk) - 1 if preDividerTemp > pdivMAX: print('The frequency of source clock is too large or the bit rate is too small, the pre-divider could not handle it') break propSegTemp, phaseSeg1Temp, phaseSeg2Temp, rJumpwidthTemp = FLEXCAN_GetSegments(bitRate, tqNum) # Determine whether the calculated timing configuration can get the optimal sampling point if (((phaseSeg2Temp + 1) * 1000) // tqNum) < spTemp: spTemp = ((phaseSeg2Temp + 1) * 1000) // tqNum fgRet = True preDivider, propSeg, phaseSeg1, phaseSeg2, rJumpwidth = preDividerTemp, propSegTemp, phaseSeg1Temp, phaseSeg2Temp, rJumpwidthTemp # print_timing(bitRate, sourceClock_Hz, propSeg, phaseSeg1, phaseSeg2, rJumpwidth, preDivider) tqNum -= 1 if fgRet: print_timing(bitRate, sourceClock_Hz, propSeg, phaseSeg1, phaseSeg2, rJumpwidth, preDivider) return propSeg, phaseSeg1, phaseSeg2, rJumpwidth, preDivider else: print('Failed to find bit timing for bit-rate: {} kbit/s, clock source: {} MHz'.format(bitRate // 1000, sourceClock_Hz * 1e-6)) assert False if __name__ == '__main__': # Adjust these to match your setup or give them as command line arguments if len(sys.argv) > 1: bitRate = int(sys.argv[1]) sourceClock_Hz = int(sys.argv[2]) else: bitRate = 500_000 # 500 kbit/s sourceClock_Hz = 60_000_000 # 60 MHz FLEXCAN_CalculateImprovedTimingValues(bitRate, sourceClock_Hz)