1. S32G网关开发环境搭建与首个CAN报文收发

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 aarch64-linux-gnu-gcc 交叉编译 scp 传输 到开发板 S32G 运行 can0 收发

核心代码: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。