1      Scope of Document

This document describes can bus hardware design and can bus driver development and can test

2      Requiremen

2.1     Function Requirement

Use can bus in am335x, user space use socketcan interface

2.2     Performance Requirement

Support can 2.0A

3      Hardware Overview

Can bus interface,pin map:

AM335X_CAN0_RX -------------UART1_RTSn

AM335X_CAN0_TX -------------UART1_CTSn

 

Figure 1 can bus interface block diagram

4      Functional Description

4.1     Functional Block Diagram

Figure 2  CAN bus connect to IOS1050DUBR CAN TRANSCEIVER

Can bus can0 connect to  ISO1050, ISO1050 is a galvanically isolated CAN transceiver that meets or exceeds the specifications of the ISO11898 standard

4.2     Can bus specification

4.2.1 Overview

Can  Architechture:

CAN is a multi-master serial bus standard for connecting Electronic Control Units [ECUs] also known as nodes. Two or more nodes are required on the CAN network to communicate. The complexity of the node can range from a simple I/O device up to an embedded computer with a CAN interface and sophisticated software. The node may also be a gateway allowing a standard computer to communicate over a USB or Ethernet port to the devices on a CAN network.

Can Node Architechture:

Can bus high speed signal:

Can bus low speed signal:

4.2.2 Block diagram

Can总线如何仲裁:

CAN BUS arbitration ,For example, consider an 11-bit ID CAN network, with two nodes with IDs of 15 (binary representation, 00000001111) and 16 (binary representation, 00000010000). If these two nodes transmit at the same time, each will first transmit the start bit then transmit the first six zeros of their ID with no arbitration decision being made.

Can总线的帧格式4种,及扩展格式说明如下

Frames[edit]

A CAN network can be configured to work with two different message (or "frame") formats: the standard or base frame format (described in CAN 2.0 A and CAN 2.0 B), and the extended frame format (only described by CAN 2.0 B). The only difference between the two formats is that the "CAN base frame" supports a length of 11 bits for the identifier, and the "CAN extended frame" supports a length of 29 bits for the identifier, made up of the 11-bit identifier ("base identifier") and an 18-bit extension ("identifier extension"). The distinction between CAN base frame format and CAN extended frame format is made by using the IDE bit, which is transmitted as dominant in case of an 11-bit frame, and transmitted as recessive in case of a 29-bit frame. CAN controllers that support extended frame format messages are also able to send and receive messages in CAN base frame format. All frames begin with a start-of-frame (SOF) bit that denotes the start of the frame transmission.

CAN has four frame types:

Data frame: a frame containing node data for transmission

Remote frame: a frame requesting the transmission of a specific identifier

Error frame: a frame transmitted by any node detecting an error

Overload frame: a frame to inject a delay between data or remote frame

Data frame[edit]

The data frame is the only frame for actual data transmission. There are two message formats:

Base frame format: with 11 identifier bits

Extended frame format: with 29 identifier bits

The CAN standard requires the implementation must accept the base frame format and may accept the extended frame format, but must tolerate the extended frame format.

Base frame format

The frame format is as follows: The bit values are described for CAN-LO signal.

Extended frame format[edit]

The frame format is as follows:

The two identifier fields (A & B) combine to form a 29-bit identifier.

Remote frame[edit]

Generally data transmission is performed on an autonomous basis with the data source node (e.g., a sensor) sending out a Data Frame. It is also possible, however, for a destination node to request the data from the source by sending a Remote Frame.

There are two differences between a Data Frame and a Remote Frame. Firstly the RTR-bit is transmitted as a dominant bit in the Data Frame and secondly in the Remote Frame there is no Data Field. The DLC field indicates the data length of the requested message (not the transmitted one)

i.e.,

RTR = 0 ; DOMINANT in data frame

RTR = 1 ; RECESSIVE in remote frame

In the event of a Data Frame and a Remote Frame with the same identifier being transmitted at the same time, the Data Frame wins arbitration due to the dominant RTR bit following the identifier.

Error frame[edit]

The error frame consists of two different fields:

The first field is given by the superposition of ERROR FLAGS (6–12 dominant/recessive bits) contributed from different stations.

The following second field is the ERROR DELIMITER (8 recessive bits).

There are two types of error flags:

Active Error Flag

six dominant bits – Transmitted by a node detecting an error on the network that is in error state "error active".

