Files

207 lines
6.6 KiB
C++
Raw Permalink Normal View History

//#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 <mutex>
#include <vector>
/* CAN 数据缓冲区 — SPI 线程写入notifier 线程读取 */
std::vector<uint8_t> g_can_data[CAN_CHANNEL_COUNT];
std::mutex g_can_mutex[CAN_CHANNEL_COUNT];
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
/* ========== 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);
2026-06-24 21:58:02 +08:00
if (unpack_ret < 0)
{
printf("SpiProtocol_Unpack error: %d\n", unpack_ret);
continue;
}
2026-06-24 21:58:02 +08:00
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<std::mutex> 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);
2026-06-24 21:58:02 +08:00
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;
}