pschichtel/JavaCAN

ISO-TP not working on a Raspberry Pi 4 Model B

andrej-hrast opened this issue · 11 comments

Hi,
I'm experiencing an issue that I think could be related to a kernel configuration, but I would like to hear your comment about it.

I'm working on a Java project, built using Maven, that depends on your libraries javacan-core and javacan-core-armv7 (3.2.0).

The application behaves as follows:

  • RawCanChannel communication works fine between Raspberry and development board with microcontroller and vice-versa
  • IsotpCanChannel doesn't work, in particular:
    • when I invoke the method IsotpChannel.write(ByteBuffer buf) with short message (e.g. 4 bytes) the microcontroller receives the correct message
    • when I invoke the method IsotpChannel.write(ByteBuffer buf) with longer message (e.g. 11 bytes) the microcontroller receives only the first frame of message. I checked this with candump on Raspberry:
     (129.182176)  can0       1FF   [8]  10 0B 00 11 22 33 44 55
     (129.184039)  can0  0000017F   [8]  30 08 00 00 00 00 00 00
    
    after the microcontroller's response the Raspberry doesn't send next frame.
    • when I invoke the method IsotpChannel.read(ByteBuffer buf), it remains in infinite waiting. If microcontroller sends first frame of ISO-TP message Raspberry doesn't send anything back and microcontroller goes in timeout.

I think kernel modules are correctly loaded:

root@raspberrypi:~# lsmod | grep "can"
can_isotp              24576  0
can_raw                20480  0
can                    28672  2 can_isotp,can_raw
can_dev                32768  1 mcp251x

and I think the network interface is correctly configured:

root@raspberrypi:~# ip addr | grep can0
4: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UP group default qlen 10

Could this be caused by some missing configuration in Java code or in O.S. configuration? Any advice is very appreciated! Thanks

Can you confirm the communication is working when using canutils?

Yes. My tests with cansend and candump works fine.
Do you recommend other tests?

There should be equivalent tools for isotp, can you test with those?

Thanks for replying.
With istotpsend I have same behavior. I run

root@raspberrypi:~# echo "11 22 33 44 55 66 11 22 33 44 55" | isotpsend -s 1FF -d 17F -p 00 can0

With can dump I captured only first frame and acknowledge frame from micro-controller :

 (001.455852)  can0       1FF   [8]  10 0B 11 22 33 44 55 66
 (001.456351)  can0  0000017F   [8]  30 08 00 00 00 00 00 00

Second frame was never caught by candump (and never arrived to the micro-controller).

OK so if isotpsend is consistent with JavaCAN then we can practically rule out JavaCAN as the cause here.

Its been a while since I worked with actual isotp hardware (vehicles back then), but I remember there being issues due to padding being disabled by default, but you have that enabled already. I wonder if there is some sff/eff addressing confusion, given that it dumped the addresses differently, but this feels far fetched. This could be a good topic for the CAN kernel mailing list.

@andrej-hrast any update on this?

Hi @pschichtel,
Yes, I have an update: yesterday I resolved the issue and your comment about padding let me investigate in the right way. The problem was caused by some small incompatibilities between microcontroller library implementation and Linux kernel module.
Microcontrollers' IDE doesn't provide a setting for 11 bit addresses, so it can only work with 29 bit addresses. This explains why in the candump reported above the second address is prefixed with 00000. Weirdly, the microcontroller doesn't distinguish between the 2 kind of addresses, while the kernel module handles them differently.
For this reason, the microcontroller replies but the kernel doesn't handle the acknowledge message and connection reaches the "timed out" state.
So, I decided to configure my project to always work using 29 bit addresses. In particular:

this.isotpChannel.bind(nd, IsotpSocketAddress.isotpAddress(0x17F | CanId.EFF_FLAG), IsotpSocketAddress.isotpAddress(0x1FF | CanId.EFF_FLAG));

This results in candump displaying:

 (004.665204)  can0  000001FF   [8]  10 15 00 11 22 33 44 55
 (004.666507)  can0  0000017F   [8]  30 08 00 00 00 00 00 00
 (004.667960)  can0  000001FF   [8]  21 66 77 00 11 00 11 22
 (004.669110)  can0  000001FF   [8]  22 33 44 55 66 77 00 11
 (004.670046)  can0  000001FF   [2]  23 22

And the message sent from Raspberry correctly arrives to the microcontroller!

Extra question: is there a more explicit way to configure IsotpSocketAddress to use 29 bit addresses rather than piping CanId.EFF_FLAG?

Thank you for your suggestions. I'm very happy to have solved this after so many days.

Nice to hear. So my guess about the EFF/SFF mismatch wasn't so far fetched after all. I wonder if I should collect these pitfalls in some kind of trouble shooting wiki page or so.

Currently there is no other way to create EFF addresses. I could imagine a effIsotpAddress helper function.

Sorry for the late reply and thanks for the document. Yes, that would have been useful!

In ISOTP section I would add the two examples of candump output (first packet and acknowledge), to highlight the padding difference in the wrong and correct cases.

In RAW section I would underline the fact that getId() method always returns an integer, from which it is not possible to understand if the used address is SFF or EFF and that isExtended() method should be used to distinguish between the two.

Many thanks again.

Thanks for you suggestion @andrej-hrast