Passive Error Flag

six recessive bits – Transmitted by a node detecting an active error frame on the network that is in error state "error passive".

There are two error counters in CAN:

1. Transmit error counter (TEC)

2. Receive error counter (REC)

When TEC or REC is greater than 127 and lesser than 255, a Passive Error frame will be transmitted on the bus.

When TEC and REC is lesser than 128, an Active Error frame will be transmitted on the bus.

When TEC is greater than 255, then the node enters into Bus Off state, where no frames will be transmitted.

Overload frame[edit]

The overload frame contains the two bit fields Overload Flag and Overload Delimiter. There are two kinds of overload conditions that can lead to the transmission of an overload flag:

The internal conditions of a receiver, which requires a delay of the next data frame or remote frame.

Detection of a dominant bit during intermission.

The start of an overload frame due to case 1 is only allowed to be started at the first bit time of an expected intermission, whereas overload frames due to case 2 start one bit after detecting the dominant bit. Overload Flag consists of six dominant bits. The overall form corresponds to that of the active error flag. The overload flag’s form destroys the fixed form of the intermission field. As a consequence, all other stations also detect an overload condition and on their part start transmission of an overload flag. Overload Delimiter consists of eight recessive bits. The overload delimiter is of the same form as the error delimiter.

ACK slot[edit]

The acknowledge slot is used to acknowledge the receipt of a valid CAN frame. Each node that receives the frame without finding an error, transmits a dominant level in the ACK slot and thus overrides the recessive level of the transmitter. If a transmitter detects a recessive level in the ACK slot it knows that no receiver found a valid frame. A receiving node may transmit a recessive to indicate that it did not receive a valid frame, but another node that did receive a valid frame may override this with a dominant. The transmitting node cannot know that the message has been received by all of the nodes on the CAN network.

Often, the mode of operation of the device is to re-transmit unacknowledged frames over and over. This may lead to eventually entering the "error passive" state.

Interframe spacing[edit]

Data frames and remote frames are separated from preceding frames by a bit field called interframe space. Interframe space consists of at least three consecutive recessive (1) bits. Following that, if a dominant bit is detected, it will be regarded as the "Start of frame" bit of the next frame. Overload frames and error frames are not preceded by an interframe space and multiple overload frames are not separated by an interframe space. Interframe space contains the bit fields intermission and bus idle, and suspend transmission for error passive stations, which have been transmitter of the previous message.[13]

Can总线上帧消息通过ACK slot进行应答,但是缺点是有可以被其它接收结点覆盖。

ACK slot[edit]

The acknowledge slot is used to acknowledge the receipt of a valid CAN frame. Each node that receives the frame without finding an error, transmits a dominant level in the ACK slot and thus overrides the recessive level of the transmitter. If a transmitter detects a recessive level in the ACK slot it knows that no receiver found a valid frame. A receiving node may transmit a recessive to indicate that it did not receive a valid frame, but another node that did receive a valid frame may override this with a dominant. The transmitting node cannot know that the message has been received by all of the nodes on the CAN network.

Often, the mode of operation of the device is to re-transmit unacknowledged frames over and over. This may lead to eventually entering the "error passive" state.

Can总线如何区分不同的帧消息:通过在总线上结束帧后面发送连续的至少3个隐性位1.

Interframe spacing[edit]

Data frames and remote frames are separated from preceding frames by a bit field called interframe space. Interframe space consists of at least three consecutive recessive (1) bits. Following that, if a dominant bit is detected, it will be regarded as the "Start of frame" bit of the next frame. Overload frames and error frames are not preceded by an interframe space and multiple overload frames are not separated by an interframe space. Interframe space contains the bit fields intermission and bus idle, and suspend transmission for error passive stations, which have been transmitter of the previous message.[13]

CAN总线通过位填充来保证同步。

Bit stuffing[edit]

To ensure enough transitions to maintain synchronization, a bit of opposite polarity is inserted after five consecutive bits of the same polarity. This practice is called bit stuffing, and is necessary due to the non-return to zero (NRZ) coding used with CAN. The stuffed data frames are destuffed by the receiver.

All fields in the frame are stuffed with the exception of the CRC delimiter, ACK field and end of frame which are a fixed size and are not stuffed. In the fields where bit stuffing is used, six consecutive bits of the same polarity (111111 or 000000) are considered an error. An active error flag can be transmitted by a node when an error has been detected. The active error flag consists of six consecutive dominant bits and violates the rule of bit stuffing.

