Car Hacking with a PocketBeagle (CAN, SWCAN, LIN/ISO9141/K-Line, J1850 and more)

We released the Macchina M2, an Arduino-based car tinkering interface a little while ago. M2’s interface board has 2X CAN, 1X SWCAN, 2X LIN/ISO9141/K-Line, J1850, 6X 12v GPIO and more. In our latest experiment, we replaced our processor board with the PocketBeagle and now we have an awesome Linux based car tinkering platform! We are here to show it off, get your feedback and find some people who want to help us test and improve it.

We can always use an extra set of eyes on the design. Let us know what you think so far. If you are interested in playing with a beta unit, reach out to us at info@macchina.cc and let us know what you have in mind. Here is what we have so far for documentation. Let us know if you have any other questions.

Hi Earl,

I’m familiar with the other M2 versions but I’m trying to get my head wrapped around the beagle version. It appears to enable can we use config_pin and that connects the can transceiver of the M2 to the linux kernel on the beagle, correct?

If so the next thing that would be easy to test is to connect the SWCAN. As it looks like that just flows into the MCP2515 which should just show up as a CAN interface as well. Looking at the current SWCAN library It looks like we setup some specific M2 related settings. How would we do this as well as pass this information to the beagle to use as a can interface?

My ultimate goal is to connect all the interfaces to the linux side but I’m trying to get up to speed on how the beagle works. I’m familiar with linux, coding and the M2 but how these all work together still hasn’t clicked. I read the source for config-pin but that didn’t really clear anything up. If I want to write the glue to make this cape ‘just work’ what’s the worflow/process I should be going through?

Craig

So config-pin is just a user-space utility that allows us to easily switch
the peripheral/pin mapping.

On the am335x, each pins usually has 8 different modes that can be setup.
(gpio, can, usart, spi, timer, pru, etc)

By default the can interface is enabled, but it's not muxed to those pins.

So when you bootup, you will see the can interface listed under "ifconfig",
but till you actually configure the pins' for can (thru config-pin), the
am335x can ip will not see any traffic..

Regards,

Ok, but looking at the library for the M2 it looked like you configure pins 0 and 27 but there are also some modes that can be set. You tend to setup an interrupt to handle the comms. So I’m wondering how do I initialize the IC (TH8056 KDC)'s modes. Once that is done I imagine I can link the pins using CAN. For the other protocols I can’t use CAN so I’ll probably try to set them up as uart, however I still may need to talk to different ICs.

Since PocketBeagle (and M2) has 2 built-in CAN controllers, we needed an external CAN controller for Single-wire CAN. That MCP2515 controller is connected to PB via SPI and a couple other GPIO pins.

The attached schematic sketch shows the connections. We’ll make a table summarizing all of the other connections between the boards later.

Keep in mind that the library you noted here:

https://github.com/macchina/Single-Wire-CAN-mcp2515/blob/master/src/MCP2515_sw_can.cpp

relies on this library for functionality:

https://github.com/macchina/mcp2515

Thanks, ecs

PB_M2 SWCAN connections.png

Ok, so should I use config-pin on all the red PIN labels, P2_18, P2_6, P2_32, etc? The linux kernel has support for MCP2515 SPI. I’m not sure yet if that is compiled into the standard beagle kernel but I can check. Would I just set the SWC Mode pins to gpio?

Ok, so should I use config-pin on all the red PIN labels, P2_18, P2_6, P2_32, etc?

Correct. Pin labels in red coorespond to pins on PocketBeagle.

The linux kernel has support for MCP2515 SPI. I’m not sure yet if that is compiled into the standard beagle kernel but I can check. Would I just set the SWC Mode pins to gpio?

Correct again, 2 mode pins would just go to GPIO outputs. Bring both HIGH for normal mode.

Yeah… can't say I've tried the Linux kernel driver, but I'd be leery of
the MCP2515.

