TS-7250-V2 CAN

From embeddedTS Manuals

There is one CAN (Controller Area Network) interface implemented in the TS-7250-V2 hardware. The CAN signals are brought to the COM3 header, pins 4 (CAN_H), and 9 (CAN_L).

The CAN controller contained in the FPGA is compatible with the register interface for the SJA1000. This is implemented using SocketCAN.

Before proceeding with the examples, see the Kernel's CAN documentation here.

This board comes preinstalled with can-utils which can be used to communicate over a CAN network without writing any code. The candump utility can be used to dump all data on the network

## First, set the baud rate and bring up the device:
ip link set can0 type can bitrate 250000
ip link set can0 up

## Dump data & errors:
candump -cae can0,0:0,#FFFFFFFF &

## Send the packet with:
#can_id = 0x7df
#data 0 = 0x3
#data 1 = 0x1
#data 2 = 0x0c
cansend can0 7Df#03010c

This example packet is designed to work with the Ozen Elektronik myOByDic 1610 ECU simulator to read the RPM speed. This device will return data from candump with:

 can0  7DF  [3] 03 01 0C                  '...'
 can0  7E8  [8] 04 41 0C 2F C0 00 00 00   '.A./....'
 can0  7E9  [8] 04 41 0C 2F 80 00 00 00   '.A./....'

In this case, 0x2f is the current RPM value. This shows a simple way you can prove out the communication before moving to another language, but this next example sends the same packet and parses the same response in C:

#include <stdio.h>
#include <pthread.h>
#include <net/if.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <assert.h>
#include <linux/can.h>
#include <linux/can/raw.h>

int main(void)
{
	int s;
	int nbytes;
	struct sockaddr_can addr;
	struct can_frame frame;
	struct ifreq ifr;
	struct iovec iov;
	struct msghdr msg;
	char ctrlmsg[CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(sizeof(__u32))];
	char *ifname = "can0";
 
	if((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
		perror("Error while opening socket");
		return -1;
	}
 
	strcpy(ifr.ifr_name, ifname);
	ioctl(s, SIOCGIFINDEX, &ifr);
	addr.can_family  = AF_CAN;
	addr.can_ifindex = ifr.ifr_ifindex;
 
	if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
		perror("socket");
		return -2;
	}
 
 	/* For the ozen myOByDic 1610 this requests the RPM guage */
	frame.can_id  = 0x7df;
	frame.can_dlc = 3;
	frame.data[0] = 3;
	frame.data[1] = 1;
	frame.data[2] = 0x0c;
 
	nbytes = write(s, &frame, sizeof(struct can_frame));
	if(nbytes < 0) {
		perror("write");
		return -3;
	}

	iov.iov_base = &frame;
	msg.msg_name = &addr;
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = &ctrlmsg;
	iov.iov_len = sizeof(frame);
	msg.msg_namelen = sizeof(struct sockaddr_can);
	msg.msg_controllen = sizeof(ctrlmsg);  
	msg.msg_flags = 0;

	do {
		nbytes = recvmsg(s, &msg, 0);
		if (nbytes < 0) {
			perror("read");
			return -4;
		}

		if (nbytes < (int)sizeof(struct can_frame)) {
			fprintf(stderr, "read: incomplete CAN frame\n");
		}
	} while(nbytes == 0);

	if(frame.data[0] == 0x4)
		printf("RPM at %d of 255\n", frame.data[3]);
 
	return 0;
}

Other languages have bindings to access CAN such as Python using C-types, Java using JNI.

The following setup instructions are only necessary for developers who need to use old sources or have some other reason that makes updating to the current image impractical or impossible. The current image has support for CAN already installed.

If building a kernel from old sources, the standard SJA1000 CAN driver will work: The TS-7250-V2 FPGA CAN core uses the sja1000_isa CAN driver. Following the kernel build instructions above, during the "make menuconfig" step, set "M" through this tree: -> Networking support (NET [=y]) -> CAN bus subsystem support (CAN [=m]) -> CAN Device Drivers -> Platform CAN drivers with Netlink support (CAN_DEV [=m]) -> Philips/NXP SJA1000 devices (CAN_SJA1000 [=m])

At the bottom of this tree, be sure to set M in both "TS-CAN1 PC104 boards" and "ISA Bus based legacy SJA1000 driver"

During startup, you will need to include this command to load the driver:
modprobe sja1000_isa mem=0x81004c00 irq=65 clk=24000000

Before using the CAN network interface, you will need to bring it up in the normal manner:
ip link set can0 type can bitrate 125000

ifconfig can0 up

From there the interface is up and available for your usage.

For your convenience, the can-utils package is already compiled and included in the default shipping TS-7250-V2 image. Further information on that package is available on the package's github page: https://github.com/linux-can/can-utils

It is also strongly recommended to fully read and understand the Linux Kernel documentation on SocketCAN, located here: https://www.kernel.org/doc/Documentation/networking/can.txt