Bit stuffing means that data frames may be larger than one would expect by simply enumerating the bits shown in the tables above. The maximum increase in size of a CAN frame (base format) after bit stuffing is in the case

11111000011110000...

which is stuffed as (stuffing bits in bold):

111110000011111000001...

The stuffing bit itself may be the first of the five consecutive identical bits, so in the worst case there is one stuffing bit per four original bits.

The size is bounded by

in the worst case one bit will be added every four original bits after the first one (hence the −1 at the numerator) and, because of the layout of the bits of the header, only 34 out of 44 of them can be subject to bit stuffing.

An undesirable side effect of the bit stuffing scheme is that a small number of bit errors in a received message may corrupt the destuffing process, causing a larger number of errors to propagate through the destuffed message. This reduces the level of protection that would otherwise be offered by the CRC against the original errors. This deficiency of the protocol has been addressed in CAN FD frames by the use of a combination of fixed stuff bits and a counter that records the number of stuff bits inserted.

5      Interface

5.1     Driver 4.14.40

Dts file modify:

Index: arch/arm/boot/dts/am335x-evm.dts

dcan0_pins_default: dcan0_pins_default {

pinctrl-single,pins = <

AM33XX_IOPAD(0x978, PIN_OUTPUT | MUX_MODE2) /* uart1_ctsn.d_can0_tx */

AM33XX_IOPAD(0x97c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* uart1_rtsn.d_can0_rx */

>;

};

};

&dcan0 {

status = "okay";   /* Enable only if Profile 1 is selected */

pinctrl-names = "default";

pinctrl-0 = <&dcan0_pins_default>;

};

kernel config

# CONFIG_NET_PKTGEN is not set

# CONFIG_HAMRADIO is not set

+CONFIG_CAN=y

+CONFIG_CAN_RAW=y

+CONFIG_CAN_BCM=y

+CONFIG_CAN_GW=y

#

# CAN Device Drivers

@@ -1172,20 +1172,20 @@

# CONFIG_CAN_VCAN is not set

# CONFIG_CAN_VXCAN is not set

# CONFIG_CAN_SLCAN is not set

+CONFIG_CAN_DEV=y

CONFIG_CAN_CALC_BITTIMING=y

# CONFIG_CAN_LEDS is not set

# CONFIG_CAN_FLEXCAN is not set

# CONFIG_CAN_GRCAN is not set

# CONFIG_CAN_TI_HECC is not set

+CONFIG_CAN_C_CAN=y

+CONFIG_CAN_C_CAN_PLATFORM=y

# CONFIG_CAN_C_CAN_PCI is not set

# CONFIG_CAN_CC770 is not set

# CONFIG_CAN_IFI_CANFD is not set

+CONFIG_CAN_M_CAN=y

# CONFIG_CAN_PEAK_PCIEFD is not set

+CONFIG_CAN_RCAR=y

# CONFIG_CAN_RCAR_CANFD is not set

# CONFIG_CAN_SJA1000 is not set

# CONFIG_CAN_SOFTING is not set

kerenl print info

[    1.090016] c_can_platform 481cc000.can: c_can_platform device registered (regs=fa1cc000, irq=37)

[    1.431054] can: controller area network core (rev 20170425 abi 9)

[    1.441954] can: raw protocol (rev 20170425)

[    1.446329] can: broadcast manager protocol (rev 20170425 t)

[    1.452066] can: netlink gateway (rev 20170425) max_hops=1

root@am335x-evm:~# cat /proc/net/dev

Inter-|   Receive                                                |  Transmit

face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed

eth0:    2788      23    0    0    0     0          0         0     3920      35    0    0    0     0       0          0

lo:   18908     248    0    0    0     0          0         0    18908     248    0    0    0     0       0          0

sit0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0

can0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0

eth1:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0

5.2     Application Interface

就像TCP/IP协议一样,在使用CAN网络之前你首先需要打开一个套接字。CAN的套接字使用到了一个新的协议族,所以在调用socket(2)这个系统函数的时候需要将PF_CAN作为第一个参数。当前有两个CAN的协议可以选择,一个是原始套接字协议( raw socket protocol),另一个是广播管理协议BCM(broadcast manager)。你可以这样来打开一个套接字:

