244 lines
9.3 KiB
C++
Executable File
244 lines
9.3 KiB
C++
Executable File
/*==================================================================================================
|
||
* Project : S32K3_miniEvb
|
||
* Platform : CORTEXM
|
||
* Peripheral : S32K3XX
|
||
* Dependencies : none
|
||
*
|
||
* Autosar Version : 4.7.0
|
||
* Autosar Revision : ASR_REL_4_7_REV_0000
|
||
* Autosar Conf.Variant :
|
||
* SW Version : 0.1.0
|
||
* Build Version :
|
||
*
|
||
* Copyright 2026 - 20xx HuaXu
|
||
*
|
||
* HuaXu Confidential. This software is owned or controlled by HuaXu and may only be
|
||
* used strictly in accordance with the applicable license terms. By expressly
|
||
* accepting such terms or by downloading, installing, activating and/or otherwise
|
||
* using the software, you are agreeing that you have read, and that you agree to
|
||
* comply with and are bound by, such license terms. If you do not agree to be
|
||
* bound by the applicable license terms, then you may not retain, install,
|
||
* activate or otherwise use the software.
|
||
==================================================================================================*/
|
||
/*==================================================================================================
|
||
* File version history:
|
||
* 0.1.0 initial version
|
||
==================================================================================================*/
|
||
/**
|
||
* @file spi_protocol.hpp
|
||
* @version 0.1.0
|
||
* @brief SPI Protocol v2.0 — SOC/MCU 通信组包/解包
|
||
*
|
||
* @addtogroup SPI
|
||
* @{
|
||
*/
|
||
|
||
#ifndef SPI_PROTOCOL_HPP
|
||
#define SPI_PROTOCOL_HPP
|
||
|
||
#ifdef __cplusplus
|
||
extern "C"{
|
||
#endif
|
||
|
||
/*==================================================================================================
|
||
INCLUDE FILES
|
||
==================================================================================================*/
|
||
#include <stdint.h>
|
||
|
||
/*==================================================================================================
|
||
CONSTANTS
|
||
==================================================================================================*/
|
||
|
||
/* 帧固定字段 */
|
||
#define SPI_PROTO_SOF 0xAAu
|
||
#define SPI_PROTO_EOF 0x55u
|
||
#define SPI_PROTO_VERSION 0x01u
|
||
|
||
/* 帧长配置(4 选 1) */
|
||
#define SPI_PROTO_FRAME_64 64u
|
||
#define SPI_PROTO_FRAME_128 128u
|
||
#define SPI_PROTO_FRAME_256 256u
|
||
#define SPI_PROTO_FRAME_512 512u
|
||
#define SPI_PROTO_FRAME_1024 1024u
|
||
|
||
/* 默认帧长 */
|
||
#define SPI_PROTO_FRAME_SIZE SPI_PROTO_FRAME_128
|
||
|
||
/* HEAD 长度 = Version(1) + FrameType(1) + Seq(2) + Timestamp(4) + PacketCount(1) + TotalLen(2) */
|
||
#define SPI_PROTO_HEAD_LEN 11u
|
||
|
||
/* 帧开销 = SOF(1) + HEAD(11) + CRC16(2) + EOF(1) */
|
||
#define SPI_PROTO_OVERHEAD 15u
|
||
|
||
/* 最大 Payload 字节数 */
|
||
#define SPI_PROTO_MAX_PAYLOAD (SPI_PROTO_FRAME_SIZE - SPI_PROTO_OVERHEAD)
|
||
|
||
/* 最大 TLV 数量 */
|
||
#define SPI_PROTO_MAX_TLV_COUNT 16u
|
||
|
||
/* TLV 头部长度 = ServiceID(1) + MethodID(1) + Length(2) */
|
||
#define SPI_PROTO_TLV_HEAD_LEN 4u
|
||
|
||
/* ——— FrameType ——— */
|
||
typedef enum
|
||
{
|
||
SPI_PROTO_FRAME_DATA = 0x00u, /* MCU→SOC 常规上报 */
|
||
SPI_PROTO_FRAME_CTRL = 0x01u, /* SOC→MCU 控制/配置 */
|
||
SPI_PROTO_FRAME_ACK = 0x02u, /* 通用确认 */
|
||
SPI_PROTO_FRAME_NACK = 0x03u, /* 错误应答 */
|
||
SPI_PROTO_FRAME_HEARTBEAT = 0x04u /* 心跳 */
|
||
} SpiProtocol_FrameType;
|
||
|
||
/* ——— ServiceID ——— */
|
||
#define SPI_PROTO_SID_SYSTEM 0x01u
|
||
#define SPI_PROTO_SID_AC 0x02u
|
||
#define SPI_PROTO_SID_KEY 0x03u
|
||
#define SPI_PROTO_SID_VEHICLE 0x04u
|
||
#define SPI_PROTO_SID_CAN 0x05u
|
||
#define SPI_PROTO_SID_UPDATE 0x06u
|
||
#define SPI_PROTO_SID_CLUSTER 0x07u
|
||
#define SPI_PROTO_SID_LOG 0x08u
|
||
#define SPI_PROTO_SID_TEST 0x09u
|
||
#define SPI_PROTO_SID_DIAG 0x0Au
|
||
#define SPI_PROTO_SID_PASS 0x0Bu
|
||
#define SPI_PROTO_SID_AUDIO 0x0Cu
|
||
#define SPI_PROTO_SID_AVM 0x0Du
|
||
#define SPI_PROTO_SID_BSD 0x0Eu
|
||
#define SPI_PROTO_SID_DMS 0x0Fu
|
||
#define SPI_PROTO_SID_ADAS 0x10u
|
||
#define SPI_PROTO_SID_THEME 0x11u
|
||
#define SPI_PROTO_SID_POWERMANAGER 0x12u
|
||
#define SPI_PROTO_SID_RVC 0x13u
|
||
#define SPI_PROTO_SID_ERROR 0xFEu /* NACK 错误信息 */
|
||
|
||
/* ——— NACK 错误码 ——— */
|
||
#define SPI_PROTO_ERR_NONE 0x00u
|
||
#define SPI_PROTO_ERR_CRC 0x01u
|
||
#define SPI_PROTO_ERR_VERSION 0x02u
|
||
#define SPI_PROTO_ERR_SOF 0x03u
|
||
#define SPI_PROTO_ERR_EOF 0x04u
|
||
#define SPI_PROTO_ERR_TOTALLEN 0x05u
|
||
#define SPI_PROTO_ERR_TLV_PARSE 0x06u
|
||
#define SPI_PROTO_ERR_PKTCOUNT 0x07u
|
||
#define SPI_PROTO_ERR_FRAMETYPE 0x08u
|
||
#define SPI_PROTO_ERR_PADDING 0x09u
|
||
#define SPI_PROTO_ERR_TRUNCATED 0x0Au
|
||
|
||
/* ——— 解包返回码 ——— */
|
||
#define SPI_PROTO_OK 0
|
||
#define SPI_PROTO_ERR_PARAM (-1)
|
||
#define SPI_PROTO_ERR_SIZE (-2)
|
||
#define SPI_PROTO_ERR_SOF_MISMATCH (-3)
|
||
#define SPI_PROTO_ERR_EOF_MISMATCH (-4)
|
||
#define SPI_PROTO_ERR_CRC_MISMATCH (-5)
|
||
#define SPI_PROTO_ERR_VERSION_MISMATCH (-6)
|
||
#define SPI_PROTO_ERR_TOTALLEN_OVF (-7)
|
||
#define SPI_PROTO_ERR_PKTCOUNT_OVF (-8)
|
||
#define SPI_PROTO_ERR_TLV_TRUNC (-9)
|
||
#define SPI_PROTO_ERR_PADDING_NZ (-10)
|
||
#define SPI_PROTO_ERR_FRAME_SHORT (-11)
|
||
|
||
/*==================================================================================================
|
||
TYPEDEFS
|
||
==================================================================================================*/
|
||
|
||
/**
|
||
* @brief TLV 子包描述
|
||
* @note value 指针由调用方管理,组包时指向待发送数据,解包时指向 frame 内数据
|
||
*/
|
||
typedef struct
|
||
{
|
||
uint8_t service_id; /**< 业务大类 */
|
||
uint8_t method_id; /**< 业务子类 */
|
||
uint16_t length; /**< Value 字节数(不含 T+L) */
|
||
const uint8_t *value; /**< Value 数据指针 */
|
||
} SpiProtocol_TlvType;
|
||
|
||
/**
|
||
* @brief 解包输出结果
|
||
*/
|
||
typedef struct
|
||
{
|
||
SpiProtocol_FrameType frame_type; /**< 帧类型 */
|
||
uint16_t seq; /**< 帧序号 */
|
||
uint32_t timestamp; /**< 时间戳 (ms) */
|
||
uint8_t tlv_count; /**< 实际 TLV 数量 */
|
||
SpiProtocol_TlvType tlvs[SPI_PROTO_MAX_TLV_COUNT]; /**< TLV 列表 */
|
||
uint8_t nack_error_code; /**< NACK 帧时有效 */
|
||
} SpiProtocol_RxResultType;
|
||
|
||
/*==================================================================================================
|
||
GLOBAL FUNCTION PROTOTYPES
|
||
==================================================================================================*/
|
||
|
||
/**
|
||
* @brief 计算 CRC16(HEAD + Payload 范围)
|
||
* @param data 数据起始指针(指向 HEAD 首字节 Version)
|
||
* @param len 数据长度
|
||
* @return CRC16 值
|
||
*/
|
||
uint16_t SpiProtocol_CalcCrc16(const uint8_t *data, uint16_t len);
|
||
|
||
/**
|
||
* @brief 组包:将 TLV 列表打包为完整帧
|
||
* @param frame 输出帧缓冲区(调用方分配,大小 ≥ SPI_PROTO_FRAME_SIZE)
|
||
* @param frame_size 帧长配置(128/256/512/1024)
|
||
* @param frame_type 帧类型
|
||
* @param seq 帧序号
|
||
* @param timestamp 时间戳 (ms)
|
||
* @param tlvs TLV 数组
|
||
* @param tlv_count TLV 数量
|
||
* @return >=0: 实际帧字节数(= frame_size); <0: 错误码
|
||
*/
|
||
int32_t SpiProtocol_Pack(uint8_t *frame, uint16_t frame_size,
|
||
SpiProtocol_FrameType frame_type, uint16_t seq, uint32_t timestamp,
|
||
const SpiProtocol_TlvType *tlvs, uint8_t tlv_count);
|
||
|
||
/**
|
||
* @brief 解包:解析接收帧,输出 TLV 列表
|
||
* @param frame 接收帧缓冲区
|
||
* @param frame_len 接收数据长度
|
||
* @param frame_size 预期帧长配置(128/256/512/1024)
|
||
* @param result 输出解析结果
|
||
* @return >=0: 成功(返回 TLV 数量); <0: 错误码
|
||
*/
|
||
int32_t SpiProtocol_Unpack(const uint8_t *frame, uint16_t frame_len,
|
||
uint16_t frame_size,
|
||
SpiProtocol_RxResultType *result);
|
||
|
||
/**
|
||
* @brief 构造 ACK 帧(确认指定 seq 的帧)
|
||
* @param frame 输出帧缓冲区
|
||
* @param frame_size 帧长配置
|
||
* @param ack_seq 被确认帧的序号
|
||
* @return >=0: 实际帧字节数; <0: 错误码
|
||
*/
|
||
int32_t SpiProtocol_PackAck(uint8_t *frame, uint16_t frame_size, uint16_t ack_seq);
|
||
|
||
/**
|
||
* @brief 构造 NACK 帧
|
||
* @param frame 输出帧缓冲区
|
||
* @param frame_size 帧长配置
|
||
* @param ack_seq 被否定应答帧的序号
|
||
* @param error_code 错误码(见 SPI_PROTO_ERR_xxx)
|
||
* @return >=0: 实际帧字节数; <0: 错误码
|
||
*/
|
||
int32_t SpiProtocol_PackNack(uint8_t *frame, uint16_t frame_size,
|
||
uint16_t ack_seq, uint8_t error_code);
|
||
|
||
/**
|
||
* @brief 构造心跳帧
|
||
* @param frame 输出帧缓冲区
|
||
* @param frame_size 帧长配置
|
||
* @param seq 帧序号
|
||
* @return >=0: 实际帧字节数; <0: 错误码
|
||
*/
|
||
int32_t SpiProtocol_PackHeartbeat(uint8_t *frame, uint16_t frame_size, uint16_t seq);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif /* SPI_PROTOCOL_HPP */
|
||
/** @} */
|