1.参考Xavier官方刷机教程,将xavier置于Forece Recorery模式,Host主机安装SDK Manager
此处需要注意:TARGET OPERATING SYSTEM对应的版本一定要选择JetPack4.4, 否则can总线将无法正常启用
2.在Nvidia Jetson Xavier开发者套件上启用CAN总线,直接按照前辈的教程一步步走完全没问题。
(随便接的,比较丑)
3.安装can-utills测试一下收发正常,摘录的部分工程代码如下
socket_can.h
#include <pthread.h>
#include <stdint.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <string>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <linux/can/error.h>
#include <linux/net_tstamp.h>
#define SET_CAN0_BAUDRATE "sudo ip link set can0 type can bitrate "
#define SET_CAN1_BAUDRATE "sudo ip link set can1 type can bitrate "
#define CAN_FD_ON " dbitrate 2000000 berr-reporting on fd on"
#define CAN0_OPEN "sudo ip link set up can0"
#define CAN1_OPEN "sudo ip link set up can1"
/* set transmit queue length: small value for slower device with a high latency, hight value is recommended for server connected with high-speed internet connections the perform large data transfers */
#define CAN0_LENGTH "sudo ip link set can0 txqueuelen 1000"
#define CAN1_LENGTH "sudo ip link set can1 txqueuelen 1000"
#define CAN0_CLOSE "sudo ip link set down can0"
#define CAN1_CLOSE "sudo ip link set down can1"
// bool Write(const vector<can_frame>&);
// int Read(vector<can_frame::Frame>&);
static void* ReceiveFunc(void* param);
static void* TransmitFunc(void* param);
pthread_t thread_0_;
pthread_t thread_1_;
static int run_flag_;
// vector<can_frame> can_buf_1_;
// vector<can_frame> can_buf_2_;
// void* handle_ = nullptr;
uint32_t receive_msgs_count;
uint8_t kbaudrate_port0 = 500000; // 250000 1000000
uint8_t kbaudrate_port1 = 500000;
uint8_t raw_socket_;
struct ifreq ifr_;
struct sockaddr_can addr_;
const char bus_name0[5] = "can0";
const char bus_name1[5] = "can1";
};
socket_can.cpp
#include <socket_can.h>
#include <iostream>
#include <cstring>
using std::system;
using std::cout;
using std::endl;
int main(int argc, int** argv) {
// 初始化,打开can控制器
system(CAN0_CLOSE);
system(CAN1_CLOSE);
system((SET_CAN0_BAUDRATE + std::to_string(kbaudrate_port0)).c_str());
system((SET_CAN1_BAUDRATE + std::to_string(kbaudrate_port1)).c_str());
system(CAN0_OPEN);
system(CAN0_LENGTH);
system(CAN1_OPEN);
system(CAN1_LENGTH);
raw_socket_ = socket(PF_CAN, SOCK_RAW, CAN_RAW);
addr_.can_ifindex = 0; /* 0 means any can interface */
addr_.can_family = PF_CAN;
int ret = bind(raw_socket_, (struct sockaddr*)&addr_, sizeof(addr_);
run_flag_ = 1;
if(ret < 0) {
cout << "Error while bind with socket" << endl;
close(raw_socket_);
run_flag_ = 0;
}
if(pthread_create(&thread_0_, NULL, ReceiveFunc, &run_flag_) != 0) {
std::perror("pthread_create ReceiveFunc error");
}
if(pthread_create(&thread_1_, NULL, TransmitFunc, &run_flag_)) {
std::perror("pthread_create ReceiveFunc error");
}
usleep(5000);
close(raw_socket_);
return 0;
}
void* ReceiveFunc(void* param) {
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
const int timestamp_flag = SOF_TIMESTAMPING_RX_SOFTWARE;
timeval socket_timestamp;
can_frame frame_raw;
socklen_t receive_length = sizeof(addr_);
int* run = static_cast<int*>(param);
setsockopt(raw_socket_, SOL_SOCKET, SO_TIMESTAMPING, ×tamp_flag, sizeof(timestamp_flag));
while((*run)& 0x0f) {
pthread_rwlock_wrlock(&socket_rwlock);
int ret = recvfrom(raw_socket_, &frame_raw, sizeof(frame_raw), 0, (struct sockaddr*)&addr_, &receive_length);
if(ret <= 0) { // ret is frame_raw.size()
ROS_ERROR_STREAM("receive nothing or receive message fail!");
}
pthread_rwlock_unlock(&socket_rwlock);
if(frame_raw.can_id == (uint)(0x120 & CAN_SFF_MASK) {
receive_msgs_count++;
cout << "Receive msgs 0x120:" << receive_msgs_count << endl;
}
}
pthread_exit(0);
}
void* TransmitFunc(void* param) {
can_frame transmit_msgs;
transmit_msgs.can_id = 0x501;
transmit_msgs.can_dlc = 5;
transmit_msgs.Data[0] = 0x11;
transmit_msgs.Data[1] = 0x22;
transmit_msgs.Data[2] = 0x33;
transmit_msgs.Data[3] = 0x44;
transmit_msgs.Data[4] = 0x55;
transmit_msgs.Data[5] = 0x66;
strcpy(ifr_.ifr_name, bus_name0);
addr_.can_ifindex = ifr_.ifr_ifindex;
ioctl(raw_socket_, SIOGIFINDEX, &ifr_);
int nbytes = sendto(raw_socket_, &transmit_msgs, sizeof(struct can_frame), 0, (struct sockaddr*)&addr_, sizeof(addr_));
}