Files
SOMEIP/source/soa_server/spi_server.cpp
2026-06-24 21:58:02 +08:00

207 lines
6.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//#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);
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<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);
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;
}