s
= socket(PF_CAN, SOCK_RAW, CAN_RAW);

或者

s
= socket(PF_CAN, SOCK_DGRAM, CAN_BCM);

在成功创建一个套接字之后,你通常需要使用bind(2)函数将套接字绑定在某个CAN接口上(这和TCP/IP使用不同的IP地址不同,参见第3章)。在绑定 (CAN_RAW)或连接(CAN_BCM)套接字之后,你可以在套接字上使用read(2)/write(2),也可以使用send(2)/sendto(2)/sendmsg(2)和对应的recv*操作。当然也会有CAN特有的套接字选项,下面将会说明。

基本的CAN帧结构体和套接字地址结构体定义在include/linux/can.h:

/*

* 扩展格式识别符由 29 位组成。其格式包含两个部分:11 位基本 ID、18 位扩展 ID。
* Controller Area Network Identifier structure
*
* bit
0-28     : CAN识别符 (11/29 bit)
* bit 29     : 错误帧标志 (0 = data frame, 1 = error
frame)
* bit 30     : 远程发送请求标志 (1 = rtr frame)

* bit
31     :帧格式标志 (0 = standard 11 bit, 1 = extended
29 bit)
*/
typedef __u32 canid_t;

struct can_frame {

canid_t
can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */
      __u8    can_dlc; /* 数据长度: 0 .. 8 */
      __u8    data[8] __attribute__((aligned(8)));

};

结构体的有效数据在data[]数组中,它的字节对齐是64bit的,所以用户可以比较方便的在data[]中传输自己定义的结构体和共用体。CAN总线中没有默认的字节序。在CAN_RAW套接字上调用read(2),返回给用户空间的数据是一个struct can_frame结构体。

就像PF_PACKET套接字一样,sockaddr_can结构体也有接口的索引,这个索引绑定了特定接口:

struct
sockaddr_can {

sa_family_t
can_family;
        
 int         can_ifindex;
          union {

/* transport protocol class
address info (e.g. ISOTP) */
                   
struct { canid_t rx_id, tx_id; } tp;
                   
/* reserved for future CAN protocols address information */

} can_addr;

};

指定接口索引需要调用ioctl()(比如对于没有错误检查CAN_RAW套接字):

int s;

struct
sockaddr_can addr;

struct ifreq
ifr;

s =
socket(PF_CAN, SOCK_RAW, CAN_RAW);

strcpy(ifr.ifr_name, "can0" );

ioctl(s, SIOCGIFINDEX, &ifr);

addr.can_family = AF_CAN;

addr.can_ifindex = ifr.ifr_ifindex;

bind(s,
(struct sockaddr *)&addr, sizeof(addr));

(..)

为了将套接字和所有的CAN接口绑定,接口索引必须是0。这样套接字便可以从所有使能的CAN接口接收CAN帧。recvfrom(2)可以指定从哪个接口接收。在一个已经和所有CAN接口绑定的套接字上,sendto(2)可以指定从哪个接口发送。

从一个CAN_RAW套接字上读取CAN帧也就是读取struct can_frame结构体:

struct
can_frame frame;

nbytes =
read(s, &frame, sizeof(struct can_frame));

if (nbytes
< 0) {

perror("can raw socket read");

return 1;

}

/* paranoid
check ... */

if (nbytes
< sizeof(struct can_frame)) {

fprintf(stderr, "read: incomplete CAN frame\n");

return 1;

}

/* do
something with the received CAN frame */

写CAN帧也是类似的,需要用到write (2)函数:

nbytes =
write(s, &frame, sizeof(struct can_frame));

如果套接字跟所有的CAN接口都绑定了(addr.can_index = 0),推荐使用recvfrom(2)获取数据源接口的信息:

struct
sockaddr_can addr;

struct ifreq
ifr;

socklen_t
len = sizeof(addr);

struct
can_frame frame;

nbytes =
recvfrom(s, &frame, sizeof(struct can_frame),

0, (struct sockaddr*)&addr, &len);

/* get
interface name of the received CAN frame */

ifr.ifr_ifindex = addr.can_ifindex;

ioctl(s,
SIOCGIFNAME, &ifr);

printf("Received a CAN frame from interface %s", ifr.ifr_name);

