2025-07-22 11:15:46 +08:00
|
|
|
|
/*
|
|
|
|
|
|
*
|
|
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
|
*
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "service_cfg.h"
|
|
|
|
|
|
#include <rtthread.h>
|
|
|
|
|
|
#include "uds_def.h"
|
|
|
|
|
|
#include "SID10_SessionControl.h"
|
|
|
|
|
|
#include "SID27_SecurityAccess.h"
|
|
|
|
|
|
|
|
|
|
|
|
// UDS 应用层相关定时计数器
|
2025-10-21 13:59:50 +08:00
|
|
|
|
static uint32_t uds_timer[UDS_TIMER_CNT] = { 0 };
|
2025-07-22 11:15:46 +08:00
|
|
|
|
|
|
|
|
|
|
// 安全访问种子匹配错误次数
|
|
|
|
|
|
extern uint8_t uds_fsa_cnt;
|
|
|
|
|
|
|
|
|
|
|
|
// 肯定响应抑制标志,在收到的服务中若带有子功能,其子功能的最高位 bit7 表示肯定响应抑制位
|
|
|
|
|
|
// 当其置 1 时,则表示不需要回复肯定响应,只进行服务处理即可
|
|
|
|
|
|
static bool_t ssp_flg;
|
|
|
|
|
|
|
|
|
|
|
|
// 服务配置表
|
|
|
|
|
|
extern const uds_service_t uds_service_list[SID_NUM];
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
|
* 函数名称: void uds_timer_start(uds_timer_t num)
|
|
|
|
|
|
* 功能说明: 启动应用层定时器
|
|
|
|
|
|
* 输入参数: uds_timer_t num --定时器
|
|
|
|
|
|
* 输出参数: 无
|
|
|
|
|
|
* 函数返回: 无
|
|
|
|
|
|
* 其它说明: 无
|
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
void uds_timer_start(uds_timer_t num)
|
|
|
|
|
|
{
|
2025-10-21 13:59:50 +08:00
|
|
|
|
// 检查参数合法性
|
|
|
|
|
|
if (num >= UDS_TIMER_CNT)
|
|
|
|
|
|
return;
|
2025-07-22 11:15:46 +08:00
|
|
|
|
|
2025-10-21 13:59:50 +08:00
|
|
|
|
// 启动 FSA 定时器
|
|
|
|
|
|
if (num == UDS_TIMER_FSA)
|
2025-07-22 11:15:46 +08:00
|
|
|
|
uds_timer[UDS_TIMER_FSA] = TIMEOUT_FSA + 1;
|
|
|
|
|
|
|
2025-10-21 13:59:50 +08:00
|
|
|
|
// 启动 S3server 定时器
|
|
|
|
|
|
if (num == UDS_TIMER_S3server)
|
|
|
|
|
|
uds_timer[UDS_TIMER_S3server] = TIMEOUT_S3server + 1;
|
2025-07-22 11:15:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
|
* 函数名称: static void uds_timer_stop (uds_timer_t num)
|
|
|
|
|
|
* 功能说明: 关闭应用层定时器
|
|
|
|
|
|
* 输入参数: uds_timer_t num --定时器
|
|
|
|
|
|
* 输出参数: 无
|
|
|
|
|
|
* 函数返回: 无
|
|
|
|
|
|
* 其它说明: 无
|
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
static void uds_timer_stop(uds_timer_t num)
|
|
|
|
|
|
{
|
2025-10-21 13:59:50 +08:00
|
|
|
|
// 检查参数合法性
|
|
|
|
|
|
if (num >= UDS_TIMER_CNT)
|
|
|
|
|
|
return;
|
2025-07-22 11:15:46 +08:00
|
|
|
|
|
2025-10-21 13:59:50 +08:00
|
|
|
|
// 计数值清 0,表示关闭定时器
|
2025-07-22 11:15:46 +08:00
|
|
|
|
uds_timer[num] = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
|
* 函数名称: static int uds_timer_run(uds_timer_t num)
|
|
|
|
|
|
* 功能说明: 定时器计数运行
|
|
|
|
|
|
* 输入参数: uds_timer_t num --定时器
|
|
|
|
|
|
* 输出参数: 无
|
|
|
|
|
|
* 函数返回: 0: 定时器已经被关闭; -1: 超时发生; 1: 定时器正在计时运行
|
|
|
|
|
|
* 其它说明: 该函数需要被 1ms 周期调用
|
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
static int uds_timer_run(uds_timer_t num)
|
|
|
|
|
|
{
|
2025-10-21 13:59:50 +08:00
|
|
|
|
// 检查参数合法性
|
|
|
|
|
|
if (num >= UDS_TIMER_CNT)
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 如果计数值为 0,表示定时器已经关闭,不再工作
|
|
|
|
|
|
if (uds_timer[num] == 0) {
|
|
|
|
|
|
return 0; // 返回 0,定时器已经被关闭
|
|
|
|
|
|
}
|
|
|
|
|
|
// 如果计数值为 1,表示定时器超时已发生
|
|
|
|
|
|
else if (uds_timer[num] == 1) {
|
|
|
|
|
|
uds_timer[num] = 0; // 关闭定时器
|
|
|
|
|
|
return -1; // 返回 -1,发生超时
|
|
|
|
|
|
}
|
|
|
|
|
|
// 其余情况则表示定时器正在运行
|
|
|
|
|
|
else {
|
|
|
|
|
|
uds_timer[num]--; // 计数值 -1
|
|
|
|
|
|
return 1; // 返回 1,定时器正在计时运行
|
|
|
|
|
|
}
|
2025-07-22 11:15:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
|
* 函数名称: int uds_timer_chk(uds_timer_t num)
|
|
|
|
|
|
* 功能说明: 检查定时器状态
|
|
|
|
|
|
* 输入参数: uds_timer_t num --定时器
|
|
|
|
|
|
* 输出参数: 无
|
|
|
|
|
|
* 函数返回: 0: 定时器已停止运行; 1: 定时器正在计时运行
|
|
|
|
|
|
* 其它说明: 无
|
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
int uds_timer_chk(uds_timer_t num)
|
|
|
|
|
|
{
|
2025-10-21 13:59:50 +08:00
|
|
|
|
// 检查参数合法性
|
|
|
|
|
|
if (num >= UDS_TIMER_CNT)
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 如果定时器计数值 > 0,表示定时器正在工作,否则表示定时器已停止工作
|
|
|
|
|
|
if (uds_timer[num] > 0)
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
else
|
|
|
|
|
|
return 0;
|
2025-07-22 11:15:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
|
* 函数名称: static void uds_no_response(void)
|
|
|
|
|
|
* 功能说明: 无响应
|
|
|
|
|
|
* 输入参数: 无
|
|
|
|
|
|
* 输出参数: 无
|
|
|
|
|
|
* 函数返回: 无
|
|
|
|
|
|
* 其它说明: 无
|
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
static void uds_no_response(void)
|
|
|
|
|
|
{
|
2025-10-21 13:59:50 +08:00
|
|
|
|
return;
|
2025-07-22 11:15:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
|
* 函数名称: void uds_negative_rsp(uint8_t sid, uds_nrc_em rsp_nrc)
|
|
|
|
|
|
* 功能说明: 否定响应
|
|
|
|
|
|
* 输入参数: uint8_t sid --服务 ID
|
|
|
|
|
|
uds_nrc_em rsp_nrc --否定响应具体原因
|
|
|
|
|
|
* 输出参数: 无
|
|
|
|
|
|
* 函数返回: 无
|
|
|
|
|
|
* 其它说明: 无
|
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
void uds_negative_rsp(uint8_t sid, uds_negative_response_code_t rsp_nrc)
|
|
|
|
|
|
{
|
2025-10-21 13:59:50 +08:00
|
|
|
|
uint8_t temp_buf[8] = { 0 };
|
2025-07-22 11:15:46 +08:00
|
|
|
|
|
2025-10-21 13:59:50 +08:00
|
|
|
|
// 如果不是正确接收请求消息,等待响应,其它情况都属于否定响应,这时候需要开启 S3server 定时器
|
2025-07-22 11:15:46 +08:00
|
|
|
|
if (rsp_nrc != NRC_SERVICE_BUSY)
|
|
|
|
|
|
uds_timer_start(UDS_TIMER_S3server);
|
|
|
|
|
|
|
2025-10-21 13:59:50 +08:00
|
|
|
|
// 在功能寻址下, 0x11,0x12,0x31,0x7E,0x7F 这几种否定响应是不需要回复的
|
|
|
|
|
|
if (g_tatype == N_TATYPE_FUNCTIONAL) {
|
|
|
|
|
|
if (NRC_SERVICE_NOT_SUPPORTED == rsp_nrc || NRC_SUBFUNCTION_NOT_SUPPORTED == rsp_nrc ||
|
|
|
|
|
|
NRC_REQUEST_OUT_OF_RANGE == rsp_nrc ||
|
|
|
|
|
|
NRC_SUBFUNCTION_NOT_SUPPORTED_IN_ACTIVE_SESSION == rsp_nrc ||
|
|
|
|
|
|
NRC_SERVICE_NOT_SUPPORTED_IN_ACTIVE_SESSION == rsp_nrc)
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 否定响应回复
|
|
|
|
|
|
temp_buf[0] = NEGATIVE_RSP;
|
|
|
|
|
|
temp_buf[1] = sid;
|
|
|
|
|
|
temp_buf[2] = rsp_nrc;
|
|
|
|
|
|
network_send_udsmsg(temp_buf, 3);
|
|
|
|
|
|
return;
|
2025-07-22 11:15:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
|
* 函数名称: void uds_positive_rsp(uint8_t* data, uint16_t len)
|
|
|
|
|
|
* 功能说明: 肯定响应
|
|
|
|
|
|
* 输入参数: uint8_t* data --正响应回复数据首地址
|
|
|
|
|
|
uint16_t len --正响应回复数据长度
|
|
|
|
|
|
* 输出参数: 无
|
|
|
|
|
|
* 函数返回: 无
|
|
|
|
|
|
* 其它说明: 无
|
|
|
|
|
|
******************************************************************************/
|
2025-10-21 13:59:50 +08:00
|
|
|
|
void uds_positive_rsp(uint8_t *data, uint16_t len)
|
2025-07-22 11:15:46 +08:00
|
|
|
|
{
|
2025-10-21 13:59:50 +08:00
|
|
|
|
// 启动 S3server 定时器
|
|
|
|
|
|
uds_timer_start(UDS_TIMER_S3server);
|
|
|
|
|
|
|
|
|
|
|
|
// 肯定响应抑制标志,在收到的服务中若带有子功能,其子功能的最高位 bit7 表示肯定响应抑制位
|
|
|
|
|
|
// 当其置 1 时,则表示不需要回复肯定响应
|
|
|
|
|
|
if (ssp_flg == TRUE)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
// 调用网络层提供的数据发送接口将数据发送出去
|
|
|
|
|
|
network_send_udsmsg(data, len);
|
2025-07-22 11:15:46 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
|
* 函数名称: static void uds_dataff_indication (uint16_t msg_dlc)
|
|
|
|
|
|
* 功能说明: 首帧指示服务处理
|
|
|
|
|
|
* 输入参数: n_result_t n_result --处理结果
|
|
|
|
|
|
* 输出参数: 无
|
|
|
|
|
|
* 函数返回: 无
|
|
|
|
|
|
* 其它说明: TP 层接收到首帧后将会调用该函数
|
|
|
|
|
|
******************************************************************************/
|
2025-10-21 13:59:50 +08:00
|
|
|
|
static void uds_dataff_indication(n_result_t n_result)
|
2025-07-22 11:15:46 +08:00
|
|
|
|
{
|
2025-10-21 13:59:50 +08:00
|
|
|
|
(void)n_result;
|
|
|
|
|
|
// 关闭 S3server 定时器
|
|
|
|
|
|
uds_timer_stop(UDS_TIMER_S3server);
|
2025-07-22 11:15:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
|
* 函数名称: static void uds_data_confirm(n_result_t n_result)
|
|
|
|
|
|
* 功能说明: 确认服务处理
|
|
|
|
|
|
* 输入参数: n_result_t n_result --处理结果
|
|
|
|
|
|
* 输出参数: 无
|
|
|
|
|
|
* 函数返回: 无
|
|
|
|
|
|
* 其它说明: TP 层接收到错误帧或者一些异常超时时将会调用该函数
|
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
static void uds_data_confirm(n_result_t n_result)
|
|
|
|
|
|
{
|
2025-10-21 13:59:50 +08:00
|
|
|
|
(void)n_result;
|
|
|
|
|
|
// 启动 S3server 定时器
|
|
|
|
|
|
uds_timer_start(UDS_TIMER_S3server);
|
2025-07-22 11:15:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
|
* 函数名称: static void uds_data_indication (uint8_t* msg_buf, uint16_t msg_dlc, n_result_t n_result)
|
|
|
|
|
|
* 功能说明: 指示服务处理
|
|
|
|
|
|
* 输入参数: 无
|
|
|
|
|
|
* 输出参数: 无
|
|
|
|
|
|
* 函数返回: 无
|
|
|
|
|
|
* 其它说明: 在 n_result == N_OK 的情况下,TP 层通过调用该函数将一包完整的有效数据传递过来
|
|
|
|
|
|
******************************************************************************/
|
2025-10-21 13:59:50 +08:00
|
|
|
|
static void uds_data_indication(uint8_t *msg_buf, uint16_t msg_dlc, n_result_t n_result)
|
2025-07-22 11:15:46 +08:00
|
|
|
|
{
|
2025-10-21 13:59:50 +08:00
|
|
|
|
uint8_t i;
|
|
|
|
|
|
uint8_t sid;
|
|
|
|
|
|
uint8_t ssp;
|
2025-07-22 11:15:46 +08:00
|
|
|
|
|
2025-10-21 13:59:50 +08:00
|
|
|
|
// 关闭 S3server 定时器
|
|
|
|
|
|
uds_timer_stop(UDS_TIMER_S3server);
|
2025-07-22 11:15:46 +08:00
|
|
|
|
|
2025-10-21 13:59:50 +08:00
|
|
|
|
// 如果 TP 接收到的帧数据异常,则重启 S3server 定时器并退出
|
|
|
|
|
|
if (n_result != N_OK) {
|
|
|
|
|
|
uds_timer_start(UDS_TIMER_S3server);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-07-22 11:15:46 +08:00
|
|
|
|
|
2025-10-21 13:59:50 +08:00
|
|
|
|
// 第一个字节区作为标识区分不同的服务
|
2025-07-22 11:15:46 +08:00
|
|
|
|
sid = msg_buf[0];
|
2025-10-21 13:59:50 +08:00
|
|
|
|
rt_kprintf("SID%d", sid);
|
|
|
|
|
|
|
|
|
|
|
|
// 肯定响应抑制位,在收到的服务中若带有子功能,其子功能的最高位 bit7 表示肯定响应抑制位
|
|
|
|
|
|
// 当其置 1 时,则表示不需要回复肯定响应,只执行即可
|
|
|
|
|
|
ssp = UDS_GET_SUB_FUNCTION_SUPPRESS_POSRSP(msg_buf[1]);
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < SID_NUM; i++) {
|
|
|
|
|
|
if (sid != uds_service_list[i].uds_sid)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否支持功能寻址
|
|
|
|
|
|
if (N_TATYPE_FUNCTIONAL == g_tatype && FALSE == uds_service_list[i].fun_spt) {
|
|
|
|
|
|
uds_no_response();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查会话状态是否支持
|
|
|
|
|
|
if ((UDS_SESSION_STD == get_current_session() && FALSE == uds_service_list[i].std_spt) ||
|
|
|
|
|
|
(UDS_SESSION_PROG == get_current_session() && FALSE == uds_service_list[i].prog_spt) ||
|
|
|
|
|
|
(UDS_SESSION_EXT == get_current_session() && FALSE == uds_service_list[i].ext_spt)) {
|
|
|
|
|
|
uds_negative_rsp(sid, NRC_SERVICE_NOT_SUPPORTED_IN_ACTIVE_SESSION);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查安全访问等级
|
|
|
|
|
|
if (get_current_sa_lv() < uds_service_list[i].uds_sa) {
|
|
|
|
|
|
uds_negative_rsp(sid, NRC_SECURITY_ACCESS_DENIED);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查数据长度是否合法
|
|
|
|
|
|
if (FALSE == uds_service_list[i].check_len(msg_buf, msg_dlc)) {
|
|
|
|
|
|
uds_negative_rsp(sid, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 肯定响应抑制标志,在收到的服务中若带有子功能,其子功能的最高位 bit7 表示肯定响应抑制位
|
|
|
|
|
|
// 当其置 1 时,则表示不需要回复肯定响应,只进行服务处理即可
|
|
|
|
|
|
if (uds_service_list[i].ssp_spt == TRUE && ssp == 0x01)
|
|
|
|
|
|
ssp_flg = TRUE;
|
|
|
|
|
|
else
|
|
|
|
|
|
ssp_flg = FALSE;
|
|
|
|
|
|
|
|
|
|
|
|
// 执行服务处理函数
|
|
|
|
|
|
uds_service_list[i].uds_service(msg_buf, msg_dlc);
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 程序运行到这里说明没找到对应的服务 ID
|
|
|
|
|
|
uds_negative_rsp(sid, NRC_SERVICE_NOT_SUPPORTED);
|
2025-07-22 11:15:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
|
* 函数名称: void service_task(void)
|
|
|
|
|
|
* 功能说明: 应用层任务处理
|
|
|
|
|
|
* 输入参数: 无
|
|
|
|
|
|
* 输出参数: 无
|
|
|
|
|
|
* 函数返回: 无
|
|
|
|
|
|
* 其它说明: 该函数需要被 1ms 周期调用
|
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
void service_task(void)
|
|
|
|
|
|
{
|
2025-10-21 13:59:50 +08:00
|
|
|
|
// 如果 S3server 定时器超时,复位当前会话状态和安全访问等级
|
|
|
|
|
|
if (uds_timer_run(UDS_TIMER_S3server) < 0) {
|
|
|
|
|
|
set_current_session(UDS_SESSION_STD);
|
|
|
|
|
|
set_current_sa_lv(UDS_SA_NON);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果 FSA 定时器超时,安全访问种子匹配错误次数清 0
|
|
|
|
|
|
if (uds_timer_run(UDS_TIMER_FSA) < 0) {
|
2025-07-22 11:15:46 +08:00
|
|
|
|
uds_fsa_cnt = 0;
|
2025-10-21 13:59:50 +08:00
|
|
|
|
}
|
2025-07-22 11:15:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
|
* 函数名称: int service_init(void)
|
|
|
|
|
|
* 功能说明: 初始化
|
|
|
|
|
|
* 输入参数: 无
|
|
|
|
|
|
* 输出参数: 无
|
|
|
|
|
|
* 函数返回: 0: OK; -1: ERR
|
|
|
|
|
|
* 其它说明: 向 TP 层注册一些接口函数
|
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
int service_init(void)
|
|
|
|
|
|
{
|
2025-10-21 13:59:50 +08:00
|
|
|
|
nt_usdata_t usdata = { 0 };
|
2025-07-22 11:15:46 +08:00
|
|
|
|
|
|
|
|
|
|
usdata.ffindication = uds_dataff_indication;
|
|
|
|
|
|
usdata.indication = uds_data_indication;
|
|
|
|
|
|
usdata.confirm = uds_data_confirm;
|
|
|
|
|
|
|
|
|
|
|
|
return network_reg(&usdata);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************EOF****************/
|