2025-07-22 11:15:46 +08:00
|
|
|
|
/*
|
|
|
|
|
|
*
|
|
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
|
*
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "uds_def.h"
|
2025-10-21 13:59:50 +08:00
|
|
|
|
//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)))
|
|
|
|
|
|
//eg:0x50 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
|
|
|
|
|
|
|
2025-07-22 11:15:46 +08:00
|
|
|
|
static rt_timer_t response_timer;
|
|
|
|
|
|
|
|
|
|
|
|
void response_timeout(void *param)
|
|
|
|
|
|
{
|
|
|
|
|
|
rt_kprintf("\n[UDS] ERROR: Response timeout!\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void init_uds_timers()
|
|
|
|
|
|
{
|
2025-10-21 13:59:50 +08:00
|
|
|
|
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);
|
2025-07-22 11:15:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
|
* 函数名称: 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,否则会被判断为无效帧
|
|
|
|
|
|
******************************************************************************/
|
2025-10-21 13:59:50 +08:00
|
|
|
|
void uds_recv_frame(uint32_t id, uint8_t *frame_buf, uint8_t frame_dlc)
|
2025-07-22 11:15:46 +08:00
|
|
|
|
{
|
2025-10-21 13:59:50 +08:00
|
|
|
|
if (UDS_REQUEST_ID == id)
|
2025-07-22 11:15:46 +08:00
|
|
|
|
uds_tp_recv_frame(0, frame_buf, frame_dlc);
|
2025-10-21 13:59:50 +08:00
|
|
|
|
else if (UDS_FUNCTION_ID == id)
|
2025-07-22 11:15:46 +08:00
|
|
|
|
uds_tp_recv_frame(1, frame_buf, frame_dlc);
|
2025-10-21 13:59:50 +08:00
|
|
|
|
else if (UDS_RESPONSE_ID == id)
|
|
|
|
|
|
handle_uds_state_machine(id, frame_buf, frame_dlc);
|
2025-07-22 11:15:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
|
* 函数名称: 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)
|
|
|
|
|
|
{
|
2025-10-21 13:59:50 +08:00
|
|
|
|
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;
|
2025-07-22 11:15:46 +08:00
|
|
|
|
|
2025-10-21 13:59:50 +08:00
|
|
|
|
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;
|
2025-07-22 11:15:46 +08:00
|
|
|
|
}
|
2025-10-21 13:59:50 +08:00
|
|
|
|
if (expect_response) {
|
|
|
|
|
|
// rt_kprintf("[UDS] Waiting for response... (timeout=2000ms)\n");
|
2025-07-22 11:15:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
|
* 函数名称: 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();
|
|
|
|
|
|
}
|