对于绑定了所有接口的套接字,向某个端口发送数据必须指定接口的详细信息:

strcpy(ifr.ifr_name, "can0");

ioctl(s,
SIOCGIFINDEX, &ifr);

addr.can_ifindex = ifr.ifr_ifindex;

addr.can_family  = AF_CAN;

nbytes =
sendto(s, &frame, sizeof(struct can_frame),

0, (struct sockaddr*)&addr, sizeof(addr));

4.1 使用can_filter的原始套接字 (RAW socket)

----------------------------------------------------

CAN_RAW套接字的用法和CAN字符设备的用法是类似的。为了使用CAN套接字的新特性,在绑定原始套接字的时候将会默认开启以下特性:

- filter将会接收所有的数据

- 套接字仅仅接收有效的数据帧(=> no error frames)

- 发送帧的回环功能被开启(参见 3.2节)

- (回环模式下)套接字不接收它自己发送的帧

这些特性的设置可以在绑定之前和之后修改。为了使用CAN_RAW套接字相关的选项,必须包含<linux/can/raw.h>。

  • 4.1.1 原始套接字选项 CAN_RAW_FILTER

CAN_RAW套接字的接收可以使用CAN_RAW_FILTER套接字选项指定的多个过滤规则(过滤器)来过滤。

过滤规则(过滤器)的定义在 include/linux/can.h中:

struct
can_filter {

canid_t can_id;

canid_t can_mask;

};

过滤规则的匹配:

<received_can_id> & mask == can_id & mask

/*

#define CAN_INV_FILTER 0x20000000U
/* to be set in can_filter.can_id */

#define CAN_ERR_FLAG  
0x20000000U /* error frame */

*/

这和大家所熟知的CAN控制器硬件过滤非常相似。可以使用 CAN_INV_FILTER这个宏将can_filter结构体的成员can_id中的比特位反转。和CAN控制器的硬件过滤形成鲜明对比的是,用户可以为每一个打开的套接字设置多个独立的过滤规则(过滤器):

/*

/* valid bits in CAN ID for frame
formats */

#define CAN_SFF_MASK 0x000007FFU
/* 标准帧格式 (SFF) */
#define CAN_EFF_MASK 0x1FFFFFFFU /* 扩展帧格式 (EFF) */
#define CAN_ERR_MASK 0x1FFFFFFFU /* 忽略EFF, RTR, ERR标志 */

*/

struct
can_filter rfilter[2];

rfilter[0].can_id   = 0x123;

rfilter[0].can_mask = CAN_SFF_MASK;

rfilter[1].can_id   = 0x200;

rfilter[1].can_mask = 0x700;

setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));

为了在指定的CAN_RAW套接字上禁用接收过滤规则,可以这样:

setsockopt(s,
SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);

在一些极端情况下不需要读取数据,可以把过滤规则清零(所有成员设为0),这样原始套接字就会忽略接收到的CAN帧。在这种仅仅发送数据(不读取)的应用中可以在内核中省略接收队列,以此减少CPU的负载(虽然只能减少一点点)。

  • 原始套接字选项 CAN_RAW_ERR_FILTER

正如3.4节所说,CAN接口驱动可以选择性的产生错误帧,错误帧和正常帧以相同的方式传给应用程序。可能产生的错误被分为不同的种类,使用适当的错误掩码可以过滤它们。为了注册所有可能的错误情况,CAN_ERR_MASK(0x1FFFFFFFU)这个宏可以用来作为错误掩码。这个错误掩码定义在linux/can/error.h。

can_err_mask_t err_mask = ( CAN_ERR_TX_TIMEOUT | CAN_ERR_BUSOFF );

setsockopt(s, SOL_CAN_RAW, CAN_RAW_ERR_FILTER,

&err_mask, sizeof(err_mask));

  • 原始套接字选项 CAN_RAW_LOOPBACK

为了满足众多应用程序的需要,本地回环功能默认是开启的(详细情况参考3.2节)。但是在一些嵌入式应用场景中(比如只有一个用户在使用CAN总线),回环功能可以被关闭(各个套接字之间是独立的):

int loopback
= 0; /* 0 = disabled, 1 = enabled (default) */

setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback, sizeof(loopback));

  • 原始套接字选项 CAN_RAW_RECV_OWN_MSGS

