//#include "someip_client.hpp" //#include "someip_client_cfg.hpp" #include "spi_server.hpp" #include "spi_protocol.hpp" #ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING // client *my_client_ptr(nullptr); // void client_handle_signal(int _signal) { // if (my_client_ptr != nullptr && // (_signal == SIGINT || _signal == SIGTERM // || _signal == SIGKILL)) // my_client_ptr->stop(); // } #endif /* * spi_slave_recv_loop.c - SPI从设备持续接收程序 * * 功能:SoC作为SPI从设备,配置与MCU主设备对齐,循环接收并打印数据 * MCU每秒发送一帧(8字节) * * MCU主设备配置(需对齐): * Mode : SPI_MODE_0 (CPOL=0, CPHA=0) * Bits/Word : 8 * Speed : 1 MHz * 发送数据 : {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08} * * 编译:aarch64-linux-gnu-gcc -o spi_slave_recv_loop spi_slave_recv_loop.c * 运行:./spi_slave_recv_loop * 退出:按 Ctrl+C */ #include #include /* CAN 数据缓冲区 — SPI 线程写入,notifier 线程读取 */ std::vector g_can_data[CAN_CHANNEL_COUNT]; std::mutex g_can_mutex[CAN_CHANNEL_COUNT]; #include #include #include #include #include #include #include #include #include /* ========== SPI配置(必须与MCU主设备完全一致)========== */ #define SPI_DEVICE "/dev/spidev4.0" #define SPI_MODE SPI_MODE_3 /* CPOL=1, CPHA=1 */ #define SPI_BITS 8 #define SPI_SPEED 1000000 /* 1MHz */ #define FRAME_LEN SPI_PROTO_FRAME_SIZE /* 每帧SPI_PROTO_FRAME_SIZE字节 */ /* ===================================================== */ static volatile int keep_running = 1; void sigint_handler(int sig) { (void)sig; keep_running = 0; printf("\n[INFO] User interrupted, exiting...\n"); } void my_spi_server_thread_func(void* arg) { #ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING // signal(SIGINT, client_handle_signal); // signal(SIGTERM, client_handle_signal); // signal(SIGKILL, client_handle_signal); #endif uint8_t buf[FRAME_LEN]; int fd, ret; unsigned int frame_count = 0; /* 注册退出信号 */ signal(SIGINT, sigint_handler); /* 1. 打开 SPI 设备 */ fd = open(SPI_DEVICE, O_RDWR); if (fd < 0) { perror("open " SPI_DEVICE); return; } /* 2. 配置 SPI 模式 */ uint8_t mode = SPI_MODE; mode |= SPI_LSB_FIRST; ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); if (ret == -1) { perror("SPI_IOC_WR_MODE"); close(fd); return; } /* 3. 配置每字位数 */ uint8_t bits = SPI_BITS; ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); if (ret == -1) { perror("SPI_IOC_WR_BITS_PER_WORD"); close(fd); return; } /* 4. 配置最大时钟频率 */ uint32_t speed = SPI_SPEED; ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); if (ret == -1) { perror("SPI_IOC_WR_MAX_SPEED_HZ"); close(fd); return; } /* 5. 回读验证配置 */ ioctl(fd, SPI_IOC_RD_MODE, &mode); ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits); ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); printf("========================================\n"); printf("SPI Slave Config (aligned with MCU)\n"); printf("========================================\n"); printf("Device : %s\n", SPI_DEVICE); printf("Mode : %d (CPOL=%d, CPHA=%d)\n", mode, (mode & SPI_CPOL) ? 1 : 0, (mode & SPI_CPHA) ? 1 : 0); printf("Bits/Word : %d\n", bits); printf("Max Speed : %d Hz\n", speed); printf("Frame length: %d bytes\n", FRAME_LEN); printf("========================================\n"); printf("Waiting for MCU (master) to send data...\n"); printf("Press Ctrl+C to stop.\n\n"); /* 6. 循环接收数据 */ while (keep_running) { memset(buf, 0, FRAME_LEN); ret = read(fd, buf, FRAME_LEN); if (ret < 0) { perror("read"); break; } else if (ret == 0) { /* 非阻塞模式可能返回0,但这里用了阻塞模式,一般不会出现 */ //continue; } frame_count++; printf("\n========== Frame #%u (%d bytes) ==========\n", frame_count, ret); printf("HEX : "); for (int i = 0; i < ret; i++) printf("0x%02X ", buf[i]); printf("\n"); printf("ASCII: "); for (int i = 0; i < ret; i++) printf(" %c ", (buf[i] >= 0x20 && buf[i] < 0x7F) ? buf[i] : '.'); printf("\n"); printf("DEC : "); for (int i = 0; i < ret; i++) printf("%3d ", buf[i]); printf("\n"); printf("=========================================\n"); // 调用SpiProtocol_Unpack解析SPI数据 SpiProtocol_RxResultType result; int32_t unpack_ret = SpiProtocol_Unpack(buf, sizeof(buf), SPI_PROTO_FRAME_SIZE, &result); if (unpack_ret < 0) { printf("SpiProtocol_Unpack error: %d\n", unpack_ret); continue; } printf("SpiProtocol_Unpack success, tlv_count=%d\n", unpack_ret); // 处理解包后的数据:提取 CAN0~CAN5 数据分发到对应缓冲区 for (uint8_t i = 0; i < result.tlv_count; i++) { if (result.tlvs[i].service_id == SPI_PROTO_SID_CAN) { uint8_t can_ch = result.tlvs[i].method_id; /* method_id 对应 CAN0~CAN5 */ if (can_ch < CAN_CHANNEL_COUNT) { std::lock_guard lock(g_can_mutex[can_ch]); g_can_data[can_ch].assign(result.tlvs[i].value, result.tlvs[i].value + result.tlvs[i].length); printf("CAN%d data updated, length=%u\n", can_ch, result.tlvs[i].length); printf(" HEX: "); for (size_t j = 0; j < g_can_data[can_ch].size(); j++) printf("%02X ", g_can_data[can_ch][j]); printf("\n"); } else { printf("WARNING: CAN channel %u out of range (max %u)\n", can_ch, CAN_CHANNEL_COUNT - 1); } } } } close(fd); return; }