From 75291c2a88e1faccd32d6613a591440d4096ef9a Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 28 Jan 2022 09:19:05 +0100 Subject: [PATCH 01/15] can-calc-bit-timing: common_bitrates: add more bitrates Signed-off-by: Marc Kleine-Budde --- can-calc-bit-timing.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/can-calc-bit-timing.c b/can-calc-bit-timing.c index dc2a62c..7cd249a 100644 --- a/can-calc-bit-timing.c +++ b/can-calc-bit-timing.c @@ -1140,11 +1140,14 @@ static const struct calc_bittiming_const can_calc_consts[] = { static const unsigned int common_bitrates[] = { 1000000, 800000, + 666666, 500000, 250000, 125000, 100000, + 83333, 50000, + 33333, 20000, 10000, 0 From 2b2d38d06ba1adc3059d427224dc1066bf7b2693 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Tue, 8 Mar 2022 15:11:29 +0100 Subject: [PATCH 02/15] can-calc-bit-timing: fix indention Signed-off-by: Marc Kleine-Budde --- can-calc-bit-timing.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/can-calc-bit-timing.c b/can-calc-bit-timing.c index 7cd249a..87c1edc 100644 --- a/can-calc-bit-timing.c +++ b/can-calc-bit-timing.c @@ -400,8 +400,8 @@ static const struct calc_bittiming_const can_calc_consts[] = { .brp_inc = 1, }, .ref_clk = { - { .clk = 20000000, .name = "CIA recommendation"}, - { .clk = 40000000, .name = "CIA recommendation"}, + { .clk = 20000000, .name = "CIA recommendation" }, + { .clk = 40000000, .name = "CIA recommendation" }, }, }, { .bittiming_const = { @@ -473,8 +473,8 @@ static const struct calc_bittiming_const can_calc_consts[] = { .brp_inc = 1, }, .ref_clk = { - { .clk = 20000000, .name = "CIA recommendation"}, - { .clk = 40000000, .name = "CIA recommendation"}, + { .clk = 20000000, .name = "CIA recommendation" }, + { .clk = 40000000, .name = "CIA recommendation" }, }, .printf_btr = printf_btr_mcp251xfd, }, { /* -------- USB -------- */ @@ -577,7 +577,7 @@ static const struct calc_bittiming_const can_calc_consts[] = { }, .ref_clk = { { .clk = 24000000, .name = "CANtact Pro (original)", }, - { .clk = 40000000, .name = "CIA recommendation"}, + { .clk = 40000000, .name = "CIA recommendation" }, }, }, { @@ -778,7 +778,7 @@ static const struct calc_bittiming_const can_calc_consts[] = { { .clk = 30000000, .name = "mx6" }, { .clk = 49875000, }, { .clk = 66000000, }, - { .clk = 66500000, .name = "mx25"}, + { .clk = 66500000, .name = "mx25" }, { .clk = 66666666, }, { .clk = 83368421, .name = "vybrid" }, }, @@ -807,8 +807,8 @@ static const struct calc_bittiming_const can_calc_consts[] = { .brp_inc = 1, }, .ref_clk = { - { .clk = 20000000, .name = "CIA recommendation"}, - { .clk = 40000000, .name = "CIA recommendation"}, + { .clk = 20000000, .name = "CIA recommendation" }, + { .clk = 40000000, .name = "CIA recommendation" }, }, }, { @@ -856,8 +856,8 @@ static const struct calc_bittiming_const can_calc_consts[] = { .brp_inc = 1, }, .ref_clk = { - { .clk = 20000000, .name = "CIA recommendation"}, - { .clk = 40000000, .name = "CIA recommendation"}, + { .clk = 20000000, .name = "CIA recommendation" }, + { .clk = 40000000, .name = "CIA recommendation" }, }, }, { .bittiming_const = { @@ -898,8 +898,8 @@ static const struct calc_bittiming_const can_calc_consts[] = { .brp_inc = 1, }, .ref_clk = { - { .clk = 20000000, .name = "CIA recommendation"}, - { .clk = 40000000, .name = "CIA recommendation"}, + { .clk = 20000000, .name = "CIA recommendation" }, + { .clk = 40000000, .name = "CIA recommendation" }, }, }, { .bittiming_const = { @@ -945,8 +945,8 @@ static const struct calc_bittiming_const can_calc_consts[] = { .brp_inc = 1, }, .ref_clk = { - { .clk = 20000000, .name = "CIA recommendation"}, - { .clk = 40000000, .name = "CIA recommendation"}, + { .clk = 20000000, .name = "CIA recommendation" }, + { .clk = 40000000, .name = "CIA recommendation" }, }, .printf_btr = printf_btr_mcan, }, { @@ -973,8 +973,8 @@ static const struct calc_bittiming_const can_calc_consts[] = { .brp_inc = 1, }, .ref_clk = { - { .clk = 20000000, .name = "CIA recommendation"}, - { .clk = 40000000, .name = "CIA recommendation"}, + { .clk = 20000000, .name = "CIA recommendation" }, + { .clk = 40000000, .name = "CIA recommendation" }, { .clk = 24000000, .name = "stm32mp1 - ck_hse" }, { .clk = 24573875, .name = "stm32mp1 - pll3_1" }, { .clk = 74250000, .name = "stm32mp1 - pll4_r" }, @@ -1104,8 +1104,8 @@ static const struct calc_bittiming_const can_calc_consts[] = { .brp_inc = 1, }, .ref_clk = { - { .clk = 20000000, .name = "CIA recommendation"}, - { .clk = 40000000, .name = "CIA recommendation"}, + { .clk = 20000000, .name = "CIA recommendation" }, + { .clk = 40000000, .name = "CIA recommendation" }, }, }, { .bittiming_const = { @@ -1131,8 +1131,8 @@ static const struct calc_bittiming_const can_calc_consts[] = { .brp_inc = 1, }, .ref_clk = { - { .clk = 20000000, .name = "CIA recommendation"}, - { .clk = 40000000, .name = "CIA recommendation"}, + { .clk = 20000000, .name = "CIA recommendation" }, + { .clk = 40000000, .name = "CIA recommendation" }, }, }, }; From 104e3f97a0162b9c1d4215b4421e0b7b284843ca Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 21 Feb 2022 21:47:53 +0100 Subject: [PATCH 03/15] can-calc-bit-timing: add new ref_clk to mcan Signed-off-by: Marc Kleine-Budde --- can-calc-bit-timing.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/can-calc-bit-timing.c b/can-calc-bit-timing.c index 87c1edc..536d020 100644 --- a/can-calc-bit-timing.c +++ b/can-calc-bit-timing.c @@ -976,9 +976,12 @@ static const struct calc_bittiming_const can_calc_consts[] = { { .clk = 20000000, .name = "CIA recommendation" }, { .clk = 40000000, .name = "CIA recommendation" }, { .clk = 24000000, .name = "stm32mp1 - ck_hse" }, - { .clk = 24573875, .name = "stm32mp1 - pll3_1" }, - { .clk = 74250000, .name = "stm32mp1 - pll4_r" }, + { .clk = 24573875, .name = "stm32mp1 - pll3_q" }, { .clk = 29700000, .name = "stm32mp1 - pll4_q" }, + { .clk = 48000000, .name = "stm32mp1 lxatac (new)" }, + { .clk = 60000000, .name = "stm32mp1 ecu02.5- pll4_r" }, + { .clk = 62500000, .name = "stm32mp1 lxatac (old) - pll4_r" }, + { .clk = 74250000, .name = "stm32mp1 - pll4_r" }, }, .printf_btr = printf_btr_mcan, }, { From 710fc9996168e5423e4040e17e73b3e44601174c Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 11 Aug 2022 20:33:35 +0200 Subject: [PATCH 04/15] can-calc-bit-timing: add new ref_clk to mcp2515 Signed-off-by: Marc Kleine-Budde --- can-calc-bit-timing.c | 1 + 1 file changed, 1 insertion(+) diff --git a/can-calc-bit-timing.c b/can-calc-bit-timing.c index 536d020..d8fbb2b 100644 --- a/can-calc-bit-timing.c +++ b/can-calc-bit-timing.c @@ -445,6 +445,7 @@ static const struct calc_bittiming_const can_calc_consts[] = { .ref_clk = { /* The mcp251x uses half of the external OSC clock as the base clock */ { .clk = 8000000 / 2, .name = "8 MHz OSC" }, + { .clk = 12000000 / 2, .name = "12 MHz OSC" }, { .clk = 16000000 / 2, .name = "16 MHz OSC" }, { .clk = 20000000 / 2, .name = "20 MHz OSC" }, }, From ab2b11d9a84e884fa4d683f7efea1ad5896abc65 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 21 Feb 2022 21:46:47 +0100 Subject: [PATCH 05/15] can-calc-bit-timing: add new ref_clk to xilinx_can_fd2 Signed-off-by: Marc Kleine-Budde --- can-calc-bit-timing.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/can-calc-bit-timing.c b/can-calc-bit-timing.c index d8fbb2b..56ff05f 100644 --- a/can-calc-bit-timing.c +++ b/can-calc-bit-timing.c @@ -1137,6 +1137,8 @@ static const struct calc_bittiming_const can_calc_consts[] = { .ref_clk = { { .clk = 20000000, .name = "CIA recommendation" }, { .clk = 40000000, .name = "CIA recommendation" }, + { .clk = 79999999, .name = "Versal ACAP" }, + { .clk = 80000000, .name = "Versal ACAP" }, }, }, }; From 258f3578140583e93d960b71cbcb9fe964934a7a Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 18 Mar 2022 14:38:59 +0100 Subject: [PATCH 06/15] can-calc-bit-timing: add information if printing data bit timing table Signed-off-by: Marc Kleine-Budde --- can-calc-bit-timing.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/can-calc-bit-timing.c b/can-calc-bit-timing.c index 56ff05f..bbf3154 100644 --- a/can-calc-bit-timing.c +++ b/can-calc-bit-timing.c @@ -163,6 +163,7 @@ struct calc_data { const struct can_bittiming *opt_bt; bool quiet; + bool fd_mode; }; static inline void *netdev_priv(const struct net_device *dev) @@ -1543,7 +1544,8 @@ static void print_bittiming_one(const struct can_calc_bittiming *calc_bittiming, unsigned int bitrate_nominal, unsigned int sample_point_nominal, void (*printf_btr)(struct can_bittiming *bt, bool hdr), - bool quiet) + bool quiet, + bool fd_mode) { struct net_device dev = { .priv.clock.freq = ref_clk->clk, @@ -1555,9 +1557,10 @@ static void print_bittiming_one(const struct can_calc_bittiming *calc_bittiming, unsigned int bitrate_error, sample_point_error; if (!quiet) { - printf("Bit timing parameters for %s with %.6f MHz ref clock %s%s%susing algo '%s'\n" + printf("%sBit timing parameters for %s with %.6f MHz ref clock %s%s%susing algo '%s'\n" " nominal real Bitrt nom real SampP\n" " Bitrate TQ[ns] PrS PhS1 PhS2 SJW BRP Bitrate Error SampP SampP Error ", + fd_mode ? "Data " : "", bittiming_const->name, ref_clk->clk / 1000000.0, ref_clk->name ? "(" : "", @@ -1649,7 +1652,8 @@ static void print_bittiming(const struct calc_data *data) *bitrates, sample_point, printf_btr, - quiet); + quiet, + data->fd_mode); bitrates++; quiet = true; } @@ -1706,6 +1710,8 @@ static void do_calc(struct calc_data *data) else data->bitrates = common_bitrates; + data->fd_mode = false; + print_bittiming(data); } @@ -1729,6 +1735,8 @@ static void do_calc(struct calc_data *data) else data->bitrates = common_data_bitrates; + data->fd_mode = true; + print_bittiming(data); } } From 9c38c16437e9c0ae4c4e0c8977a8253b1e8db9f8 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 18 Mar 2022 13:28:18 +0100 Subject: [PATCH 07/15] can-calc-bit-timing: move into subdir The source file will be split into several files in the next patches. Signed-off-by: Marc Kleine-Budde --- .gitignore | 1 + CMakeLists.txt | 4 ++++ GNUmakefile.am | 3 +++ Makefile | 5 ++++- .../can-calc-bit-timing.c | 0 5 files changed, 12 insertions(+), 1 deletion(-) rename can-calc-bit-timing.c => calc-bit-timing/can-calc-bit-timing.c (100%) diff --git a/.gitignore b/.gitignore index 568f070..1faf977 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ GNUmakefile.in /config/m4/ltsugar.m4 /config/m4/ltversion.m4 /config/m4/lt~obsolete.m4 +/calc-bit-timing/.dirstamp /mcp251xfd/.dirstamp /asc2log diff --git a/CMakeLists.txt b/CMakeLists.txt index fea4171..c317188 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,6 +62,10 @@ set(PROGRAMS slcanpty ) +add_executable(can-calc-bit-timing + calc-bit-timing/can-calc-bit-timing.c +) + add_executable(mcp251xfd-dump mcp251xfd/mcp251xfd-dev-coredump.c mcp251xfd/mcp251xfd-dump.c diff --git a/GNUmakefile.am b/GNUmakefile.am index 02c37ab..ed55131 100644 --- a/GNUmakefile.am +++ b/GNUmakefile.am @@ -39,6 +39,9 @@ libcan_la_SOURCES = \ libj1939_la_SOURCES = \ libj1939.c +can_calc_bit_timing_SOURCES = \ + calc-bit-timing/can-calc-bit-timing.c + mcp251xfd_dump_SOURCES = \ mcp251xfd/mcp251xfd-dev-coredump.c \ mcp251xfd/mcp251xfd-dump-userspace.h \ diff --git a/Makefile b/Makefile index fb52643..970a4cb 100644 --- a/Makefile +++ b/Makefile @@ -142,5 +142,8 @@ j1939sr: j1939sr.o libj1939.o testj1939: testj1939.o libj1939.o canbusload: canbusload.o canframelen.o -mcp251xfd-dump: mcp251xfd/mcp251xfd-dev-coredump.o mcp251xfd/mcp251xfd-dump.o mcp251xfd/mcp251xfd-main.o mcp251xfd/mcp251xfd-regmap.o +can-calc-bit-timing: calc-bit-timing/can-calc-bit-timing.o + $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ + +mcp251xfd-dump: mcp251xfd/mcp251xfd-dev-coredump.o mcp251xfd/mcp251xfd-dump.o mcp251xfd/mcp251xfd-main.o mcp251xfd/mcp251xfd-regmap.o $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ diff --git a/can-calc-bit-timing.c b/calc-bit-timing/can-calc-bit-timing.c similarity index 100% rename from can-calc-bit-timing.c rename to calc-bit-timing/can-calc-bit-timing.c From cfc3030080fe2e9de5667575ba5bd3c9cb38c636 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 21 Feb 2022 22:59:11 +0100 Subject: [PATCH 08/15] can-calc-bit-timing: prepare for more algos Signed-off-by: Marc Kleine-Budde --- calc-bit-timing/can-calc-bit-timing.c | 34 +++++++++++++-------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/calc-bit-timing/can-calc-bit-timing.c b/calc-bit-timing/can-calc-bit-timing.c index bbf3154..5c82c91 100644 --- a/calc-bit-timing/can-calc-bit-timing.c +++ b/calc-bit-timing/can-calc-bit-timing.c @@ -140,15 +140,15 @@ struct calc_bittiming_const { const void (*printf_data_btr)(struct can_bittiming *bt, bool hdr); }; -struct can_calc_bittiming { - int (*alg)(struct net_device *dev, struct can_bittiming *bt, - const struct can_bittiming_const *btc); +struct alg { + int (*calc_bittiming)(struct net_device *dev, struct can_bittiming *bt, + const struct can_bittiming_const *btc); const char *name; }; struct calc_data { const struct can_bittiming_const *bittiming_const; - const struct can_calc_bittiming *calc_bittiming; + const struct alg *alg; const void (*printf_btr)(struct can_bittiming *bt, bool hdr); const char *name; @@ -1472,13 +1472,13 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, #undef can_calc_bittiming #undef can_update_spt -static const struct can_calc_bittiming calc_bittiming_list[] = { +static const struct alg alg_list[] = { /* 1st will be default */ { - .alg = can_calc_bittiming_v4_8, + .calc_bittiming = can_calc_bittiming_v4_8, .name = "v4.8", }, { - .alg = can_calc_bittiming_v3_18, + .calc_bittiming = can_calc_bittiming_v3_18, .name = "v3.18", }, }; @@ -1537,7 +1537,7 @@ static __u32 get_cia_sample_point(__u32 bitrate) return sampl_pt; } -static void print_bittiming_one(const struct can_calc_bittiming *calc_bittiming, +static void print_bittiming_one(const struct alg *alg, const struct can_bittiming_const *bittiming_const, const struct can_bittiming *ref_bt, const struct calc_ref_clk *ref_clk, @@ -1566,7 +1566,7 @@ static void print_bittiming_one(const struct can_calc_bittiming *calc_bittiming, ref_clk->name ? "(" : "", ref_clk->name ? ref_clk->name : "", ref_clk->name ? ") " : "", - calc_bittiming->name); + alg->name); printf_btr(&bt, true); printf("\n"); @@ -1580,7 +1580,7 @@ static void print_bittiming_one(const struct can_calc_bittiming *calc_bittiming, return; } } else { - if (calc_bittiming->alg(&dev, &bt, bittiming_const)) { + if (alg->calc_bittiming(&dev, &bt, bittiming_const)) { printf("%8d ***bitrate not possible***\n", bitrate_nominal); return; } @@ -1645,7 +1645,7 @@ static void print_bittiming(const struct calc_data *data) else sample_point = get_cia_sample_point(*bitrates); - print_bittiming_one(data->calc_bittiming, + print_bittiming_one(data->alg, data->bittiming_const, data->opt_bt, ref_clks, @@ -1667,8 +1667,8 @@ static void do_list_calc_bittiming_list(void) { unsigned int i; - for (i = 0; i < ARRAY_SIZE(calc_bittiming_list); i++) - printf(" %s\n", calc_bittiming_list[i].name); + for (i = 0; i < ARRAY_SIZE(alg_list); i++) + printf(" %s\n", alg_list[i].name); } static void do_list(void) @@ -1765,7 +1765,7 @@ int main(int argc, char *argv[]) }; struct calc_data data[] = { { - .calc_bittiming = calc_bittiming_list, + .alg = alg_list, } }; const char *opt_alg_name = NULL; @@ -1890,9 +1890,9 @@ int main(int argc, char *argv[]) bool alg_found = false; unsigned int i; - for (i = 0; i < ARRAY_SIZE(calc_bittiming_list); i++) { - if (!strcmp(opt_alg_name, calc_bittiming_list[i].name)) { - data->calc_bittiming = &calc_bittiming_list[i]; + for (i = 0; i < ARRAY_SIZE(alg_list); i++) { + if (!strcmp(opt_alg_name, alg_list[i].name)) { + data->alg = &alg_list[i]; alg_found = true; } } From a7062893da9877c2f7cb8ab947e638fc0fed469f Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 21 Feb 2022 23:17:34 +0100 Subject: [PATCH 09/15] can-calc-bit-timing: add can_fixup_bittiming to alg Signed-off-by: Marc Kleine-Budde --- calc-bit-timing/can-calc-bit-timing.c | 28 +++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/calc-bit-timing/can-calc-bit-timing.c b/calc-bit-timing/can-calc-bit-timing.c index 5c82c91..4b56fa1 100644 --- a/calc-bit-timing/can-calc-bit-timing.c +++ b/calc-bit-timing/can-calc-bit-timing.c @@ -143,6 +143,8 @@ struct calc_bittiming_const { struct alg { int (*calc_bittiming)(struct net_device *dev, struct can_bittiming *bt, const struct can_bittiming_const *btc); + int (*fixup_bittiming)(struct net_device *dev, struct can_bittiming *bt, + const struct can_bittiming_const *btc); const char *name; }; @@ -1472,17 +1474,6 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, #undef can_calc_bittiming #undef can_update_spt -static const struct alg alg_list[] = { - /* 1st will be default */ - { - .calc_bittiming = can_calc_bittiming_v4_8, - .name = "v4.8", - }, { - .calc_bittiming = can_calc_bittiming_v3_18, - .name = "v3.18", - }, -}; - static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt, const struct can_bittiming_const *btc) { @@ -1523,6 +1514,19 @@ static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt, return 0; } +static const struct alg alg_list[] = { + /* 1st will be default */ + { + .calc_bittiming = can_calc_bittiming_v4_8, + .fixup_bittiming = can_fixup_bittiming, + .name = "v4.8", + }, { + .calc_bittiming = can_calc_bittiming_v3_18, + .fixup_bittiming = can_fixup_bittiming, + .name = "v3.18", + }, +}; + static __u32 get_cia_sample_point(__u32 bitrate) { __u32 sampl_pt; @@ -1575,7 +1579,7 @@ static void print_bittiming_one(const struct alg *alg, if (ref_bt) { bt = *ref_bt; - if (can_fixup_bittiming(&dev, &bt, bittiming_const)) { + if (alg->fixup_bittiming(&dev, &bt, bittiming_const)) { printf("%8d ***parameters exceed controller's range***\n", bitrate_nominal); return; } From ee2f48f33bc805305997f3f4ebb0b88bd0046986 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 18 Mar 2022 13:43:42 +0100 Subject: [PATCH 10/15] can-calc-bit-timing: move algorithms into separate files Signed-off-by: Marc Kleine-Budde --- GNUmakefile.am | 8 +- calc-bit-timing/can-calc-bit-timing-v3_18.c | 155 ++++++++++ calc-bit-timing/can-calc-bit-timing-v4_8.c | 181 ++++++++++++ calc-bit-timing/can-calc-bit-timing.c | 298 +------------------- 4 files changed, 349 insertions(+), 293 deletions(-) create mode 100644 calc-bit-timing/can-calc-bit-timing-v3_18.c create mode 100644 calc-bit-timing/can-calc-bit-timing-v4_8.c diff --git a/GNUmakefile.am b/GNUmakefile.am index ed55131..65b891e 100644 --- a/GNUmakefile.am +++ b/GNUmakefile.am @@ -5,6 +5,8 @@ AM_CPPFLAGS = \ -I$(top_builddir)/include \ $(linux_CFLAGS) +EXTRA_DIST = + # link every app against libcan, it's static so it wouldn't hurt LDADD = \ libcan.la @@ -42,6 +44,10 @@ libj1939_la_SOURCES = \ can_calc_bit_timing_SOURCES = \ calc-bit-timing/can-calc-bit-timing.c +EXTRA_DIST += \ + calc-bit-timing/can-calc-bit-timing-v3_18.c \ + calc-bit-timing/can-calc-bit-timing-v4_8.c + mcp251xfd_dump_SOURCES = \ mcp251xfd/mcp251xfd-dev-coredump.c \ mcp251xfd/mcp251xfd-dump-userspace.h \ @@ -90,7 +96,7 @@ j1939spy_LDADD = libj1939.la j1939sr_LDADD = libj1939.la testj1939_LDADD = libj1939.la -EXTRA_DIST = \ +EXTRA_DIST += \ .travis.yml \ Android.mk \ README.md \ diff --git a/calc-bit-timing/can-calc-bit-timing-v3_18.c b/calc-bit-timing/can-calc-bit-timing-v3_18.c new file mode 100644 index 0000000..95f177f --- /dev/null +++ b/calc-bit-timing/can-calc-bit-timing-v3_18.c @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* + * imported from v3.18-rc1~52^2~248^2~1 + * + */ + +/* + * Copyright (C) 2005 Marc Kleine-Budde, Pengutronix + * Copyright (C) 2006 Andrey Volkov, Varma Electronics + * Copyright (C) 2008-2009 Wolfgang Grandegger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the version 2 of the GNU General Public License + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/* + * Bit-timing calculation derived from: + * + * Code based on LinCAN sources and H8S2638 project + * Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz + * Copyright 2005 Stanislav Marek + * email: pisa@cmp.felk.cvut.cz + * + * Calculates proper bit-timing parameters for a specified bit-rate + * and sample-point, which can then be used to set the bit-timing + * registers of the CAN controller. You can find more information + * in the header file linux/can/netlink.h. + */ + +static int can_update_spt(const struct can_bittiming_const *btc, + int sampl_pt, int tseg, int *tseg1, int *tseg2) +{ + *tseg2 = tseg + 1 - (sampl_pt * (tseg + 1)) / 1000; + if (*tseg2 < btc->tseg2_min) + *tseg2 = btc->tseg2_min; + if (*tseg2 > btc->tseg2_max) + *tseg2 = btc->tseg2_max; + *tseg1 = tseg - *tseg2; + if (*tseg1 > btc->tseg1_max) { + *tseg1 = btc->tseg1_max; + *tseg2 = tseg - *tseg1; + } + return 1000 * (tseg + 1 - *tseg2) / (tseg + 1); +} + +static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, + const struct can_bittiming_const *btc) +{ + struct can_priv *priv = netdev_priv(dev); + long best_error = 1000000000, error = 0; + int best_tseg = 0, best_brp = 0, brp = 0; + int tsegall, tseg = 0, tseg1 = 0, tseg2 = 0; + int spt_error = 1000, spt = 0, sampl_pt; + long rate; + u64 v64; + + /* Use CIA recommended sample points */ + if (bt->sample_point) { + sampl_pt = bt->sample_point; + } else { + if (bt->bitrate > 800000) + sampl_pt = 750; + else if (bt->bitrate > 500000) + sampl_pt = 800; + else + sampl_pt = 875; + } + + /* tseg even = round down, odd = round up */ + for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1; + tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) { + tsegall = 1 + tseg / 2; + /* Compute all possible tseg choices (tseg=tseg1+tseg2) */ + brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2; + /* chose brp step which is possible in system */ + brp = (brp / btc->brp_inc) * btc->brp_inc; + if ((brp < btc->brp_min) || (brp > btc->brp_max)) + continue; + rate = priv->clock.freq / (brp * tsegall); + error = bt->bitrate - rate; + /* tseg brp biterror */ + if (error < 0) + error = -error; + if (error > best_error) + continue; + best_error = error; + if (error == 0) { + spt = can_update_spt(btc, sampl_pt, tseg / 2, + &tseg1, &tseg2); + error = sampl_pt - spt; + if (error < 0) + error = -error; + if (error > spt_error) + continue; + spt_error = error; + } + best_tseg = tseg / 2; + best_brp = brp; + if (error == 0) + break; + } + + if (best_error) { + /* Error in one-tenth of a percent */ + error = (best_error * 1000) / bt->bitrate; + if (error > CAN_CALC_MAX_ERROR) { + netdev_err(dev, + "bitrate error %ld.%ld%% too high\n", + error / 10, error % 10); + return -EDOM; + } else { + netdev_warn(dev, "bitrate error %ld.%ld%%\n", + error / 10, error % 10); + } + } + + /* real sample point */ + bt->sample_point = can_update_spt(btc, sampl_pt, best_tseg, + &tseg1, &tseg2); + + v64 = (u64)best_brp * 1000000000UL; + do_div(v64, priv->clock.freq); + bt->tq = (u32)v64; + bt->prop_seg = tseg1 / 2; + bt->phase_seg1 = tseg1 - bt->prop_seg; + bt->phase_seg2 = tseg2; + + /* check for sjw user settings */ + if (!bt->sjw || !btc->sjw_max) + bt->sjw = 1; + else { + /* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */ + if (bt->sjw > btc->sjw_max) + bt->sjw = btc->sjw_max; + /* bt->sjw must not be higher than tseg2 */ + if (tseg2 < bt->sjw) + bt->sjw = tseg2; + } + + bt->brp = best_brp; + /* real bit-rate */ + bt->bitrate = priv->clock.freq / (bt->brp * (tseg1 + tseg2 + 1)); + + return 0; +} diff --git a/calc-bit-timing/can-calc-bit-timing-v4_8.c b/calc-bit-timing/can-calc-bit-timing-v4_8.c new file mode 100644 index 0000000..8936fb4 --- /dev/null +++ b/calc-bit-timing/can-calc-bit-timing-v4_8.c @@ -0,0 +1,181 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* + * imported from v4.8-rc1~140^2~304^2~11 + * + */ + +/* + * Copyright (C) 2005 Marc Kleine-Budde, Pengutronix + * Copyright (C) 2006 Andrey Volkov, Varma Electronics + * Copyright (C) 2008-2009 Wolfgang Grandegger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the version 2 of the GNU General Public License + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/* + * Bit-timing calculation derived from: + * + * Code based on LinCAN sources and H8S2638 project + * Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz + * Copyright 2005 Stanislav Marek + * email: pisa@cmp.felk.cvut.cz + * + * Calculates proper bit-timing parameters for a specified bit-rate + * and sample-point, which can then be used to set the bit-timing + * registers of the CAN controller. You can find more information + * in the header file linux/can/netlink.h. + */ +static int can_update_spt(const struct can_bittiming_const *btc, + unsigned int spt_nominal, unsigned int tseg, + unsigned int *tseg1_ptr, unsigned int *tseg2_ptr, + unsigned int *spt_error_ptr) +{ + unsigned int spt_error, best_spt_error = UINT_MAX; + unsigned int spt, best_spt = 0; + unsigned int tseg1, tseg2; + int i; + + for (i = 0; i <= 1; i++) { + tseg2 = tseg + CAN_CALC_SYNC_SEG - (spt_nominal * (tseg + CAN_CALC_SYNC_SEG)) / 1000 - i; + tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max); + tseg1 = tseg - tseg2; + if (tseg1 > btc->tseg1_max) { + tseg1 = btc->tseg1_max; + tseg2 = tseg - tseg1; + } + + spt = 1000 * (tseg + CAN_CALC_SYNC_SEG - tseg2) / (tseg + CAN_CALC_SYNC_SEG); + spt_error = abs(spt_nominal - spt); + + if ((spt <= spt_nominal) && (spt_error < best_spt_error)) { + best_spt = spt; + best_spt_error = spt_error; + *tseg1_ptr = tseg1; + *tseg2_ptr = tseg2; + } + } + + if (spt_error_ptr) + *spt_error_ptr = best_spt_error; + + return best_spt; +} + +static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, + const struct can_bittiming_const *btc) +{ + struct can_priv *priv = netdev_priv(dev); + unsigned int rate; /* current bitrate */ + unsigned int rate_error; /* difference between current and nominal value */ + unsigned int best_rate_error = UINT_MAX; + unsigned int spt_error; /* difference between current and nominal value */ + unsigned int best_spt_error = UINT_MAX; + unsigned int spt_nominal; /* nominal sample point */ + unsigned int best_tseg = 0; /* current best value for tseg */ + unsigned int best_brp = 0; /* current best value for brp */ + unsigned int brp, tsegall, tseg, tseg1 = 0, tseg2 = 0; + u64 v64; + + /* Use CiA recommended sample points */ + if (bt->sample_point) { + spt_nominal = bt->sample_point; + } else { + if (bt->bitrate > 800000) + spt_nominal = 750; + else if (bt->bitrate > 500000) + spt_nominal = 800; + else + spt_nominal = 875; + } + + /* tseg even = round down, odd = round up */ + for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1; + tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) { + tsegall = CAN_CALC_SYNC_SEG + tseg / 2; + + /* Compute all possible tseg choices (tseg=tseg1+tseg2) */ + brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2; + + /* choose brp step which is possible in system */ + brp = (brp / btc->brp_inc) * btc->brp_inc; + if ((brp < btc->brp_min) || (brp > btc->brp_max)) + continue; + + rate = priv->clock.freq / (brp * tsegall); + rate_error = abs(bt->bitrate - rate); + + /* tseg brp biterror */ + if (rate_error > best_rate_error) + continue; + + /* reset sample point error if we have a better bitrate */ + if (rate_error < best_rate_error) + best_spt_error = UINT_MAX; + + can_update_spt(btc, spt_nominal, tseg / 2, &tseg1, &tseg2, &spt_error); + if (spt_error > best_spt_error) + continue; + + best_spt_error = spt_error; + best_rate_error = rate_error; + best_tseg = tseg / 2; + best_brp = brp; + + if (rate_error == 0 && spt_error == 0) + break; + } + + if (best_rate_error) { + /* Error in one-tenth of a percent */ + rate_error = (best_rate_error * 1000) / bt->bitrate; + if (rate_error > CAN_CALC_MAX_ERROR) { + netdev_err(dev, + "bitrate error %ld.%ld%% too high\n", + rate_error / 10, rate_error % 10); + return -EDOM; + } + netdev_warn(dev, "bitrate error %ld.%ld%%\n", + rate_error / 10, rate_error % 10); + } + + /* real sample point */ + bt->sample_point = can_update_spt(btc, spt_nominal, best_tseg, + &tseg1, &tseg2, NULL); + + v64 = (u64)best_brp * 1000 * 1000 * 1000; + do_div(v64, priv->clock.freq); + bt->tq = (u32)v64; + bt->prop_seg = tseg1 / 2; + bt->phase_seg1 = tseg1 - bt->prop_seg; + bt->phase_seg2 = tseg2; + + /* check for sjw user settings */ + if (!bt->sjw || !btc->sjw_max) { + bt->sjw = 1; + } else { + /* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */ + if (bt->sjw > btc->sjw_max) + bt->sjw = btc->sjw_max; + /* bt->sjw must not be higher than tseg2 */ + if (tseg2 < bt->sjw) + bt->sjw = tseg2; + } + + bt->brp = best_brp; + + /* real bit-rate */ + bt->bitrate = priv->clock.freq / (bt->brp * (CAN_CALC_SYNC_SEG + tseg1 + tseg2)); + + return 0; +} diff --git a/calc-bit-timing/can-calc-bit-timing.c b/calc-bit-timing/can-calc-bit-timing.c index 4b56fa1..41c5b65 100644 --- a/calc-bit-timing/can-calc-bit-timing.c +++ b/calc-bit-timing/can-calc-bit-timing.c @@ -1176,303 +1176,17 @@ static const unsigned int common_data_bitrates[] = { #define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */ #define CAN_CALC_SYNC_SEG 1 -/* - * Bit-timing calculation derived from: - * - * Code based on LinCAN sources and H8S2638 project - * Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz - * Copyright 2005 Stanislav Marek - * email: pisa@cmp.felk.cvut.cz - * - * Calculates proper bit-timing parameters for a specified bit-rate - * and sample-point, which can then be used to set the bit-timing - * registers of the CAN controller. You can find more information - * in the header file linux/can/netlink.h. - */ - -/* - * imported from v3.18-rc1~52^2~248^2~1 - * - * b25a437206ed can: dev: remove unused variable from can_calc_bittiming() function - */ -#undef can_calc_bittiming -#undef can_update_spt -#define can_calc_bittiming can_calc_bittiming_v3_18 #define can_update_spt can_update_spt_v3_18 - -static int can_update_spt(const struct can_bittiming_const *btc, - int sampl_pt, int tseg, int *tseg1, int *tseg2) -{ - *tseg2 = tseg + 1 - (sampl_pt * (tseg + 1)) / 1000; - if (*tseg2 < btc->tseg2_min) - *tseg2 = btc->tseg2_min; - if (*tseg2 > btc->tseg2_max) - *tseg2 = btc->tseg2_max; - *tseg1 = tseg - *tseg2; - if (*tseg1 > btc->tseg1_max) { - *tseg1 = btc->tseg1_max; - *tseg2 = tseg - *tseg1; - } - return 1000 * (tseg + 1 - *tseg2) / (tseg + 1); -} - -static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, - const struct can_bittiming_const *btc) -{ - struct can_priv *priv = netdev_priv(dev); - long best_error = 1000000000, error = 0; - int best_tseg = 0, best_brp = 0, brp = 0; - int tsegall, tseg = 0, tseg1 = 0, tseg2 = 0; - int spt_error = 1000, spt = 0, sampl_pt; - long rate; - u64 v64; - - /* Use CIA recommended sample points */ - if (bt->sample_point) { - sampl_pt = bt->sample_point; - } else { - if (bt->bitrate > 800000) - sampl_pt = 750; - else if (bt->bitrate > 500000) - sampl_pt = 800; - else - sampl_pt = 875; - } - - /* tseg even = round down, odd = round up */ - for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1; - tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) { - tsegall = 1 + tseg / 2; - /* Compute all possible tseg choices (tseg=tseg1+tseg2) */ - brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2; - /* chose brp step which is possible in system */ - brp = (brp / btc->brp_inc) * btc->brp_inc; - if ((brp < btc->brp_min) || (brp > btc->brp_max)) - continue; - rate = priv->clock.freq / (brp * tsegall); - error = bt->bitrate - rate; - /* tseg brp biterror */ - if (error < 0) - error = -error; - if (error > best_error) - continue; - best_error = error; - if (error == 0) { - spt = can_update_spt(btc, sampl_pt, tseg / 2, - &tseg1, &tseg2); - error = sampl_pt - spt; - if (error < 0) - error = -error; - if (error > spt_error) - continue; - spt_error = error; - } - best_tseg = tseg / 2; - best_brp = brp; - if (error == 0) - break; - } - - if (best_error) { - /* Error in one-tenth of a percent */ - error = (best_error * 1000) / bt->bitrate; - if (error > CAN_CALC_MAX_ERROR) { - netdev_err(dev, - "bitrate error %ld.%ld%% too high\n", - error / 10, error % 10); - return -EDOM; - } else { - netdev_warn(dev, "bitrate error %ld.%ld%%\n", - error / 10, error % 10); - } - } - - /* real sample point */ - bt->sample_point = can_update_spt(btc, sampl_pt, best_tseg, - &tseg1, &tseg2); - - v64 = (u64)best_brp * 1000000000UL; - do_div(v64, priv->clock.freq); - bt->tq = (u32)v64; - bt->prop_seg = tseg1 / 2; - bt->phase_seg1 = tseg1 - bt->prop_seg; - bt->phase_seg2 = tseg2; - - /* check for sjw user settings */ - if (!bt->sjw || !btc->sjw_max) - bt->sjw = 1; - else { - /* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */ - if (bt->sjw > btc->sjw_max) - bt->sjw = btc->sjw_max; - /* bt->sjw must not be higher than tseg2 */ - if (tseg2 < bt->sjw) - bt->sjw = tseg2; - } - - bt->brp = best_brp; - /* real bit-rate */ - bt->bitrate = priv->clock.freq / (bt->brp * (tseg1 + tseg2 + 1)); - - return 0; -} - -/* - * imported from v4.8-rc1~140^2~304^2~11 - * - * 7da29f97d6c8 can: dev: can-calc-bit-timing(): better sample point calculation - */ +#define can_calc_bittiming can_calc_bittiming_v3_18 +#include "can-calc-bit-timing-v3_18.c" #undef can_update_spt #undef can_calc_bittiming -#define can_update_spt can_update_spt_v4_8 + +#define can_update_sample_point can_update_sample_point_v4_8 #define can_calc_bittiming can_calc_bittiming_v4_8 - -static int can_update_spt(const struct can_bittiming_const *btc, - unsigned int spt_nominal, unsigned int tseg, - unsigned int *tseg1_ptr, unsigned int *tseg2_ptr, - unsigned int *spt_error_ptr) -{ - unsigned int spt_error, best_spt_error = UINT_MAX; - unsigned int spt, best_spt = 0; - unsigned int tseg1, tseg2; - int i; - - for (i = 0; i <= 1; i++) { - tseg2 = tseg + CAN_CALC_SYNC_SEG - (spt_nominal * (tseg + CAN_CALC_SYNC_SEG)) / 1000 - i; - tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max); - tseg1 = tseg - tseg2; - if (tseg1 > btc->tseg1_max) { - tseg1 = btc->tseg1_max; - tseg2 = tseg - tseg1; - } - - spt = 1000 * (tseg + CAN_CALC_SYNC_SEG - tseg2) / (tseg + CAN_CALC_SYNC_SEG); - spt_error = abs(spt_nominal - spt); - - if ((spt <= spt_nominal) && (spt_error < best_spt_error)) { - best_spt = spt; - best_spt_error = spt_error; - *tseg1_ptr = tseg1; - *tseg2_ptr = tseg2; - } - } - - if (spt_error_ptr) - *spt_error_ptr = best_spt_error; - - return best_spt; -} - -static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, - const struct can_bittiming_const *btc) -{ - struct can_priv *priv = netdev_priv(dev); - unsigned int rate; /* current bitrate */ - unsigned int rate_error; /* difference between current and nominal value */ - unsigned int best_rate_error = UINT_MAX; - unsigned int spt_error; /* difference between current and nominal value */ - unsigned int best_spt_error = UINT_MAX; - unsigned int spt_nominal; /* nominal sample point */ - unsigned int best_tseg = 0; /* current best value for tseg */ - unsigned int best_brp = 0; /* current best value for brp */ - unsigned int brp, tsegall, tseg, tseg1 = 0, tseg2 = 0; - u64 v64; - - /* Use CiA recommended sample points */ - if (bt->sample_point) { - spt_nominal = bt->sample_point; - } else { - if (bt->bitrate > 800000) - spt_nominal = 750; - else if (bt->bitrate > 500000) - spt_nominal = 800; - else - spt_nominal = 875; - } - - /* tseg even = round down, odd = round up */ - for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1; - tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) { - tsegall = CAN_CALC_SYNC_SEG + tseg / 2; - - /* Compute all possible tseg choices (tseg=tseg1+tseg2) */ - brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2; - - /* choose brp step which is possible in system */ - brp = (brp / btc->brp_inc) * btc->brp_inc; - if ((brp < btc->brp_min) || (brp > btc->brp_max)) - continue; - - rate = priv->clock.freq / (brp * tsegall); - rate_error = abs(bt->bitrate - rate); - - /* tseg brp biterror */ - if (rate_error > best_rate_error) - continue; - - /* reset sample point error if we have a better bitrate */ - if (rate_error < best_rate_error) - best_spt_error = UINT_MAX; - - can_update_spt(btc, spt_nominal, tseg / 2, &tseg1, &tseg2, &spt_error); - if (spt_error > best_spt_error) - continue; - - best_spt_error = spt_error; - best_rate_error = rate_error; - best_tseg = tseg / 2; - best_brp = brp; - - if (rate_error == 0 && spt_error == 0) - break; - } - - if (best_rate_error) { - /* Error in one-tenth of a percent */ - rate_error = (best_rate_error * 1000) / bt->bitrate; - if (rate_error > CAN_CALC_MAX_ERROR) { - netdev_err(dev, - "bitrate error %ld.%ld%% too high\n", - rate_error / 10, rate_error % 10); - return -EDOM; - } - netdev_warn(dev, "bitrate error %ld.%ld%%\n", - rate_error / 10, rate_error % 10); - } - - /* real sample point */ - bt->sample_point = can_update_spt(btc, spt_nominal, best_tseg, - &tseg1, &tseg2, NULL); - - v64 = (u64)best_brp * 1000 * 1000 * 1000; - do_div(v64, priv->clock.freq); - bt->tq = (u32)v64; - bt->prop_seg = tseg1 / 2; - bt->phase_seg1 = tseg1 - bt->prop_seg; - bt->phase_seg2 = tseg2; - - /* check for sjw user settings */ - if (!bt->sjw || !btc->sjw_max) { - bt->sjw = 1; - } else { - /* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */ - if (bt->sjw > btc->sjw_max) - bt->sjw = btc->sjw_max; - /* bt->sjw must not be higher than tseg2 */ - if (tseg2 < bt->sjw) - bt->sjw = tseg2; - } - - bt->brp = best_brp; - - /* real bit-rate */ - bt->bitrate = priv->clock.freq / (bt->brp * (CAN_CALC_SYNC_SEG + tseg1 + tseg2)); - - return 0; -} - +#include "can-calc-bit-timing-v4_8.c" +#undef can_update_sample_point #undef can_calc_bittiming -#undef can_update_spt static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt, const struct can_bittiming_const *btc) From c1f5dc53ec436bdb88154c4828813f90542987fb Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 16 Mar 2022 22:22:33 +0100 Subject: [PATCH 11/15] can-calc-bit-timing: import bit timing calculation algorithm from v2.6.31 Signed-off-by: Marc Kleine-Budde --- GNUmakefile.am | 1 + calc-bit-timing/can-calc-bit-timing-v2_6_31.c | 190 ++++++++++++++++++ calc-bit-timing/can-calc-bit-timing.c | 12 ++ 3 files changed, 203 insertions(+) create mode 100644 calc-bit-timing/can-calc-bit-timing-v2_6_31.c diff --git a/GNUmakefile.am b/GNUmakefile.am index 65b891e..ee99051 100644 --- a/GNUmakefile.am +++ b/GNUmakefile.am @@ -45,6 +45,7 @@ can_calc_bit_timing_SOURCES = \ calc-bit-timing/can-calc-bit-timing.c EXTRA_DIST += \ + calc-bit-timing/can-calc-bit-timing-v2_6_31.c \ calc-bit-timing/can-calc-bit-timing-v3_18.c \ calc-bit-timing/can-calc-bit-timing-v4_8.c diff --git a/calc-bit-timing/can-calc-bit-timing-v2_6_31.c b/calc-bit-timing/can-calc-bit-timing-v2_6_31.c new file mode 100644 index 0000000..3020aa1 --- /dev/null +++ b/calc-bit-timing/can-calc-bit-timing-v2_6_31.c @@ -0,0 +1,190 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* + * imported from v2.6.31-rc1~330^2~376 + * + * 39549eef3587 can: CAN Network device driver and Netlink interface + * + * cherry-picked for easier integration: + * 61463a30f652 can: make function can_get_bittiming static + * aabdfd6adb80 can: replace the dev_dbg/info/err/... with the new netdev_xxx macros + * 08da7da41ea4 can: provide a separate bittiming_const parameter to bittiming functions + * b25a437206ed can: dev: remove unused variable from can_calc_bittiming() function +*/ + +/* + * Copyright (C) 2005 Marc Kleine-Budde, Pengutronix + * Copyright (C) 2006 Andrey Volkov, Varma Electronics + * Copyright (C) 2008-2009 Wolfgang Grandegger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the version 2 of the GNU General Public License + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Bit-timing calculation derived from: + * + * Code based on LinCAN sources and H8S2638 project + * Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz + * Copyright 2005 Stanislav Marek + * email: pisa@cmp.felk.cvut.cz + * + * Calculates proper bit-timing parameters for a specified bit-rate + * and sample-point, which can then be used to set the bit-timing + * registers of the CAN controller. You can find more information + * in the header file linux/can/netlink.h. + */ +static int can_update_spt(const struct can_bittiming_const *btc, + int sampl_pt, int tseg, int *tseg1, int *tseg2) +{ + *tseg2 = tseg + 1 - (sampl_pt * (tseg + 1)) / 1000; + if (*tseg2 < btc->tseg2_min) + *tseg2 = btc->tseg2_min; + if (*tseg2 > btc->tseg2_max) + *tseg2 = btc->tseg2_max; + *tseg1 = tseg - *tseg2; + if (*tseg1 > btc->tseg1_max) { + *tseg1 = btc->tseg1_max; + *tseg2 = tseg - *tseg1; + } + return 1000 * (tseg + 1 - *tseg2) / (tseg + 1); +} + +static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, + const struct can_bittiming_const *btc) +{ + struct can_priv *priv = netdev_priv(dev); + long best_error = 1000000000, error = 0; + int best_tseg = 0, best_brp = 0, brp = 0; + int tsegall, tseg = 0, tseg1 = 0, tseg2 = 0; + int spt_error = 1000, spt = 0, sampl_pt; + long rate; + u64 v64; + + /* Use CIA recommended sample points */ + if (bt->sample_point) { + sampl_pt = bt->sample_point; + } else { + if (bt->bitrate > 800000) + sampl_pt = 750; + else if (bt->bitrate > 500000) + sampl_pt = 800; + else + sampl_pt = 875; + } + + /* tseg even = round down, odd = round up */ + for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1; + tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) { + tsegall = 1 + tseg / 2; + /* Compute all possible tseg choices (tseg=tseg1+tseg2) */ + brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2; + /* chose brp step which is possible in system */ + brp = (brp / btc->brp_inc) * btc->brp_inc; + if ((brp < btc->brp_min) || (brp > btc->brp_max)) + continue; + rate = priv->clock.freq / (brp * tsegall); + error = bt->bitrate - rate; + /* tseg brp biterror */ + if (error < 0) + error = -error; + if (error > best_error) + continue; + best_error = error; + if (error == 0) { + spt = can_update_spt(btc, sampl_pt, tseg / 2, + &tseg1, &tseg2); + error = sampl_pt - spt; + if (error < 0) + error = -error; + if (error > spt_error) + continue; + spt_error = error; + } + best_tseg = tseg / 2; + best_brp = brp; + if (error == 0) + break; + } + + if (best_error) { + /* Error in one-tenth of a percent */ + error = (best_error * 1000) / bt->bitrate; + if (error > CAN_CALC_MAX_ERROR) { + netdev_err(dev, + "bitrate error %ld.%ld%% too high\n", + error / 10, error % 10); + return -EDOM; + } else { + netdev_warn(dev, "bitrate error %ld.%ld%%\n", + error / 10, error % 10); + } + } + + /* real sample point */ + bt->sample_point = can_update_spt(btc, sampl_pt, best_tseg, + &tseg1, &tseg2); + + v64 = (u64)best_brp * 1000000000UL; + do_div(v64, priv->clock.freq); + bt->tq = (u32)v64; + bt->prop_seg = tseg1 / 2; + bt->phase_seg1 = tseg1 - bt->prop_seg; + bt->phase_seg2 = tseg2; + bt->sjw = 1; + bt->brp = best_brp; + /* real bit-rate */ + bt->bitrate = priv->clock.freq / (bt->brp * (tseg1 + tseg2 + 1)); + + return 0; +} + +/* + * Checks the validity of the specified bit-timing parameters prop_seg, + * phase_seg1, phase_seg2 and sjw and tries to determine the bitrate + * prescaler value brp. You can find more information in the header + * file linux/can/netlink.h. + */ +static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt, + const struct can_bittiming_const *btc) +{ + struct can_priv *priv = netdev_priv(dev); + int tseg1, alltseg; + u64 brp64; + + tseg1 = bt->prop_seg + bt->phase_seg1; + if (!bt->sjw) + bt->sjw = 1; + if (bt->sjw > btc->sjw_max || + tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max || + bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max) + return -ERANGE; + + brp64 = (u64)priv->clock.freq * (u64)bt->tq; + if (btc->brp_inc > 1) + do_div(brp64, btc->brp_inc); + brp64 += 500000000UL - 1; + do_div(brp64, 1000000000UL); /* the practicable BRP */ + if (btc->brp_inc > 1) + brp64 *= btc->brp_inc; + bt->brp = (u32)brp64; + + if (bt->brp < btc->brp_min || bt->brp > btc->brp_max) + return -EINVAL; + + alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1; + bt->bitrate = priv->clock.freq / (bt->brp * alltseg); + bt->sample_point = ((tseg1 + 1) * 1000) / alltseg; + + return 0; +} diff --git a/calc-bit-timing/can-calc-bit-timing.c b/calc-bit-timing/can-calc-bit-timing.c index 41c5b65..e8cb060 100644 --- a/calc-bit-timing/can-calc-bit-timing.c +++ b/calc-bit-timing/can-calc-bit-timing.c @@ -1176,6 +1176,14 @@ static const unsigned int common_data_bitrates[] = { #define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */ #define CAN_CALC_SYNC_SEG 1 +#define can_update_spt can_update_spt_v2_6_31 +#define can_calc_bittiming can_calc_bittiming_v2_6_31 +#define can_fixup_bittiming can_fixup_bittiming_v2_6_31 +#include "can-calc-bit-timing-v2_6_31.c" +#undef can_update_spt +#undef can_calc_bittiming +#undef can_fixup_bittiming + #define can_update_spt can_update_spt_v3_18 #define can_calc_bittiming can_calc_bittiming_v3_18 #include "can-calc-bit-timing-v3_18.c" @@ -1238,6 +1246,10 @@ static const struct alg alg_list[] = { .calc_bittiming = can_calc_bittiming_v3_18, .fixup_bittiming = can_fixup_bittiming, .name = "v3.18", + }, { + .calc_bittiming = can_calc_bittiming_v2_6_31, + .fixup_bittiming = can_fixup_bittiming_v2_6_31, + .name = "v2.6.31", }, }; From b777ce2e6dd8c8ba24592b7ed5ff6faf13bb0e20 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sat, 19 Mar 2022 14:28:18 +0100 Subject: [PATCH 12/15] can-calc-bit-timing: import bit timing calculation algorithm from v3.18 add missing can_fixup_bittiming() Signed-off-by: Marc Kleine-Budde --- calc-bit-timing/can-calc-bit-timing-v3_18.c | 41 ++++++++++++++++++++- calc-bit-timing/can-calc-bit-timing.c | 4 +- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/calc-bit-timing/can-calc-bit-timing-v3_18.c b/calc-bit-timing/can-calc-bit-timing-v3_18.c index 95f177f..14ac8ea 100644 --- a/calc-bit-timing/can-calc-bit-timing-v3_18.c +++ b/calc-bit-timing/can-calc-bit-timing-v3_18.c @@ -36,7 +36,6 @@ * registers of the CAN controller. You can find more information * in the header file linux/can/netlink.h. */ - static int can_update_spt(const struct can_bittiming_const *btc, int sampl_pt, int tseg, int *tseg1, int *tseg2) { @@ -153,3 +152,43 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, return 0; } + +/* + * Checks the validity of the specified bit-timing parameters prop_seg, + * phase_seg1, phase_seg2 and sjw and tries to determine the bitrate + * prescaler value brp. You can find more information in the header + * file linux/can/netlink.h. + */ +static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt, + const struct can_bittiming_const *btc) +{ + struct can_priv *priv = netdev_priv(dev); + int tseg1, alltseg; + u64 brp64; + + tseg1 = bt->prop_seg + bt->phase_seg1; + if (!bt->sjw) + bt->sjw = 1; + if (bt->sjw > btc->sjw_max || + tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max || + bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max) + return -ERANGE; + + brp64 = (u64)priv->clock.freq * (u64)bt->tq; + if (btc->brp_inc > 1) + do_div(brp64, btc->brp_inc); + brp64 += 500000000UL - 1; + do_div(brp64, 1000000000UL); /* the practicable BRP */ + if (btc->brp_inc > 1) + brp64 *= btc->brp_inc; + bt->brp = (u32)brp64; + + if (bt->brp < btc->brp_min || bt->brp > btc->brp_max) + return -EINVAL; + + alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1; + bt->bitrate = priv->clock.freq / (bt->brp * alltseg); + bt->sample_point = ((tseg1 + 1) * 1000) / alltseg; + + return 0; +} diff --git a/calc-bit-timing/can-calc-bit-timing.c b/calc-bit-timing/can-calc-bit-timing.c index e8cb060..8e77432 100644 --- a/calc-bit-timing/can-calc-bit-timing.c +++ b/calc-bit-timing/can-calc-bit-timing.c @@ -1186,9 +1186,11 @@ static const unsigned int common_data_bitrates[] = { #define can_update_spt can_update_spt_v3_18 #define can_calc_bittiming can_calc_bittiming_v3_18 +#define can_fixup_bittiming can_fixup_bittiming_v3_18 #include "can-calc-bit-timing-v3_18.c" #undef can_update_spt #undef can_calc_bittiming +#undef can_fixup_bittiming #define can_update_sample_point can_update_sample_point_v4_8 #define can_calc_bittiming can_calc_bittiming_v4_8 @@ -1244,7 +1246,7 @@ static const struct alg alg_list[] = { .name = "v4.8", }, { .calc_bittiming = can_calc_bittiming_v3_18, - .fixup_bittiming = can_fixup_bittiming, + .fixup_bittiming = can_fixup_bittiming_v3_18, .name = "v3.18", }, { .calc_bittiming = can_calc_bittiming_v2_6_31, From 18eb0ab7844972301f7dac1a9ac5c0f5594dbd90 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 21 Feb 2022 22:25:12 +0100 Subject: [PATCH 13/15] can-calc-bit-timing: import bit timing calculation algorithm from v4.8 The bit timing algorithm is not identical with the referenced commit. So re-import from that commit. Signed-off-by: Marc Kleine-Budde --- calc-bit-timing/can-calc-bit-timing-v4_8.c | 132 ++++++++++++++------- calc-bit-timing/can-calc-bit-timing.c | 44 +------ 2 files changed, 90 insertions(+), 86 deletions(-) diff --git a/calc-bit-timing/can-calc-bit-timing-v4_8.c b/calc-bit-timing/can-calc-bit-timing-v4_8.c index 8936fb4..7b0dad7 100644 --- a/calc-bit-timing/can-calc-bit-timing-v4_8.c +++ b/calc-bit-timing/can-calc-bit-timing-v4_8.c @@ -36,18 +36,18 @@ * registers of the CAN controller. You can find more information * in the header file linux/can/netlink.h. */ -static int can_update_spt(const struct can_bittiming_const *btc, - unsigned int spt_nominal, unsigned int tseg, +static int can_update_sample_point(const struct can_bittiming_const *btc, + unsigned int sample_point_nominal, unsigned int tseg, unsigned int *tseg1_ptr, unsigned int *tseg2_ptr, - unsigned int *spt_error_ptr) + unsigned int *sample_point_error_ptr) { - unsigned int spt_error, best_spt_error = UINT_MAX; - unsigned int spt, best_spt = 0; + unsigned int sample_point_error, best_sample_point_error = UINT_MAX; + unsigned int sample_point, best_sample_point = 0; unsigned int tseg1, tseg2; int i; for (i = 0; i <= 1; i++) { - tseg2 = tseg + CAN_CALC_SYNC_SEG - (spt_nominal * (tseg + CAN_CALC_SYNC_SEG)) / 1000 - i; + tseg2 = tseg + CAN_CALC_SYNC_SEG - (sample_point_nominal * (tseg + CAN_CALC_SYNC_SEG)) / 1000 - i; tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max); tseg1 = tseg - tseg2; if (tseg1 > btc->tseg1_max) { @@ -55,48 +55,48 @@ static int can_update_spt(const struct can_bittiming_const *btc, tseg2 = tseg - tseg1; } - spt = 1000 * (tseg + CAN_CALC_SYNC_SEG - tseg2) / (tseg + CAN_CALC_SYNC_SEG); - spt_error = abs(spt_nominal - spt); + sample_point = 1000 * (tseg + CAN_CALC_SYNC_SEG - tseg2) / (tseg + CAN_CALC_SYNC_SEG); + sample_point_error = abs(sample_point_nominal - sample_point); - if ((spt <= spt_nominal) && (spt_error < best_spt_error)) { - best_spt = spt; - best_spt_error = spt_error; + if ((sample_point <= sample_point_nominal) && (sample_point_error < best_sample_point_error)) { + best_sample_point = sample_point; + best_sample_point_error = sample_point_error; *tseg1_ptr = tseg1; *tseg2_ptr = tseg2; } } - if (spt_error_ptr) - *spt_error_ptr = best_spt_error; + if (sample_point_error_ptr) + *sample_point_error_ptr = best_sample_point_error; - return best_spt; + return best_sample_point; } static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, const struct can_bittiming_const *btc) { struct can_priv *priv = netdev_priv(dev); - unsigned int rate; /* current bitrate */ - unsigned int rate_error; /* difference between current and nominal value */ - unsigned int best_rate_error = UINT_MAX; - unsigned int spt_error; /* difference between current and nominal value */ - unsigned int best_spt_error = UINT_MAX; - unsigned int spt_nominal; /* nominal sample point */ - unsigned int best_tseg = 0; /* current best value for tseg */ - unsigned int best_brp = 0; /* current best value for brp */ + unsigned int bitrate; /* current bitrate */ + unsigned int bitrate_error; /* difference between current and nominal value */ + unsigned int best_bitrate_error = UINT_MAX; + unsigned int sample_point_error; /* difference between current and nominal value */ + unsigned int best_sample_point_error = UINT_MAX; + unsigned int sample_point_nominal; /* nominal sample point */ + unsigned int best_tseg = 0; /* current best value for tseg */ + unsigned int best_brp = 0; /* current best value for brp */ unsigned int brp, tsegall, tseg, tseg1 = 0, tseg2 = 0; u64 v64; /* Use CiA recommended sample points */ if (bt->sample_point) { - spt_nominal = bt->sample_point; + sample_point_nominal = bt->sample_point; } else { if (bt->bitrate > 800000) - spt_nominal = 750; + sample_point_nominal = 750; else if (bt->bitrate > 500000) - spt_nominal = 800; + sample_point_nominal = 800; else - spt_nominal = 875; + sample_point_nominal = 875; } /* tseg even = round down, odd = round up */ @@ -112,45 +112,47 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, if ((brp < btc->brp_min) || (brp > btc->brp_max)) continue; - rate = priv->clock.freq / (brp * tsegall); - rate_error = abs(bt->bitrate - rate); + bitrate = priv->clock.freq / (brp * tsegall); + bitrate_error = abs(bt->bitrate - bitrate); /* tseg brp biterror */ - if (rate_error > best_rate_error) + if (bitrate_error > best_bitrate_error) continue; /* reset sample point error if we have a better bitrate */ - if (rate_error < best_rate_error) - best_spt_error = UINT_MAX; + if (bitrate_error < best_bitrate_error) + best_sample_point_error = UINT_MAX; - can_update_spt(btc, spt_nominal, tseg / 2, &tseg1, &tseg2, &spt_error); - if (spt_error > best_spt_error) + can_update_sample_point(btc, sample_point_nominal, tseg / 2, &tseg1, &tseg2, &sample_point_error); + if (sample_point_error > best_sample_point_error) continue; - best_spt_error = spt_error; - best_rate_error = rate_error; + best_sample_point_error = sample_point_error; + best_bitrate_error = bitrate_error; best_tseg = tseg / 2; best_brp = brp; - if (rate_error == 0 && spt_error == 0) + if (bitrate_error == 0 && sample_point_error == 0) break; } - if (best_rate_error) { + if (best_bitrate_error) { /* Error in one-tenth of a percent */ - rate_error = (best_rate_error * 1000) / bt->bitrate; - if (rate_error > CAN_CALC_MAX_ERROR) { + v64 = (u64)best_bitrate_error * 1000; + do_div(v64, bt->bitrate); + bitrate_error = (u32)v64; + if (bitrate_error > CAN_CALC_MAX_ERROR) { netdev_err(dev, - "bitrate error %ld.%ld%% too high\n", - rate_error / 10, rate_error % 10); + "bitrate error %d.%d%% too high\n", + bitrate_error / 10, bitrate_error % 10); return -EDOM; } - netdev_warn(dev, "bitrate error %ld.%ld%%\n", - rate_error / 10, rate_error % 10); + netdev_warn(dev, "bitrate error %d.%d%%\n", + bitrate_error / 10, bitrate_error % 10); } /* real sample point */ - bt->sample_point = can_update_spt(btc, spt_nominal, best_tseg, + bt->sample_point = can_update_sample_point(btc, sample_point_nominal, best_tseg, &tseg1, &tseg2, NULL); v64 = (u64)best_brp * 1000 * 1000 * 1000; @@ -174,8 +176,48 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, bt->brp = best_brp; - /* real bit-rate */ + /* real bitrate */ bt->bitrate = priv->clock.freq / (bt->brp * (CAN_CALC_SYNC_SEG + tseg1 + tseg2)); return 0; } + +/* + * Checks the validity of the specified bit-timing parameters prop_seg, + * phase_seg1, phase_seg2 and sjw and tries to determine the bitrate + * prescaler value brp. You can find more information in the header + * file linux/can/netlink.h. + */ +static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt, + const struct can_bittiming_const *btc) +{ + struct can_priv *priv = netdev_priv(dev); + int tseg1, alltseg; + u64 brp64; + + tseg1 = bt->prop_seg + bt->phase_seg1; + if (!bt->sjw) + bt->sjw = 1; + if (bt->sjw > btc->sjw_max || + tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max || + bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max) + return -ERANGE; + + brp64 = (u64)priv->clock.freq * (u64)bt->tq; + if (btc->brp_inc > 1) + do_div(brp64, btc->brp_inc); + brp64 += 500000000UL - 1; + do_div(brp64, 1000000000UL); /* the practicable BRP */ + if (btc->brp_inc > 1) + brp64 *= btc->brp_inc; + bt->brp = (u32)brp64; + + if (bt->brp < btc->brp_min || bt->brp > btc->brp_max) + return -EINVAL; + + alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1; + bt->bitrate = priv->clock.freq / (bt->brp * alltseg); + bt->sample_point = ((tseg1 + 1) * 1000) / alltseg; + + return 0; +} diff --git a/calc-bit-timing/can-calc-bit-timing.c b/calc-bit-timing/can-calc-bit-timing.c index 8e77432..f869c9c 100644 --- a/calc-bit-timing/can-calc-bit-timing.c +++ b/calc-bit-timing/can-calc-bit-timing.c @@ -1194,55 +1194,17 @@ static const unsigned int common_data_bitrates[] = { #define can_update_sample_point can_update_sample_point_v4_8 #define can_calc_bittiming can_calc_bittiming_v4_8 +#define can_fixup_bittiming can_fixup_bittiming_v4_8 #include "can-calc-bit-timing-v4_8.c" #undef can_update_sample_point #undef can_calc_bittiming - -static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt, - const struct can_bittiming_const *btc) -{ - struct can_priv *priv = netdev_priv(dev); - unsigned int tseg1, alltseg; - u64 brp64, v64; - - tseg1 = bt->prop_seg + bt->phase_seg1; - if (!bt->sjw) - bt->sjw = 1; - if (bt->sjw > btc->sjw_max || - tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max || - bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max) - return -ERANGE; - - if (!bt->brp) { - brp64 = (u64)priv->clock.freq * (u64)bt->tq; - if (btc->brp_inc > 1) - do_div(brp64, btc->brp_inc); - brp64 += 500000000UL - 1; - do_div(brp64, 1000000000UL); /* the practicable BRP */ - if (btc->brp_inc > 1) - brp64 *= btc->brp_inc; - bt->brp = brp64; - } - - v64 = bt->brp * 1000 * 1000 * 1000; - do_div(v64, priv->clock.freq); - bt->tq = v64; - - if (bt->brp < btc->brp_min || bt->brp > btc->brp_max) - return -EINVAL; - - alltseg = CAN_CALC_SYNC_SEG + bt->prop_seg + bt->phase_seg1 + bt->phase_seg2; - bt->bitrate = priv->clock.freq / (bt->brp * alltseg); - bt->sample_point = ((CAN_CALC_SYNC_SEG + tseg1) * 1000) / alltseg; - - return 0; -} +#undef can_fixup_bittiming static const struct alg alg_list[] = { /* 1st will be default */ { .calc_bittiming = can_calc_bittiming_v4_8, - .fixup_bittiming = can_fixup_bittiming, + .fixup_bittiming = can_fixup_bittiming_v4_8, .name = "v4.8", }, { .calc_bittiming = can_calc_bittiming_v3_18, From 0654d4e711d04fa1c47a7bd546dfe762dac43450 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 17 Mar 2022 13:50:23 +0100 Subject: [PATCH 14/15] can-calc-bit-timing: import bit timing calculation algorithm from v5.16 Signed-off-by: Marc Kleine-Budde --- GNUmakefile.am | 3 +- calc-bit-timing/can-calc-bit-timing-v5_16.c | 216 ++++++++++++++++++++ calc-bit-timing/can-calc-bit-timing.c | 14 ++ 3 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 calc-bit-timing/can-calc-bit-timing-v5_16.c diff --git a/GNUmakefile.am b/GNUmakefile.am index ee99051..3090909 100644 --- a/GNUmakefile.am +++ b/GNUmakefile.am @@ -47,7 +47,8 @@ can_calc_bit_timing_SOURCES = \ EXTRA_DIST += \ calc-bit-timing/can-calc-bit-timing-v2_6_31.c \ calc-bit-timing/can-calc-bit-timing-v3_18.c \ - calc-bit-timing/can-calc-bit-timing-v4_8.c + calc-bit-timing/can-calc-bit-timing-v4_8.c \ + calc-bit-timing/can-calc-bit-timing-v5_16.c mcp251xfd_dump_SOURCES = \ mcp251xfd/mcp251xfd-dev-coredump.c \ diff --git a/calc-bit-timing/can-calc-bit-timing-v5_16.c b/calc-bit-timing/can-calc-bit-timing-v5_16.c new file mode 100644 index 0000000..aecfdbd --- /dev/null +++ b/calc-bit-timing/can-calc-bit-timing-v5_16.c @@ -0,0 +1,216 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* + * imported from v5.16-rc1~159^2~104^2~13 + * + */ + +/* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix + * Copyright (C) 2006 Andrey Volkov, Varma Electronics + * Copyright (C) 2008-2009 Wolfgang Grandegger + */ + +/* Bit-timing calculation derived from: + * + * Code based on LinCAN sources and H8S2638 project + * Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz + * Copyright 2005 Stanislav Marek + * email: pisa@cmp.felk.cvut.cz + * + * Calculates proper bit-timing parameters for a specified bit-rate + * and sample-point, which can then be used to set the bit-timing + * registers of the CAN controller. You can find more information + * in the header file linux/can/netlink.h. + */ +static int +can_update_sample_point(const struct can_bittiming_const *btc, + unsigned int sample_point_nominal, unsigned int tseg, + unsigned int *tseg1_ptr, unsigned int *tseg2_ptr, + unsigned int *sample_point_error_ptr) +{ + unsigned int sample_point_error, best_sample_point_error = UINT_MAX; + unsigned int sample_point, best_sample_point = 0; + unsigned int tseg1, tseg2; + int i; + + for (i = 0; i <= 1; i++) { + tseg2 = tseg + CAN_SYNC_SEG - + (sample_point_nominal * (tseg + CAN_SYNC_SEG)) / + 1000 - i; + tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max); + tseg1 = tseg - tseg2; + if (tseg1 > btc->tseg1_max) { + tseg1 = btc->tseg1_max; + tseg2 = tseg - tseg1; + } + + sample_point = 1000 * (tseg + CAN_SYNC_SEG - tseg2) / + (tseg + CAN_SYNC_SEG); + sample_point_error = abs(sample_point_nominal - sample_point); + + if (sample_point <= sample_point_nominal && + sample_point_error < best_sample_point_error) { + best_sample_point = sample_point; + best_sample_point_error = sample_point_error; + *tseg1_ptr = tseg1; + *tseg2_ptr = tseg2; + } + } + + if (sample_point_error_ptr) + *sample_point_error_ptr = best_sample_point_error; + + return best_sample_point; +} + +int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, + const struct can_bittiming_const *btc) +{ + struct can_priv *priv = netdev_priv(dev); + unsigned int bitrate; /* current bitrate */ + unsigned int bitrate_error; /* difference between current and nominal value */ + unsigned int best_bitrate_error = UINT_MAX; + unsigned int sample_point_error; /* difference between current and nominal value */ + unsigned int best_sample_point_error = UINT_MAX; + unsigned int sample_point_nominal; /* nominal sample point */ + unsigned int best_tseg = 0; /* current best value for tseg */ + unsigned int best_brp = 0; /* current best value for brp */ + unsigned int brp, tsegall, tseg, tseg1 = 0, tseg2 = 0; + u64 v64; + + /* Use CiA recommended sample points */ + if (bt->sample_point) { + sample_point_nominal = bt->sample_point; + } else { + if (bt->bitrate > 800 * CAN_KBPS) + sample_point_nominal = 750; + else if (bt->bitrate > 500 * CAN_KBPS) + sample_point_nominal = 800; + else + sample_point_nominal = 875; + } + + /* tseg even = round down, odd = round up */ + for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1; + tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) { + tsegall = CAN_SYNC_SEG + tseg / 2; + + /* Compute all possible tseg choices (tseg=tseg1+tseg2) */ + brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2; + + /* choose brp step which is possible in system */ + brp = (brp / btc->brp_inc) * btc->brp_inc; + if (brp < btc->brp_min || brp > btc->brp_max) + continue; + + bitrate = priv->clock.freq / (brp * tsegall); + bitrate_error = abs(bt->bitrate - bitrate); + + /* tseg brp biterror */ + if (bitrate_error > best_bitrate_error) + continue; + + /* reset sample point error if we have a better bitrate */ + if (bitrate_error < best_bitrate_error) + best_sample_point_error = UINT_MAX; + + can_update_sample_point(btc, sample_point_nominal, tseg / 2, + &tseg1, &tseg2, &sample_point_error); + if (sample_point_error > best_sample_point_error) + continue; + + best_sample_point_error = sample_point_error; + best_bitrate_error = bitrate_error; + best_tseg = tseg / 2; + best_brp = brp; + + if (bitrate_error == 0 && sample_point_error == 0) + break; + } + + if (best_bitrate_error) { + /* Error in one-tenth of a percent */ + v64 = (u64)best_bitrate_error * 1000; + do_div(v64, bt->bitrate); + bitrate_error = (u32)v64; + if (bitrate_error > CAN_CALC_MAX_ERROR) { + netdev_err(dev, + "bitrate error %d.%d%% too high\n", + bitrate_error / 10, bitrate_error % 10); + return -EDOM; + } + netdev_warn(dev, "bitrate error %d.%d%%\n", + bitrate_error / 10, bitrate_error % 10); + } + + /* real sample point */ + bt->sample_point = can_update_sample_point(btc, sample_point_nominal, + best_tseg, &tseg1, &tseg2, + NULL); + + v64 = (u64)best_brp * 1000 * 1000 * 1000; + do_div(v64, priv->clock.freq); + bt->tq = (u32)v64; + bt->prop_seg = tseg1 / 2; + bt->phase_seg1 = tseg1 - bt->prop_seg; + bt->phase_seg2 = tseg2; + + /* check for sjw user settings */ + if (!bt->sjw || !btc->sjw_max) { + bt->sjw = 1; + } else { + /* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */ + if (bt->sjw > btc->sjw_max) + bt->sjw = btc->sjw_max; + /* bt->sjw must not be higher than tseg2 */ + if (tseg2 < bt->sjw) + bt->sjw = tseg2; + } + + bt->brp = best_brp; + + /* real bitrate */ + bt->bitrate = priv->clock.freq / + (bt->brp * (CAN_SYNC_SEG + tseg1 + tseg2)); + + return 0; +} + +/* Checks the validity of the specified bit-timing parameters prop_seg, + * phase_seg1, phase_seg2 and sjw and tries to determine the bitrate + * prescaler value brp. You can find more information in the header + * file linux/can/netlink.h. + */ +static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt, + const struct can_bittiming_const *btc) +{ + struct can_priv *priv = netdev_priv(dev); + unsigned int tseg1, alltseg; + u64 brp64; + + tseg1 = bt->prop_seg + bt->phase_seg1; + if (!bt->sjw) + bt->sjw = 1; + if (bt->sjw > btc->sjw_max || + tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max || + bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max) + return -ERANGE; + + brp64 = (u64)priv->clock.freq * (u64)bt->tq; + if (btc->brp_inc > 1) + do_div(brp64, btc->brp_inc); + brp64 += 500000000UL - 1; + do_div(brp64, 1000000000UL); /* the practicable BRP */ + if (btc->brp_inc > 1) + brp64 *= btc->brp_inc; + bt->brp = (u32)brp64; + + if (bt->brp < btc->brp_min || bt->brp > btc->brp_max) + return -EINVAL; + + alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1; + bt->bitrate = priv->clock.freq / (bt->brp * alltseg); + bt->sample_point = ((tseg1 + 1) * 1000) / alltseg; + + return 0; +} diff --git a/calc-bit-timing/can-calc-bit-timing.c b/calc-bit-timing/can-calc-bit-timing.c index f869c9c..2b2c72b 100644 --- a/calc-bit-timing/can-calc-bit-timing.c +++ b/calc-bit-timing/can-calc-bit-timing.c @@ -1175,6 +1175,8 @@ static const unsigned int common_data_bitrates[] = { #define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */ #define CAN_CALC_SYNC_SEG 1 +#define CAN_SYNC_SEG 1 +#define CAN_KBPS 1000 #define can_update_spt can_update_spt_v2_6_31 #define can_calc_bittiming can_calc_bittiming_v2_6_31 @@ -1200,9 +1202,21 @@ static const unsigned int common_data_bitrates[] = { #undef can_calc_bittiming #undef can_fixup_bittiming +#define can_update_sample_point can_update_sample_point_v5_16 +#define can_calc_bittiming can_calc_bittiming_v5_16 +#define can_fixup_bittiming can_fixup_bittiming_v5_16 +#include "can-calc-bit-timing-v5_16.c" +#undef can_update_sample_point +#undef can_calc_bittiming +#undef can_fixup_bittiming + static const struct alg alg_list[] = { /* 1st will be default */ { + .calc_bittiming = can_calc_bittiming_v5_16, + .fixup_bittiming = can_fixup_bittiming_v5_16, + .name = "v5.16", + }, { .calc_bittiming = can_calc_bittiming_v4_8, .fixup_bittiming = can_fixup_bittiming_v4_8, .name = "v4.8", From 7e2010a1c09c22443eedf4120d931724effbac9d Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 11 Aug 2022 22:42:04 +0200 Subject: [PATCH 15/15] can-calc-bit-timing: import bit timing calculation algorithm from v5.19 Signed-off-by: Marc Kleine-Budde --- GNUmakefile.am | 3 +- calc-bit-timing/can-calc-bit-timing-v5_19.c | 216 ++++++++++++++++++++ calc-bit-timing/can-calc-bit-timing.c | 29 ++- 3 files changed, 243 insertions(+), 5 deletions(-) create mode 100644 calc-bit-timing/can-calc-bit-timing-v5_19.c diff --git a/GNUmakefile.am b/GNUmakefile.am index 3090909..8ce78e2 100644 --- a/GNUmakefile.am +++ b/GNUmakefile.am @@ -48,7 +48,8 @@ EXTRA_DIST += \ calc-bit-timing/can-calc-bit-timing-v2_6_31.c \ calc-bit-timing/can-calc-bit-timing-v3_18.c \ calc-bit-timing/can-calc-bit-timing-v4_8.c \ - calc-bit-timing/can-calc-bit-timing-v5_16.c + calc-bit-timing/can-calc-bit-timing-v5_16.c \ + calc-bit-timing/can-calc-bit-timing-v5_19.c mcp251xfd_dump_SOURCES = \ mcp251xfd/mcp251xfd-dev-coredump.c \ diff --git a/calc-bit-timing/can-calc-bit-timing-v5_19.c b/calc-bit-timing/can-calc-bit-timing-v5_19.c new file mode 100644 index 0000000..a1b8821 --- /dev/null +++ b/calc-bit-timing/can-calc-bit-timing-v5_19.c @@ -0,0 +1,216 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* + * imported from v5.19-rc1~159^2~286^2~15 + * + */ + +/* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix + * Copyright (C) 2006 Andrey Volkov, Varma Electronics + * Copyright (C) 2008-2009 Wolfgang Grandegger + */ + +/* Bit-timing calculation derived from: + * + * Code based on LinCAN sources and H8S2638 project + * Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz + * Copyright 2005 Stanislav Marek + * email: pisa@cmp.felk.cvut.cz + * + * Calculates proper bit-timing parameters for a specified bit-rate + * and sample-point, which can then be used to set the bit-timing + * registers of the CAN controller. You can find more information + * in the header file linux/can/netlink.h. + */ +static int +can_update_sample_point(const struct can_bittiming_const *btc, + const unsigned int sample_point_nominal, const unsigned int tseg, + unsigned int *tseg1_ptr, unsigned int *tseg2_ptr, + unsigned int *sample_point_error_ptr) +{ + unsigned int sample_point_error, best_sample_point_error = UINT_MAX; + unsigned int sample_point, best_sample_point = 0; + unsigned int tseg1, tseg2; + int i; + + for (i = 0; i <= 1; i++) { + tseg2 = tseg + CAN_SYNC_SEG - + (sample_point_nominal * (tseg + CAN_SYNC_SEG)) / + 1000 - i; + tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max); + tseg1 = tseg - tseg2; + if (tseg1 > btc->tseg1_max) { + tseg1 = btc->tseg1_max; + tseg2 = tseg - tseg1; + } + + sample_point = 1000 * (tseg + CAN_SYNC_SEG - tseg2) / + (tseg + CAN_SYNC_SEG); + sample_point_error = abs(sample_point_nominal - sample_point); + + if (sample_point <= sample_point_nominal && + sample_point_error < best_sample_point_error) { + best_sample_point = sample_point; + best_sample_point_error = sample_point_error; + *tseg1_ptr = tseg1; + *tseg2_ptr = tseg2; + } + } + + if (sample_point_error_ptr) + *sample_point_error_ptr = best_sample_point_error; + + return best_sample_point; +} + +int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt, + const struct can_bittiming_const *btc) +{ + struct can_priv *priv = netdev_priv(dev); + unsigned int bitrate; /* current bitrate */ + unsigned int bitrate_error; /* difference between current and nominal value */ + unsigned int best_bitrate_error = UINT_MAX; + unsigned int sample_point_error; /* difference between current and nominal value */ + unsigned int best_sample_point_error = UINT_MAX; + unsigned int sample_point_nominal; /* nominal sample point */ + unsigned int best_tseg = 0; /* current best value for tseg */ + unsigned int best_brp = 0; /* current best value for brp */ + unsigned int brp, tsegall, tseg, tseg1 = 0, tseg2 = 0; + u64 v64; + + /* Use CiA recommended sample points */ + if (bt->sample_point) { + sample_point_nominal = bt->sample_point; + } else { + if (bt->bitrate > 800 * KILO /* BPS */) + sample_point_nominal = 750; + else if (bt->bitrate > 500 * KILO /* BPS */) + sample_point_nominal = 800; + else + sample_point_nominal = 875; + } + + /* tseg even = round down, odd = round up */ + for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1; + tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) { + tsegall = CAN_SYNC_SEG + tseg / 2; + + /* Compute all possible tseg choices (tseg=tseg1+tseg2) */ + brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2; + + /* choose brp step which is possible in system */ + brp = (brp / btc->brp_inc) * btc->brp_inc; + if (brp < btc->brp_min || brp > btc->brp_max) + continue; + + bitrate = priv->clock.freq / (brp * tsegall); + bitrate_error = abs(bt->bitrate - bitrate); + + /* tseg brp biterror */ + if (bitrate_error > best_bitrate_error) + continue; + + /* reset sample point error if we have a better bitrate */ + if (bitrate_error < best_bitrate_error) + best_sample_point_error = UINT_MAX; + + can_update_sample_point(btc, sample_point_nominal, tseg / 2, + &tseg1, &tseg2, &sample_point_error); + if (sample_point_error >= best_sample_point_error) + continue; + + best_sample_point_error = sample_point_error; + best_bitrate_error = bitrate_error; + best_tseg = tseg / 2; + best_brp = brp; + + if (bitrate_error == 0 && sample_point_error == 0) + break; + } + + if (best_bitrate_error) { + /* Error in one-tenth of a percent */ + v64 = (u64)best_bitrate_error * 1000; + do_div(v64, bt->bitrate); + bitrate_error = (u32)v64; + if (bitrate_error > CAN_CALC_MAX_ERROR) { + netdev_err(dev, + "bitrate error %d.%d%% too high\n", + bitrate_error / 10, bitrate_error % 10); + return -EDOM; + } + netdev_warn(dev, "bitrate error %d.%d%%\n", + bitrate_error / 10, bitrate_error % 10); + } + + /* real sample point */ + bt->sample_point = can_update_sample_point(btc, sample_point_nominal, + best_tseg, &tseg1, &tseg2, + NULL); + + v64 = (u64)best_brp * 1000 * 1000 * 1000; + do_div(v64, priv->clock.freq); + bt->tq = (u32)v64; + bt->prop_seg = tseg1 / 2; + bt->phase_seg1 = tseg1 - bt->prop_seg; + bt->phase_seg2 = tseg2; + + /* check for sjw user settings */ + if (!bt->sjw || !btc->sjw_max) { + bt->sjw = 1; + } else { + /* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */ + if (bt->sjw > btc->sjw_max) + bt->sjw = btc->sjw_max; + /* bt->sjw must not be higher than tseg2 */ + if (tseg2 < bt->sjw) + bt->sjw = tseg2; + } + + bt->brp = best_brp; + + /* real bitrate */ + bt->bitrate = priv->clock.freq / + (bt->brp * (CAN_SYNC_SEG + tseg1 + tseg2)); + + return 0; +} + +/* Checks the validity of the specified bit-timing parameters prop_seg, + * phase_seg1, phase_seg2 and sjw and tries to determine the bitrate + * prescaler value brp. You can find more information in the header + * file linux/can/netlink.h. + */ +static int can_fixup_bittiming(const struct net_device *dev, struct can_bittiming *bt, + const struct can_bittiming_const *btc) +{ + const struct can_priv *priv = netdev_priv(dev); + unsigned int tseg1, alltseg; + u64 brp64; + + tseg1 = bt->prop_seg + bt->phase_seg1; + if (!bt->sjw) + bt->sjw = 1; + if (bt->sjw > btc->sjw_max || + tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max || + bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max) + return -ERANGE; + + brp64 = (u64)priv->clock.freq * (u64)bt->tq; + if (btc->brp_inc > 1) + do_div(brp64, btc->brp_inc); + brp64 += 500000000UL - 1; + do_div(brp64, 1000000000UL); /* the practicable BRP */ + if (btc->brp_inc > 1) + brp64 *= btc->brp_inc; + bt->brp = (u32)brp64; + + if (bt->brp < btc->brp_min || bt->brp > btc->brp_max) + return -EINVAL; + + alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1; + bt->bitrate = priv->clock.freq / (bt->brp * alltseg); + bt->sample_point = ((tseg1 + 1) * 1000) / alltseg; + + return 0; +} diff --git a/calc-bit-timing/can-calc-bit-timing.c b/calc-bit-timing/can-calc-bit-timing.c index 2b2c72b..787a50f 100644 --- a/calc-bit-timing/can-calc-bit-timing.c +++ b/calc-bit-timing/can-calc-bit-timing.c @@ -141,10 +141,18 @@ struct calc_bittiming_const { }; struct alg { - int (*calc_bittiming)(struct net_device *dev, struct can_bittiming *bt, - const struct can_bittiming_const *btc); - int (*fixup_bittiming)(struct net_device *dev, struct can_bittiming *bt, - const struct can_bittiming_const *btc); + union { + int (*calc_bittiming)(struct net_device *dev, struct can_bittiming *bt, + const struct can_bittiming_const *btc); + int (*calc_bittiming_const)(const struct net_device *dev, struct can_bittiming *bt, + const struct can_bittiming_const *btc); + }; + union { + int (*fixup_bittiming)(struct net_device *dev, struct can_bittiming *bt, + const struct can_bittiming_const *btc); + int (*fixup_bittiming_const)(const struct net_device *dev, struct can_bittiming *bt, + const struct can_bittiming_const *btc); + }; const char *name; }; @@ -1177,6 +1185,7 @@ static const unsigned int common_data_bitrates[] = { #define CAN_CALC_SYNC_SEG 1 #define CAN_SYNC_SEG 1 #define CAN_KBPS 1000 +#define KILO 1000UL #define can_update_spt can_update_spt_v2_6_31 #define can_calc_bittiming can_calc_bittiming_v2_6_31 @@ -1210,9 +1219,21 @@ static const unsigned int common_data_bitrates[] = { #undef can_calc_bittiming #undef can_fixup_bittiming +#define can_update_sample_point can_update_sample_point_v5_19 +#define can_calc_bittiming can_calc_bittiming_v5_19 +#define can_fixup_bittiming can_fixup_bittiming_v5_19 +#include "can-calc-bit-timing-v5_19.c" +#undef can_update_sample_point +#undef can_calc_bittiming +#undef can_fixup_bittiming + static const struct alg alg_list[] = { /* 1st will be default */ { + .calc_bittiming_const = can_calc_bittiming_v5_19, + .fixup_bittiming_const = can_fixup_bittiming_v5_19, + .name = "v5.19", + }, { .calc_bittiming = can_calc_bittiming_v5_16, .fixup_bittiming = can_fixup_bittiming_v5_16, .name = "v5.16",