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

312 lines
11 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 "uds_def.h"
//Negative Response
#define IS_NEGATIVE_RESPONSE(frame_buf) (frame_buf[0] == 0x7F)
//Positive Response
#define IS_POSITIVE_RESPONSE(frame_buf, service_id) (frame_buf[1] == (0x40 + (service_id)))
//eg0x50 03
#define IS_RESPONSE_WITH_SUBFUNC(frame_buf, service_id, subfunc) \
(frame_buf[1] == (0x40 + (service_id)) && frame_buf[2] == (subfunc))
//Check if it is a negative response for a specific service
#define IS_NEGATIVE_RESPONSE_FOR_SERVICE(frame_buf, service_id) \
(IS_NEGATIVE_RESPONSE(frame_buf) && frame_buf[1] == (service_id))
#define UDS_SERVICE_DIAG_SESSION_CTRL 0x10
#define UDS_SERVICE_ECU_RESET 0x11
#define UDS_SERVICE_READ_DATA 0x22
#define UDS_SERVICE_SECURITY_ACCESS 0x27
#define UDS_SERVICE_COMMUNICATION_CTRL 0x28
#define UDS_SERVICE_ROUTINE_CTRL 0x31
#define UDS_SERVICE_REQUEST_DOWNLOAD 0x34
#define UDS_SERVICE_REQUEST_UPLOAD 0x35
#define UDS_SERVICE_TRANSFER_DATA 0x36
#define UDS_SERVICE_REQUEST_TRANSFER_EXIT 0x37
#define UDS_SERVICE_WRITE_DATA 0x3E
#define UDS_SERVICE_CTRL_DTC 0x85
static rt_timer_t response_timer;
void response_timeout(void *param)
{
rt_kprintf("\n[UDS] ERROR: Response timeout!\n");
}
void init_uds_timers()
{
response_timer =
rt_timer_create("uds_tout", response_timeout, RT_NULL, 2000, RT_TIMER_FLAG_ONE_SHOT);
}
static uint8_t g_key[4] = { 0 };
typedef struct {
uint8_t data[8];
uint8_t len;
uint8_t next_state;
} UdsRequest;
static const UdsRequest uds_requests[] = {
[UDS_STATE_ENTER_EXT_SESSION] = {
.data = {0x03, 0x22, 0xF1, 0x86},
.len = 4,
.next_state = UDS_STATE_READ_ECU_INFO,
},
[UDS_STATE_READ_ECU_INFO] = {
.data = {0x02, 0x10, 0x02},
.len = 3,
.next_state = UDS_STATE_ENTER_PROG_SESSION,
},
[UDS_STATE_ENTER_PROG_SESSION] = {
.data = {0x02, 0x27, 0x01},
.len = 3,
.next_state = UDS_STATE_SAFE_ACCESS,
},
[UDS_STATE_REQUEST_UPLOAD_EXIT] = {
.data = {0x01, 0x37},
.len = 2,
.next_state = UDS_STATE_APP_CHECK,
}
};
#define UDS_STATE_COUNT (UDS_STATE_ENTER_DEFAULT_SESSION + 1)
void send_uds_service(void)
{
uint8_t uds_request[8] = { 0 };
uint8_t uds_request_len = 0;
if (g_current_state >= UDS_STATE_COUNT) {
rt_kprintf("[UDS] Invalid state: %d\n", g_current_state);
return;
}
const UdsRequest *req = &uds_requests[g_current_state];
if (g_current_state == UDS_STATE_SAFE_ACCESS) {
uds_request[0] = 0x06;
uds_request[1] = 0x27;
uds_request[2] = 0x02;
if (g_key[0] || g_key[1] || g_key[2] || g_key[3]) {
uds_request[3] = g_key[0];
uds_request[4] = g_key[1];
uds_request[5] = g_key[2];
uds_request[6] = g_key[3];
uds_request_len = 7;
g_current_state = UDS_STATE_REQUEST_UPLOAD_WAIT;
} else {
rt_kprintf("[UDS] Error: Key not initialized\n");
return;
}
} else {
if (req->len > 0 && req->len <= 8) {
memcpy(uds_request, req->data, req->len);
uds_request_len = req->len;
g_current_state = req->next_state;
} else {
rt_kprintf("[UDS] Invalid request length: %d\n", req->len);
return;
}
}
if (uds_request_len > 0) {
uds_send_frame(UDS_REQUEST_ID, uds_request, uds_request_len, 1);
} else {
rt_kprintf("[UDS] Error: Attempting to send empty frame\n");
}
}
int uds_calculate_key_direct(const uint8_t *frame_buf, uint8_t *key_buf)
{
if (frame_buf == NULL || key_buf == NULL) {
return -1;
}
uint8_t frame_len = frame_buf[0];
if (frame_len < 6) {
return -1;
}
if (frame_buf[1] != 0x67 || frame_buf[2] != 0x01) {
return -1;
}
uint32_t seed = (uint32_t)frame_buf[3] << 24 | (uint32_t)frame_buf[4] << 16 |
(uint32_t)frame_buf[5] << 8 | (uint32_t)frame_buf[6];
uint32_t calculated_key = ~seed;
key_buf[0] = (uint8_t)(calculated_key >> 24);
key_buf[1] = (uint8_t)(calculated_key >> 16);
key_buf[2] = (uint8_t)(calculated_key >> 8);
key_buf[3] = (uint8_t)calculated_key;
return 0;
}
/******************************************************************************
* 函数名称: static void handle_uds_state_machine(uint32_t id, uint8_t* frame_buf, uint8_t frame_dlc)
* 功能说明: UDS状态机处理
* 输入参数: uint32_t id --消息帧 ID
    uint8_t* frame_buf --接收报文帧数据首地址
    uint8_t frame_dlc --接收报文帧数据长度
* 输出参数: 无
* 函数返回: 无
* 其它说明: ecu响应处理状态机
******************************************************************************/
static void handle_uds_state_machine(uint32_t id, uint8_t *frame_buf, uint8_t frame_dlc)
{
if (frame_dlc < 2) {
return;
}
rt_mutex_take(g_uds_state_mutex, RT_WAITING_FOREVER);
switch (g_current_state) {
case UDS_STATE_ENTER_EXT_SESSION:
if (IS_RESPONSE_WITH_SUBFUNC(frame_buf, UDS_SERVICE_DIAG_SESSION_CTRL, 0x03)) {
send_uds_service();
}
break;
case UDS_STATE_READ_ECU_INFO:
if (IS_POSITIVE_RESPONSE(frame_buf, UDS_SERVICE_READ_DATA)) {
send_uds_service();
}
break;
case UDS_STATE_ENTER_PROG_SESSION:
if (IS_RESPONSE_WITH_SUBFUNC(frame_buf, UDS_SERVICE_DIAG_SESSION_CTRL, 0x02)) {
send_uds_service();
}
break;
case UDS_STATE_SAFE_ACCESS:
if (IS_RESPONSE_WITH_SUBFUNC(frame_buf, UDS_SERVICE_SECURITY_ACCESS, 0x01)) {
// Calculate the key
uds_calculate_key_direct(frame_buf, g_key);
send_uds_service();
}
break;
case UDS_STATE_SAFE_ACCESS_SEND_VERIFY:
if (IS_RESPONSE_WITH_SUBFUNC(frame_buf, UDS_SERVICE_SECURITY_ACCESS, 0x02)) {
send_uds_service();
}
break;
case UDS_STATE_ERASE_CODE:
if (IS_RESPONSE_WITH_SUBFUNC(frame_buf, UDS_SERVICE_ROUTINE_CTRL, 0x01)) {
send_uds_service();
}
break;
case UDS_STATE_REQUEST_UPLOAD:
break;
case UDS_STATE_SEND_UPLOAD:
break;
case UDS_STATE_REQUEST_UPLOAD_EXIT:
break;
case UDS_STATE_APP_CHECK:
break;
case UDS_STATE_CODE_CHECK:
break;
case UDS_STATE_REQUEST_UPLOAD_WAIT:
g_current_state = UDS_STATE_REQUEST_UPLOAD;
break;
case UDS_STATE_WAIT_DOWNLOAD_RESPONSE:
if (frame_dlc >= 5 && IS_POSITIVE_RESPONSE(frame_buf, UDS_SERVICE_REQUEST_DOWNLOAD)) {
g_max_block_size = (frame_buf[3] << 8) | frame_buf[4];
g_bytes_per_block = (g_max_block_size > 0) ? g_max_block_size : 32;
g_current_state = UDS_STATE_SEND_UPLOAD;
} else if (IS_NEGATIVE_RESPONSE_FOR_SERVICE(frame_buf, UDS_SERVICE_REQUEST_DOWNLOAD)) {
g_current_state = UDS_STATE_ERROR;
} else {
uds_tp_recv_frame(0, frame_buf, frame_dlc);
}
break;
case UDS_STATE_WAIT_TRANSFER_RESPONSE:
if (IS_POSITIVE_RESPONSE(frame_buf, UDS_SERVICE_TRANSFER_DATA)) {
rt_sem_release(&g_flow_control_sem);
} else if (IS_NEGATIVE_RESPONSE_FOR_SERVICE(frame_buf, UDS_SERVICE_TRANSFER_DATA)) {
g_current_state = UDS_STATE_ERROR;
} else {
uds_tp_recv_frame(0, frame_buf, frame_dlc);
}
break;
default:
break;
}
rt_mutex_release(g_uds_state_mutex);
}
/******************************************************************************
* 函数名称: void uds_recv_frame(uint32_t id, uint8_t* frame_buf, uint8_t frame_dlc)
* 功能说明: 接收到一帧报文
* 输入参数: uint32_t id --消息帧 ID
    uint8_t* frame_buf --接收报文帧数据首地址
    uint8_t frame_dlc --接收报文帧数据长度
* 输出参数: 无
* 函数返回: 无
* 其它说明: frame_dlc 长度必须等于 FRAME_SIZE否则会被判断为无效帧
******************************************************************************/
void uds_recv_frame(uint32_t id, uint8_t *frame_buf, uint8_t frame_dlc)
{
if (UDS_REQUEST_ID == id)
uds_tp_recv_frame(0, frame_buf, frame_dlc);
else if (UDS_FUNCTION_ID == id)
uds_tp_recv_frame(1, frame_buf, frame_dlc);
else if (UDS_RESPONSE_ID == id)
handle_uds_state_machine(id, frame_buf, frame_dlc);
}
/******************************************************************************
* 函数名称: void uds_send_frame(uint32_t id, uint8_t* frame_buf, uint8_t frame_dlc)
* 功能说明: 发送一帧报文
* 输入参数: uint8_t response_id --应答 ID
    uint8_t* frame_buf --发送报文帧数据首地址
    uint8_t frame_dlc --发送报文帧数据长度
* 输出参数: 无
* 函数返回: 无
* 其它说明: frame_dlc 长度应当等于 FRAME_SIZE
******************************************************************************/
void uds_send_frame(uint32_t id, uint8_t *data, uint8_t len, uint8_t expect_response)
{
rt_size_t size;
struct rt_can_msg msg = { 0 };
msg.id = id;
msg.ide = (id > 0x7FF) ? 1 : 0;
msg.rtr = 0;
msg.len = len;
memcpy(msg.data, data, len);
size = rt_device_write(g_can_tx_dev, 0, &msg, sizeof(msg));
if (size != sizeof(msg)) {
rt_kprintf("[UDS] Error: Failed to send frame\n");
return;
}
if (expect_response) {
// rt_kprintf("[UDS] Waiting for response... (timeout=2000ms)\n");
}
}
/******************************************************************************
* 函数名称: void uds_init(void)
* 功能说明: UDS 初始化
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 无
******************************************************************************/
void uds_init(void)
{
service_init();
}
/******************************************************************************
* 函数名称: void uds_1ms_task(void)
* 功能说明: UDS 周期任务
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 该函数需要被 1ms 周期调用
******************************************************************************/
void uds_1ms_task(void)
{
network_task();
service_task();
}