1. S32G网关开发环境搭建与首个CAN报文收发
任务目标
在 S32G 开发板上完成交叉编译、调试、烧录环境搭建,并运行一个最小 CAN 程序:通过 CAN0 发送一帧标准数据帧(ID=0x123,8 字节),同时接收总线上的报文并打印。
环境与依赖
- 主机:Ubuntu 20.04/22.04,已安装
gcc-aarch64-linux-gnu、gdb-multiarch、make。 - 目标:S32G 开发板运行 Linux(BSP 提供
can0接口),通过串口或网口登录。 - 烧录:使用 NXP S32G BSP 提供的
flash.sh(或 UUU)将镜像写入 SD/eMMC;本案例假设 BSP 已烧录并可启动。 - CAN 收发:使用 Linux SocketCAN,无需额外库。
交叉编译与调试链路
核心代码:can_demo.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
int main(void)
{
int s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (s < 0) { perror("socket"); return 1; }
struct ifreq ifr;
strcpy(ifr.ifr_name, "can0");
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { perror("ioctl"); return 1; }
struct sockaddr_can addr = {0};
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("bind"); return 1; }
/* 发送一帧标准数据帧:ID=0x123, 8 字节 */
struct can_frame tx = {0};
tx.can_id = 0x123;
tx.can_dlc = 8;
for (int i = 0; i < 8; i++) tx.data[i] = i;
if (write(s, &tx, sizeof(tx)) != sizeof(tx)) { perror("write"); return 1; }
printf("TX id=0x%X dlc=%d\n", tx.can_id, tx.can_dlc);
/* 接收一帧并打印 */
struct can_frame rx;
int n = read(s, &rx, sizeof(rx));
if (n < 0) { perror("read"); return 1; }
printf("RX id=0x%X dlc=%d data=", rx.can_id & CAN_EFF_MASK, rx.can_dlc);
for (int i = 0; i < rx.can_dlc; i++) printf("%02X ", rx.data[i]);
printf("\n");
close(s);
return 0;
}
编译、部署与运行
# 1. 交叉编译
aarch64-linux-gnu-gcc -O2 -Wall -o can_demo can_demo.c
# 2. 传输到开发板
scp can_demo root@<board_ip>:/root/
# 3. 开发板上配置 CAN(500kbps)
ip link set can0 type can bitrate 500000
ip link set can0 up
# 4. 运行
./can_demo
验证方法与通过条件
- 终端打印
TX id=0x123 dlc=8,说明发送成功。 - 若总线上有另一节点(或回环模式)发送报文,程序打印
RX id=... dlc=... data=...,说明接收成功。 - 无对端时可用回环验证:
ip link set can0 type can bitrate 500000 loopback on,再运行程序,应能收到自己发出的 0x123 帧。 - 调试:
gdb-multiarch ./can_demo,在开发板运行gdbserver :1234 ./can_demo,主机target remote <board_ip>:1234。