In high traffic situations, I've seen them get incoming and outgoing
traffic scrambled: namely transmitting a frame with the payload replaced
from a frame that was being received on the CANbus. It was if a race
condition caused the buffer storing the outgoing frame payload was
overwritten by the incoming frame just as transmission began.

I don’t see any updates on this thread since December. Has anyone done any work with this since then?

I am currently a computer science student soon to graduate, but I have many years of experience tinkering. I am familiar with dealing with external hardware from computers although computers such as the RPI, Arduino and the beagles are a somewhat new experience for me.

Anyhow, my summer project is to build new firmware for the stock M2 unit and I am hoping to start working on some stuff for this as well. I really want to learn how to build Linux drivers and this may make a lot of sense for me to learn on.

My Goal would be to add full Lawicel 2.0 support to the board and go from there. Lawicel is what defines SocketCAN and the intent is to expand it beyond JUST CANBUS to other protocols as well. Still maintains full compatibility with Standard SocketCAN but adds similar support for the other devices as well. Such as J1850VPW, LIN etc.

As it sits right now is there a low power mode for this board? Eventually I hope to have some of these installed full time in my truck to do some interesting projects but I need to be able to make them sleep when the truck is not running but be able to wake if necissary.

Good to hear your interest. I recently saw the PocketBeagle adapter for Macchina in the Car Hacking Village at CypherCon. I was talking to Will and Earl at Macchina (cc’d) about future possibilities.

My understanding is that one issue is that SocketCAN support had not been sorted out yet. I think it would be awesome if this is something you’re interested in working on.

Thanks,
Drew

I have emailed Earl and Josh about getting one of the Adapter boards when they are available. Just today I ordered a PocketBeagle to try and get up and running. I have a couple M2’s right now and will try to get a new interface board so I am not sharing across the different devices. Since I will be working on modularizing the current M2 Arduino based software I wanted to look into building a Linux based driver at some point anyhow. So I can potentially work in parallel on this.

I would be interested in finding out what issues there were with the SocketCAN stuff. I saw mention of a possible race condition with the Canbus Transceiver but I think a method similar to how Collin has done with the Due_Can driver with separate buffers for the send and receive buffers would go a long ways in helping to prevent that. Otherwise I only am aware of what is mentioned in this thread.

I would guess otherwise that the PocketBeagle SocketCAN driver should work the same with the M2 as it would with other devices or is it a generic PocketBeagle issue?

Good to hear your interest. I recently saw the PocketBeagle adapter for Macchina in the Car Hacking Village at CypherCon. I was talking to Will and Earl at Macchina (cc’d) about future possibilities.

My understanding is that one issue is that SocketCAN support had not been sorted out yet. I think it would be awesome if this is something you’re interested in working on.

Is there any challenge to SocketCAN? Wouldn’t it “just work” like any Linux system with CAN?

I do think sockets will be the way to go for pretty much all of the interfaces. CAN and single wire CAN are obvious candidates for going with a native socketcan interface. Some of the other protocols might be a bit of a stretch. But, there exists two possibilities.

  1. We can create another socket type for them. Currently you can create TCP, UDP, etc or CAN sockets in LINUX. It’d be possible to create something akin to socketcan but instead it uses a different socket type, perhaps K-LINE could be a socket type for instance. This would be kind of a bum deal as other programs would need to be specifically written to take advantage of the new socket types.

  2. Make everything a socketcan interface and fudge the details to match. I don’t think all of the other protocols have the same ID and data configuration as CAN and not all of them are broadcast buses like CAN but those low level details can likely be abstracted away. Then every interface can exist with a socketcan compatible interface. Technically CAN frames have either 11 or 29 bit IDs but you’d need to store the ID in a 32 bit field. So, the upper 3 bits could even be abused to specify protocol. 0 = CAN, 1 = LIN, 2 = K-Line, etc. Then you’d have that info right in the ID but perhaps that isn’t necessary. We’d already know that a given interface only supports a specific protocol. The end result would be that it’s possible to capture and send LIN traffic or some other interface type from any normal socketcan compatible program. However, some socketcan programs might be hard coded to expect no more than 8 data bytes. Some of the other interfaces can send and receive larger payloads. But, CAN-FD already goes up to 64 bytes and that’s possible in modern socketcan implementations so the danger should be limited.