在本地回环功能开启的情况下,所有的发送帧都会被回环到在相应CAN接口上注册了同样CAN-ID(和发送帧的相同)的套接字上。发送CAN帧的套接字被假设不想接收自己发送的CAN帧,因此在发送套接字上的回环功能默认是关闭的。可以在需要的时候改变这一默认行为:

int
recv_own_msgs = 1; /* 0 = disabled (default), 1 = enabled */

setsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,

&recv_own_msgs, sizeof(recv_own_msgs));

6     
Example

#include <stdio.h>

#include <string.h>

#include <sys/socket.h>

#include <linux/sockios.h>

#include <linux/if.h>

#include <pthread.h>

#include "can.h"

#define PF_CAN 29

#define AF_CAN PF_CAN

#define SIOCSCANBAUDRATE        (SIOCDEVPRIVATE+0)

#define SIOCGCANBAUDRATE        (SIOCDEVPRIVATE+1)

#define SOL_CAN_RAW (SOL_CAN_BASE + CAN_RAW)

#define CAN_RAW_FILTER  1

#define CAN_RAW_RECV_OWN_MSGS 0x4

typedef __u32 can_baudrate_t;

struct ifreq ifr;

int init_can(char* can) {

int
sock;

struct
sockaddr_can addr;

//struct
ifreq ifr;

sock =
socket(PF_CAN, SOCK_RAW, CAN_RAW);

if(sock
< 0) {

printf("error\n");

return
-1;

}

addr.can_family
= AF_CAN;

strcpy(ifr.ifr_name,
can );

int
ret;

ret =
ioctl(sock, SIOCGIFINDEX, &ifr); 
//get index

if(ret
&& ifr.ifr_ifindex == 0) {

printf("Can't
get interface index for can0, code= %d, can0 ifr_ifindex value: %d, name:
%s\n", ret, ifr.ifr_ifindex, ifr.ifr_name);

close(sock);

return
-1;

}

printf("%s
can_ifindex = %x\n",ifr.ifr_name,ifr.ifr_ifindex);

addr.can_ifindex
= ifr.ifr_ifindex;

//ioctl(sock,SIOCGIFNAME,&ifr);

//printf("ret
= %d can0 can_ifname = %s\n",ret,ifr.ifr_name);

int
recv_own_msgs = 0;//set loop back:  1
enable 0 disable

setsockopt(sock,
SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,&recv_own_msgs, sizeof(recv_own_msgs));

if
(bind(sock,(struct sockaddr*)&addr,sizeof(addr))<0) {

printf("bind
error\n");

close(sock);

return
-1;

}

return
sock;

}

void Can_Read_thread(void* psock)

{

int
sock = *(int *)psock;

int i =
0;

struct
can_frame frame;

while(1)
{

memset(&frame,0,sizeof(struct can_frame));

read(sock,&frame,sizeof(struct
can_frame));

if(frame.can_dlc)

{

printf("\n%s
DLC:%d Data:", ifr.ifr_name, frame.can_dlc);

for(i
= 0; i < frame.can_dlc; i++)

{

printf("%#x
",frame.data[i]);

}

printf("\n");

}

}

}

int Write_Can_Data(int sock,char* str,int len)

{

struct
can_frame frame;

int i;

int
nbytes = 0;

frame.can_id
= 0x0; //can device id

while(len)
{

if(len
> sizeof(frame.data)) {

memset(&frame.data,0,sizeof(frame.data));

memcpy(&frame.data,str,sizeof(frame.data));

//printf("%d,(%s)\r\n",sizeof(frame.data),frame.data);

frame.can_dlc
= sizeof(frame.data);

str
+= sizeof(frame.data);

len
-= sizeof(frame.data);

}

else
{

memset(&frame.data,0,sizeof(frame.data));

memcpy(&frame.data,str,len);

//printf("%d,(%s)\r\n",len,frame.data);

frame.can_dlc
= len;

str
= NULL;

len
= 0;

}

write(sock,
&frame, sizeof(struct can_frame));

usleep(100);

}

}

int main(int argc ,char** argv)

{

int
sock;

int
nbytes;

pthread_t
canthreadid;

int
ret;

char
str[4096];

if(argc
< 2) {

printf("Usage:
%s <device>(can0/can1)\n", argv[0]);

return
0;

}

sock =
init_can(argv[1]);

if(sock
< 0)

{

return
0;

}

ret=pthread_create(&canthreadid,NULL,(void*)Can_Read_thread,&sock);

while(1)
{

printf("Please
Input string to send to %s\n:",argv[1]);

scanf("%s",
str);

if(strlen(str)>0)

Write_Can_Data(sock,str,strlen(str));

}

close(sock);

printf("ok\n");

return
0;

}

am335x system upgrade kernel can(八)的更多相关文章

  1. am335x system upgrade kernel emmc(十八)

    1      Scope of Document This document describes EMMC hardware design 2      Requiremen 2.1     Func ...

  2. am335x system upgrade kernel tf(五)

    1      Scope of Document This document describes TF hardware design 2      Requiremen 2.1     Functi ...

  3. am335x system upgrade kernel ethernet(四)

    1      Scope of Document This document describes ethernet hardware design and porting KZS8081 to ubo ...

  4. am335x system upgrade kernel gpio(九)

    1      Hardware Overview gpio interface,pin map: AM335X_I2C0_W_C----------------------MCASP0_AXR1 /* ...

  5. am335x system upgrade kernel uart(七)

    1      Scope of Document This document describes UART hardware design, uart driver porting 2      Re ...

  6. am335x system upgrade kernel i2c rtc eeprom(六)

    1      Scope of Document This document describes i2c bus hardware design and support i2c-devices: ee ...

  7. am335x system upgrade kernel ec20 simcom7600ce(十一)

    1      Scope of Document This document describes 4G hardware design, support quectel ec20 4G module/ ...

  8. am335x system upgrade kernel usb stroage(十)

    1      Scope of Document This document describes USB hardware design, support stardard usb2.0 port o ...

  9. am335x system upgrade kernel f-ram fm25l16b(十六)

    1      Scope of Document This document describes SPI F-RAM hardware design 2      Requiremen 2.1     ...

随机推荐

  1. 『Go基础』第8节 格式化输出

    输出就是将数据信息打印到电脑屏幕上. 本节我们就来学习一下Go语言中的三种输出方式: Print().Println().Printf(). 1.Print() Print()主要的一个特点就是打印数 ...

  2. iOS核心动画(基础篇)

    Core Animation相关内容基本介绍 此框架把屏幕上的内容组合起来,这个内容被分解成图层,放到图层树中,这个树形成了你能在应用程序看到的内容的基础 图层在iOS中就是CALayer类 当我们创 ...

  3. Ted演讲 The secrets of learning a new language

    第一次写这么多英文~~对照双语字幕整理的~~ 这是我很喜欢的一个演讲~~ 让我们一起学英文吧 l  I love learning foreign languages. l  In fact, I l ...

  4. 原子类 Atomic

    @Testpublic void testAtomicBoolean() { AtomicBoolean atomicBoolean = new AtomicBoolean(); boolean b ...

  5. 进入恢复模式(Recovery HD)

    进入恢复模式(Recovery HD) 1,选中要启动的虚拟机,随后点击VM菜单的启动按钮后面向下箭头,随后点击菜单项”打开电源时进入固件“. 2,在虚拟机里面,用上下键移动到”Enter setup ...

  6. 心知天气数据API 产品的高并发实践

    心知天气数据API 产品的高并发实践 心知天气作为国内领先的商业气象服务提供商,天气数据API 产品从公司创立以来就一直扮演着很重要的角色.2009 年API 产品初次上线,历经十年,我们不断用心迭代 ...

  7. 单例模式的双重锁为什么要加volatile(转)

    单例模式如下: 需要volatile关键字的原因是,在并发情况下,如果没有volatile关键字,在第5行会出现问题. instance = new TestInstance();可以分解为3行伪代码 ...

  8. input file 无法打开手机端文件选择器

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/m0_37805167/article/details/78538044手机端对input file的 ...

  9. php后台实现页面跳转的方法-转载

    地址:http://blog.csdn.net/abandonship/article/details/6459104 其中方法三的js代码在tp框架使用存在故障,一个是需要把代码写在一起(可能也不需 ...

  10. vue 生命周期的详解

    一.vue生命周期的解析 > 1>什么是vue生命周期 每个vue实例在被创建之前都要经过一系列的初始化过程,这个过程就是vue的生命周期.详细来说,就是Vue实例从开始创建,初始化数据, ...