ECU复位服务就是可以此诊断指令来命令ECU执行自复位,复位有多种形式,依据子功能参数来区分(即客户端使用ECU复位服务来请求服务端重置,重置成功后,将直接进入默认会话)。
通常来说,ECU在收到一条诊断指令后,要先进行相应的处理,执行某些诊断操作,完毕后再发送肯定响应。但是ECU复位服务是个特例,因为它的诊断操作是复位,这时候这个ECU就会重新开始运行,此时ECU也不会记得你前面发过诊断指令,所以复位后没办法ECU就没办法再去发送诊断响应,所以要先发送肯定响应,再执行复位。
注意:从发送完肯定响应到执行复位的这段时间内,ECU是否还可以响应其它诊断请求,标准中没有规定。建议此期间ECU不接受任何请求消息,也不发送任何响应消息。
一般而言,对于11诊断服务,主要应用场景为以下场合:
注意事项:
根据ISO14229-1标准所述,当Client向Server发送11诊断服务请求时,Server可在重置行为完成之后或者开始重启行为之前给到Client
诊断响应,但14229-1强烈推荐的一种做法是:”当Server接受到来自Client的11诊断服务请求时,Server应当先给出诊断响应然后开始重启行为“。
至于为什么如此,我想到一个场景:如果功能寻址请求11诊断服务时(未抑制正响应),在复位未完成之前,一般都会先回复NRC78让Client进行等待,那么对于Client需要根据不同的ECU节点的回复做超时监控,这无疑增加了Client负担,对于Client而言,最为简单的方法就发送完请求,各ECU节点回复正响应,然后各自完成复位操作即可。


由上图2所提到复位类型,复位类型作为subfunction参数来传递给到Server发生相应的重启行为,具体由以下几种类型:

/********************************************************************************
* @file 11_ecu_reset.c
* @author jianqiang.xue
* @version V1.0.0
* @date 2023-05-30
* @brief ECU 复位功能
********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include
#include
#include
#include
#include "modules.h"
#include "os_api.h"
#include "edebug.h"
#include "kv_sys.h"
#include "ecu_ble_uart.h"
/* Private includes ----------------------------------------------------------*/
#include "std_math.h"
#include "app_can.h"
#include "can_nm.h"
#include "app_nm.h"
#include "diag_main.h"
/* Private define ------------------------------------------------------------*/
#define UDS_ID 0x11
/* Private typedef -----------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static uint8_t ecu_reset_req = 0;
/***************软定时器创建***************/
/* Private func --------------------------------------------------------------*/
void post_func(uint8_t val) {
(void)val;
if (ecu_reset_req) {
diag_main_send_signal(SIGNAL_DIAG_RESET);
}
}
void uds11_main(nwl_msg_t* p) {
uint8_t data[10];
ecu_reset_req = 0;
if (p->len != 2) {
send_nrc_data(UDS_ID, NRC_INCORRECT_MESSAGE_LENTH);
goto end;
}
switch (p->data[1] & 0x7F) { // 子功能,bit7为应答位。 =1则不允许应答
case 0x01: // 硬件复位
if ((g_car_ste.IPB.bit.VehicleSpeedVld == 1) && (get_car_speed() > 3)) {
send_nrc_data(UDS_ID, NRC_CONDITION_NOT_CORRECT);
goto end;
}
if (p->data[1] & 0x80) {
// 应用无需应答
} else {
// 回复正响应码 单帧格式: len, 服务ID|0x40, 子功能ID,
data[0] = 2; // 数据总长度=数据长度+服务号
data[1] = UDS_ID | 0x40; // 服务号,回复上位机需要 |0x40
data[2] = p->data[1];
memset(&data[3], 0xAA, 5);
app_can_enqueue_msg(CAN_MSG_EVENT_SEND, NWL_RES_ADDR, data, 8);
g_p2_service_time_remaining = 0; // 如果发送诊断报文,则清除倒计时。P2_SERVER_MAX
os_delay(1);
}
ecu_reset_req = 1;
break;
default:
send_nrc_data(UDS_ID, NRC_SUBFUNCTION_NOT_SUPPORTED);
break;
}
end:
return;
}
#if AUTOSAR_DIAG_SWITCH && USE_UDS_11
DIAG_SERVICE_REG(UDS_ID, DIAG_NO_SECURITY_LEVEL, (DEFAULT_SESSION|PROGRAMMING_SESSION|EXTENDED_SESSION),
(DIAG_PHYS_REQ|DIAG_FUNC_REQ), NULL, post_func, uds11_main);
#endif