I think option 2 would work fine. If someone wants to do that then that’s great. I can assist as needed.

It maybe of benefit to see a LIN implementation like this. Here is a paper: https://rtime.felk.cvut.cz/can/sllin-rtlws14-paper.pdf and here is some git code: https://github.com/trainman419/linux-lin/tree/master/sllin

Disclaimer, I haven’t used this module.

Craig

Option 2 is where I was thinking. Additional devices can be done as a LIN, VPW, PWM devices. I haven’t looked at the code base yet but will do so when I get the hardware to be able to do this. I have a pocketbeagle and a beagle bone black (for something else) on order now. When Macchina gets their next batch of adapters I hopefully will be getting one.

As part of my summer project with the M2 I hope to make them into a master slave configuration so you can use 2 M2’s or possibly a PocketBeagle and M2 to build a bridge or something similar using the PocketBeagle as a master. We shall see how far I get with it.

Rodney

Thanks Craig. I am sure that will be helpful when we get to that point. I still have my lab setup that I showed you so I can (hopefully) test any protocols that are out there.

My Priority will be insuring the CANBUS and SWCAN are working before moving on. LIN appears to be relatively simple since the hardware is already there so I MAY try integrating that next followed by VPW on this device. Will see what challenges are ahead for this once I get to that point. Since I don’t personally have a LIN device other than what I can simulate I will have to depend on others testing if it works or not outside my Simulation lab.

Will also depend on when the new boards are available so I can get my pocketbeagle up and running on it.

I do think sockets will be the way to go for pretty much all of the interfaces. CAN and single wire CAN are obvious candidates for going with a native socketcan interface. Some of the other protocols might be a bit of a stretch. But, there exists two possibilities.

For simplicity of reference, what are the interfaces outside of CAN and single-wire CAN?

  1. We can create another socket type for them. Currently you can create TCP, UDP, etc or CAN sockets in LINUX. It’d be possible to create something akin to socketcan but instead it uses a different socket type, perhaps K-LINE could be a socket type for instance. This would be kind of a bum deal as other programs would need to be specifically written to take advantage of the new socket types.

I looked up that K-LINE is ISO 9141-2. Don’t see any Linux drivers for that yet. I searched for sn65hvda195. What device are you using to create the interface?

  1. Make everything a socketcan interface and fudge the details to match. I don’t think all of the other protocols have the same ID and data configuration as CAN and not all of them are broadcast buses like CAN but those low level details can likely be abstracted away. Then every interface can exist with a socketcan compatible interface. Technically CAN frames have either 11 or 29 bit IDs but you’d need to store the ID in a 32 bit field. So, the upper 3 bits could even be abused to specify protocol. 0 = CAN, 1 = LIN, 2 = K-Line, etc. Then you’d have that info right in the ID but perhaps that isn’t necessary. We’d already know that a given interface only supports a specific protocol. The end result would be that it’s possible to capture and send LIN traffic or some other interface type from any normal socketcan compatible program. However, some socketcan programs might be hard coded to expect no more than 8 data bytes. Some of the other interfaces can send and receive larger payloads. But, CAN-FD already goes up to 64 bytes and that’s possible in modern socketcan implementations so the danger should be limited.

Can we define a super-set along with fallbacks when the superset (including, only the smallest subset) isn’t implemented?

I think option 2 would work fine. If someone wants to do that then that’s great. I can assist as needed.

Don’t really know who’d take this on.

I do think sockets will be the way to go for pretty much all of the
interfaces. CAN and single wire CAN are obvious candidates for going with a
native socketcan interface. Some of the other protocols might be a bit of a
stretch. But, there exists two possibilities.

