Customers using Digi Connect ME 9210 with FIM CAN or ConnectCore 9P9215 with FIM CAN an Digi Embedded Linux DEL-5.7.2 having issues with timings not matching or wrong baudrate settings, as well as detection of bus-off does not work, should update to latest Linux driver 1.5 from 2017/February and current FIM firmware.
Either you update to latest DEL-5.7.3 with newer fim_can driver, or if you are staying with DEL-5.7.2 use patch below:
The FIM firmware fim_can.bin which is loaded during runtime by the driver into the FIM should be requested from Digi Technical Support through registration on:
https://www.digi.com/canbus
You should get the latest source code from with above request.
If you received your sources before 2017 you can patch fim_can.c to version 1.5 by applying patch:
--- fim_can_DEL57.c 2011-11-24 17:13:10.000000000 +0100
+++ fim_can.c 2017-03-13 12:58:27.000000000 +0100
@@ -9,7 +9,7 @@
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
- * !Revision: $Revision: 1.2 $
+ * !Revision: $Revision: 1.5 $
* !Author: Luis Galdos, Hector Oron
* !Descr:
* !References: Based on the virtual CAN driver (Copyright (c) 2002-2007
@@ -59,7 +59,7 @@
#endif
/* Driver informations */
-#define DRIVER_VERSION "1.3"
+#define DRIVER_VERSION "1.5"
#define DRIVER_AUTHOR "Luis Galdos, Hector Oron"
#define DRIVER_DESC "FIM CAN bus driver"
#define FIM_DRIVER_NAME "fim-can"
@@ -100,11 +100,12 @@
#define FIM_CAN_NR_FILTERS (8)
/* Default timing values (see Net+OS driver: nacbus.c) */
-#define FIM_CAN_DEFAULT_SJW (7)
-#define FIM_CAN_DEFAULT_PROPSEG (8)
-#define FIM_CAN_DEFAULT_PHASE1 (8)
-#define FIM_CAN_DEFAULT_PHASE2 (8)
+#define FIM_CAN_DEFAULT_SJW (1)
+#define FIM_CAN_DEFAULT_PROPSEG (0)
+#define FIM_CAN_DEFAULT_PHASE1 (1)
+#define FIM_CAN_DEFAULT_PHASE2 (1)
#define FIM_CAN_DEFAULT_BITRATE 500000
+#define FIM_CAN_DEFAULT_SAMPLE_POINT 875
/* Maximal values from the Net+OS driver */
#define FIM_CAN_MAX_BITRATE (1000000)
@@ -364,8 +365,8 @@
* In the future we will probably need different latency times for the
* bitrates. Let us keep this function for this purpose.
*/
-#define FIM_CAN_RXIRQ_LATENCY (1)
-#define FIM_CAN_TXIRQ_LATENCY (100)
+#define FIM_CAN_RXIRQ_LATENCY (24)
+#define FIM_CAN_TXIRQ_LATENCY (22)
*rx = FIM_CAN_RXIRQ_LATENCY;
*tx = FIM_CAN_TXIRQ_LATENCY;
ret = 0;
@@ -396,12 +397,11 @@
struct can_bittiming *bt;
bt = &port->can.bittiming;
- printk_debug("New timing: %u bps | sjw %u | sample %u | sync %u | clock %u\n",
+ printk_debug("New timing: %u bps | sjw %u | sample %u | sync %u\n",
bt->bitrate,
sjw,
sample_point,
- sync_period,
- bt->clock);
+ sync_period);
if (fim_can_calculate_latency(bt->bitrate, &larx, &latx)) {
printk_err("Failed latency calculation for rate %u\n", bt->bitrate);
@@ -450,6 +450,7 @@
unsigned char *ptr;
unsigned char data[sizeof(struct fim_can_timing_t) + (FIM_CAN_NR_FILTERS * 8)];
struct can_bittiming *bt;
+ unsigned int total_tq = 0, round_up_tq = 0;
/* Init the timing parameters */
memset(&cfg, 0, sizeof(cfg));
@@ -461,22 +462,28 @@
return -EINVAL;
}
- /* We must use the default bit rates for our FIM-firmware */
- if (!bt->sjw)
+ /*
+ * Use our defaults if user has not supplied timing values.
+ */
+ if ((bt->sjw == 0) || (bt->tq == 0) || (bt->sample_point == 0)) {
bt->sjw = FIM_CAN_DEFAULT_SJW;
- if (!bt->prop_seg)
bt->prop_seg = FIM_CAN_DEFAULT_PROPSEG;
-
- if (!bt->phase_seg1)
bt->phase_seg1 = FIM_CAN_DEFAULT_PHASE1;
-
- if (!bt->phase_seg2)
bt->phase_seg2 = FIM_CAN_DEFAULT_PHASE2;
+ bt->sample_point = FIM_CAN_DEFAULT_SAMPLE_POINT;
+ }
+ total_tq = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1; /* +1 to include sync segment*/
+ round_up_tq = total_tq / 2;
+
+ /*
+ * fim_can_fill_timing wants values expressed as percentages of the total bit time, so
+ * make the necessary adjustments to the parameters that we pass to it.
+ */
fim_can_fill_timing(port, &cfg,
- bt->sjw,
- bt->prop_seg + bt->phase_seg1 + 1,
- bt->phase_seg2);
+ ((100 * bt->sjw) + round_up_tq) / total_tq,
+ (bt->sample_point + 5)/10,
+ (100 + round_up_tq) / total_tq); /* timing for sync segment*/
fim_can_do_dump_timing(&cfg,
bt->sjw,
@@ -739,7 +746,12 @@
}
retval = fim_can_restart_fim(port);
if (!retval) {
- netif_start_queue(dev);
+ if (dev->operstate == IF_OPER_DOWN) {
+ netif_carrier_on(dev);
+ netif_wake_queue(dev);
+ } else {
+ netif_start_queue(dev);
+ }
port->can.state = CAN_STATE_ERROR_ACTIVE;
port->opened = 1;
}
@@ -920,11 +932,13 @@
struct can_frame *cf;
unsigned int bus, fatal;
struct net_device_stats *stats = &dev->stats;
+ enum can_state state;
port = netdev_priv(dev);
fim = &port->fim;
fim_get_exp_reg(fim, FIM_CAN_BUSSTATE_REG, &bus);
fim_get_exp_reg(fim, FIM_CAN_FATALERR_REG, &fatal);
+ state = port->can.state;
if ((!bus) && (!fatal) && (!is_transmit_failure))
return 0;
@@ -958,8 +972,10 @@
* The corresponding error flags are under: include/linux/can/error.h
*/
if (bus & FIM_CAN_BUSSTATE_OFF) {
+ state = CAN_STATE_BUS_OFF;
cf->can_id |= CAN_ERR_BUSOFF;
- can_bus_off(dev);
+ netif_carrier_off(dev);
+ port->can.can_stats.bus_off++;
}
/* @XXX: This seems to be the correct flags for our controller, or? */
@@ -971,8 +987,11 @@
if (is_transmit_failure) {
cf->can_id |= CAN_ERR_ACK;
+ stats->tx_errors++;
}
+ port->can.state = state;
+
/* Pass the error frame to the socket layer */
netif_rx(skb);
@@ -1252,6 +1271,7 @@
skb = dev_alloc_skb(sizeof(struct can_frame));
if (!skb) {
printk_err("No memory available? Dropping a CAN-frame!\n");
+ stats->rx_errors++;
goto fim_can_rx_isr_exit;
}
Last updated:
Sep 27, 2024