Files
luban-lite/packages/artinchip/uds/UDSBase/uds_service.c
刘可亮 3e10f578d3 v1.2.2
2025-10-21 13:59:50 +08:00

339 lines
12 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
/*
*
* 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 应用层相关定时计数器
static uint32_t uds_timer[UDS_TIMER_CNT] = { 0 };
// 安全访问种子匹配错误次数
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)
{
// 检查参数合法性
if (num >= UDS_TIMER_CNT)
return;
// 启动 FSA 定时器
if (num == UDS_TIMER_FSA)
uds_timer[UDS_TIMER_FSA] = TIMEOUT_FSA + 1;
// 启动 S3server 定时器
if (num == UDS_TIMER_S3server)
uds_timer[UDS_TIMER_S3server] = TIMEOUT_S3server + 1;
}
/******************************************************************************
* 函数名称: static void uds_timer_stop (uds_timer_t num)
* 功能说明: 关闭应用层定时器
* 输入参数: uds_timer_t num --定时器
* 输出参数: 无
* 函数返回: 无
* 其它说明: 无
******************************************************************************/
static void uds_timer_stop(uds_timer_t num)
{
// 检查参数合法性
if (num >= UDS_TIMER_CNT)
return;
// 计数值清 0表示关闭定时器
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)
{
// 检查参数合法性
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定时器正在计时运行
}
}
/******************************************************************************
* 函数名称: int uds_timer_chk(uds_timer_t num)
* 功能说明: 检查定时器状态
* 输入参数: uds_timer_t num --定时器
* 输出参数: 无
* 函数返回: 0: 定时器已停止运行; 1: 定时器正在计时运行
* 其它说明: 无
******************************************************************************/
int uds_timer_chk(uds_timer_t num)
{
// 检查参数合法性
if (num >= UDS_TIMER_CNT)
return 0;
// 如果定时器计数值 > 0,表示定时器正在工作,否则表示定时器已停止工作
if (uds_timer[num] > 0)
return 1;
else
return 0;
}
/******************************************************************************
* 函数名称: static void uds_no_response(void)
* 功能说明: 无响应
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 无
******************************************************************************/
static void uds_no_response(void)
{
return;
}
/******************************************************************************
* 函数名称: 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)
{
uint8_t temp_buf[8] = { 0 };
// 如果不是正确接收请求消息,等待响应,其它情况都属于否定响应,这时候需要开启 S3server 定时器
if (rsp_nrc != NRC_SERVICE_BUSY)
uds_timer_start(UDS_TIMER_S3server);
// 在功能寻址下, 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;
}
/******************************************************************************
* 函数名称: void uds_positive_rsp(uint8_t* data, uint16_t len)
* 功能说明: 肯定响应
* 输入参数: uint8_t* data --正响应回复数据首地址
    uint16_t len --正响应回复数据长度
* 输出参数: 无
* 函数返回: 无
* 其它说明: 无
******************************************************************************/
void uds_positive_rsp(uint8_t *data, uint16_t len)
{
// 启动 S3server 定时器
uds_timer_start(UDS_TIMER_S3server);
// 肯定响应抑制标志,在收到的服务中若带有子功能,其子功能的最高位 bit7 表示肯定响应抑制位
// 当其置 1 时,则表示不需要回复肯定响应
if (ssp_flg == TRUE)
return;
// 调用网络层提供的数据发送接口将数据发送出去
network_send_udsmsg(data, len);
return;
}
/******************************************************************************
* 函数名称: static void uds_dataff_indication (uint16_t msg_dlc)
* 功能说明: 首帧指示服务处理
* 输入参数: n_result_t n_result --处理结果
* 输出参数: 无
* 函数返回: 无
* 其它说明: TP 层接收到首帧后将会调用该函数
******************************************************************************/
static void uds_dataff_indication(n_result_t n_result)
{
(void)n_result;
// 关闭 S3server 定时器
uds_timer_stop(UDS_TIMER_S3server);
}
/******************************************************************************
* 函数名称: 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)
{
(void)n_result;
// 启动 S3server 定时器
uds_timer_start(UDS_TIMER_S3server);
}
/******************************************************************************
* 函数名称: static void uds_data_indication (uint8_t* msg_buf, uint16_t msg_dlc, n_result_t n_result)
* 功能说明: 指示服务处理
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 在 n_result == N_OK 的情况下TP 层通过调用该函数将一包完整的有效数据传递过来
******************************************************************************/
static void uds_data_indication(uint8_t *msg_buf, uint16_t msg_dlc, n_result_t n_result)
{
uint8_t i;
uint8_t sid;
uint8_t ssp;
// 关闭 S3server 定时器
uds_timer_stop(UDS_TIMER_S3server);
// 如果 TP 接收到的帧数据异常,则重启 S3server 定时器并退出
if (n_result != N_OK) {
uds_timer_start(UDS_TIMER_S3server);
return;
}
// 第一个字节区作为标识区分不同的服务
sid = msg_buf[0];
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);
}
/******************************************************************************
* 函数名称: void service_task(void)
* 功能说明: 应用层任务处理
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 该函数需要被 1ms 周期调用
******************************************************************************/
void service_task(void)
{
// 如果 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) {
uds_fsa_cnt = 0;
}
}
/******************************************************************************
* 函数名称: int service_init(void)
* 功能说明: 初始化
* 输入参数: 无
* 输出参数: 无
* 函数返回: 0: OK; -1: ERR
* 其它说明: 向 TP 层注册一些接口函数
******************************************************************************/
int service_init(void)
{
nt_usdata_t usdata = { 0 };
usdata.ffindication = uds_dataff_indication;
usdata.indication = uds_data_indication;
usdata.confirm = uds_data_confirm;
return network_reg(&usdata);
}
/****************EOF****************/