For simplicity of reference, what are the interfaces outside of CAN and
single-wire CAN?

The M2 interface pretty much supports all of the ODBII protocols found in
US vehicles.
CAN, SWCAN, LIN (And related protocols), J1850 both VPW and PWM.
Support for ALDL could also easily be added but would require some
modifications.
See the first message in this thread for more details.

1. We can create another socket type for them. Currently you can create
TCP, UDP, etc or CAN sockets in LINUX. It'd be possible to create something
akin to socketcan but instead it uses a different socket type, perhaps
K-LINE could be a socket type for instance. This would be kind of a bum
deal as other programs would need to be specifically written to take
advantage of the new socket types.

I looked up that K-LINE is ISO 9141-2. Don't see any Linux drivers for
that yet. I searched for sn65hvda195. What device are you using to create
the interface?

There are no current linux drivers for anything outside of CAN / SWCAN
other than what Craig listed as a potential library for LIN.

2. Make everything a socketcan interface and fudge the details to match.
I don't think all of the other protocols have the same ID and data
configuration as CAN and not all of them are broadcast buses like CAN but
those low level details can likely be abstracted away. Then every interface
can exist with a socketcan compatible interface. Technically CAN frames
have either 11 or 29 bit IDs but you'd need to store the ID in a 32 bit
field. So, the upper 3 bits could even be abused to specify protocol. 0 =
CAN, 1 = LIN, 2 = K-Line, etc. Then you'd have that info right in the ID
but perhaps that isn't necessary. We'd already know that a given interface
only supports a specific protocol. The end result would be that it's
possible to capture and send LIN traffic or some other interface type from
any normal socketcan compatible program. However, some socketcan programs
might be hard coded to expect no more than 8 data bytes. Some of the other
interfaces can send and receive larger payloads. But, CAN-FD already goes
up to 64 bytes and that's possible in modern socketcan implementations so
the danger should be limited.

Can we define a super-set along with fallbacks when the superset
(including, only the smallest subset) isn't implemented?

I think option 2 would work fine. If someone wants to do that then that's
great. I can assist as needed.

Don't really know who'd take this on.

As a learning tool I plan to take this on. I will be working on getting the
firmware working for the M2 with the Arduino CPU board and will try to get
the same protocols working under the pocketBeagle CPU board.
I may use the LIN library that Craig has already mentioned for both the LIN
stuff and possibly for a framework to do the other protocols but I will
address that when I have hardware to work with.

As far as fallbacks and such.Since you have to physically enable the CANBUS
ports now is this really going to be an issue?
I don't believe this is done in any of the RPI add-ons that are out there.
You just get an error or it freezes if you try to access a CAN port that
isn't there.

Its been a little while since I posted my last response. I would like to learn how to work with the kernel modules on this device so I can look at adding additional protocol support.

I now have one in my possession and would like to see what I can learn about it before I can dedicate more time on it this summer.

I would like to at least get a development system up and running so I can run and test this device by summer and find out where the socketcan driver is and such.

My route on this at this time will likely be to create a new kernel module and I will likely call it SocketOBD. The basis for SocketCAN has been based on Lawicel 1.0. I would like to expand it to support Lawicel 2.0 which also supports other OBD protocols. So connecting to a different port would be no different than the basic CANBUS ports.

Since it would be a new expanded module I plan to fork it from the standard SocketCAN modules.

I finished my Bachelors in Computer Science in DEC 2018 but have been programming as a hobby for decades so I am not new to programming. I am currently working on a Masters in Cyber Security. My time during the semester will be limited but I would like to learn as much as I can leading up to the summer.

I will likely also fork the Can utils that depend on the socketCan and produce a version of that which will be compatible with either.

I basically hope to make them so the CANBUS functionality won’t lose anything but you will gain the same functionality for the other protocols.

Rodney