215 lines
7.4 KiB
C
215 lines
7.4 KiB
C
#include "app_uds.h"
|
|
#include <string.h>
|
|
#include "stdio.h"
|
|
extern CAN_HandleTypeDef hcan;
|
|
|
|
uint32_t frame_seq_uds_task = 0;
|
|
|
|
/* ===================== Bootloader 启动检查 ===================== */
|
|
|
|
/* Bootloader 启动检查, 必须在 main() 的 HAL_Init 之前调用
|
|
*
|
|
* 原因: 此时 FreeRTOS 未启动, SysTick/PendSV/外设中断均未运行
|
|
* 跳转环境最干净, 直接设 VTOR + MSP + 跳转即可
|
|
*
|
|
* 优先级1: 编程请求(APP收到0x10 0x02 → 写0x12121212 → 复位)
|
|
* → 停留 Bootloader, HAL_Init后清除标志
|
|
* 优先级2: 升级标志
|
|
* flag=UPGRADING → 停留 Bootloader(断电续传)
|
|
* flag=COMPLETE/NONE → 检查栈顶 → 跳转 App
|
|
*/
|
|
void uds_bootloader_check(void)
|
|
{
|
|
/* 如果当前已在App地址运行, 不跳转(避免App无限跳转自己)
|
|
* 关键: App版编译的固件同样包含此函数
|
|
* 若不加此判断, App启动后看到flag=COMPLETE会再次跳转0x08006000(自己)
|
|
* → 无限重启循环, 永远无法正常进入App业务 */
|
|
// if (iap_is_app_mode())
|
|
// return;
|
|
|
|
/* 优先级1: 检查编程请求(APP→Bootloader通信) */
|
|
// if (iap_check_prog_request())
|
|
// return; /* 有编程请求, 停留 Bootloader */
|
|
|
|
uint32_t prog_req = flash_read_word(IAP_PARAM_ADDR + IAP_PARAM_OFF_PROG_REQ);
|
|
if(prog_req == IAP_PROG_REQUEST_MAGIC){
|
|
return;
|
|
}
|
|
|
|
/* 优先级2: 检查升级标志 */
|
|
uint32_t flag = iap_check_flag();
|
|
|
|
/* flag=UPGRADING: 停留 Bootloader, 等待 IAP 升级 */
|
|
if (flag == IAP_FLAG_UPGRADING)
|
|
return;
|
|
|
|
/* flag=COMPLETE 或 NONE: 尝试跳转 App */
|
|
uint32_t app_sp = *(volatile uint32_t *)IAP_APP_ADDR;
|
|
if ((app_sp & 0xFFFE0000) == 0x20000000)
|
|
{
|
|
/* 栈顶合法, 直接跳转(无需关中断, 此时没有中断在运行) */
|
|
SCB->VTOR = IAP_APP_ADDR;
|
|
__set_MSP(app_sp);
|
|
uint32_t app_pc = *(volatile uint32_t *)(IAP_APP_ADDR + 4);
|
|
((void (*)(void))app_pc)();
|
|
}
|
|
|
|
/* 栈顶不合法, 清除标志, 继续运行 Bootloader */
|
|
if (flag == IAP_FLAG_COMPLETE)
|
|
iap_write_flag(IAP_FLAG_NONE);
|
|
}
|
|
|
|
|
|
static void System_Reset(void)
|
|
{
|
|
// 2. 关闭全局中断,防止复位过程被干扰[reference:12]
|
|
__set_FAULTMASK(1);
|
|
// 或者使用 __disable_irq();
|
|
// 3. 执行软件复位[reference:13]
|
|
HAL_NVIC_SystemReset();
|
|
// 4. 程序通常不会执行到这里
|
|
while(1);
|
|
}
|
|
|
|
void uds_frame_handle(CanFrame_t *f)
|
|
{
|
|
CanFrame_t resp = {0};
|
|
resp.id = f->id;
|
|
#if 1
|
|
if(f->id == 0x180)
|
|
{
|
|
uint8_t uds_cmd = f->data[0];
|
|
uint8_t uds_sub_cmd = f->data[1];
|
|
switch(uds_cmd)
|
|
{
|
|
case 0x10:
|
|
switch(uds_sub_cmd)
|
|
{
|
|
case 0x01:
|
|
// 处理 UDS 指令 0x01 0x01
|
|
resp.data[0] = 0x50;
|
|
resp.data[1] = 0x01;
|
|
memset(&resp.data[2], 0, 6);
|
|
resp.dlc = 8;
|
|
if(hwCanSend(resp.id, resp.data, resp.dlc)){
|
|
frame_seq_uds_task++;
|
|
}
|
|
break;
|
|
case 0x02:
|
|
// 处理 UDS 指令 0x01 0x02
|
|
//复位BMS
|
|
System_Reset();
|
|
// resp.data[0] = 0x50;
|
|
// resp.data[1] = 0x02;
|
|
// memset(&resp.data[2], 0, 6);
|
|
// resp.dlc = 8;
|
|
// hwCanSend(resp.id, resp.data, resp.dlc);
|
|
break;
|
|
case 0x03:
|
|
// 处理 UDS 指令 0x01 0x03
|
|
resp.data[0] = 0x50;
|
|
resp.data[1] = 0x03;
|
|
memset(&resp.data[2], 0, 6);
|
|
resp.dlc = 8;
|
|
hwCanSend(resp.id, resp.data, resp.dlc);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case 0x14:
|
|
resp.data[0] = 0x54;
|
|
memset(&resp.data[1], 0, 7);
|
|
resp.dlc = 8;
|
|
hwCanSend(resp.id, resp.data, resp.dlc);
|
|
break;
|
|
case 0x28:
|
|
switch(uds_sub_cmd)
|
|
{
|
|
case 0x01:
|
|
// 处理 UDS 指令 0x02 0x01
|
|
resp.data[0] = 0x68;
|
|
resp.data[1] = 0x01;
|
|
resp.data[2] = 0x03;
|
|
memset(&resp.data[3], 0, 5);
|
|
resp.dlc = 8;
|
|
hwCanSend(resp.id, resp.data, resp.dlc);
|
|
break;
|
|
case 0x02:
|
|
// 处理 UDS 指令 0x02 0x02
|
|
//复位BMS
|
|
resp.data[0] = 0x68;
|
|
resp.data[1] = 0x02;
|
|
resp.data[2] = 0x03;
|
|
memset(&resp.data[3], 0, 5);
|
|
resp.dlc = 8;
|
|
hwCanSend(resp.id, resp.data, resp.dlc);
|
|
break;
|
|
case 0x03:
|
|
// 处理 UDS 指令 0x02 0x03
|
|
resp.data[0] = 0x68;
|
|
resp.data[1] = 0x03;
|
|
resp.data[2] = 0x03;
|
|
memset(&resp.data[3], 0, 5);
|
|
resp.dlc = 8;
|
|
hwCanSend(resp.id, resp.data, resp.dlc);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case 0x85:
|
|
switch(uds_sub_cmd)
|
|
{
|
|
case 0x01:
|
|
// 处理 UDS 指令 0x08 0x01
|
|
resp.data[0] = 0xC5;
|
|
resp.data[1] = 0x01;
|
|
memset(&resp.data[2], 0, 6);
|
|
resp.dlc = 8;
|
|
hwCanSend(resp.id, resp.data, resp.dlc);
|
|
break;
|
|
case 0x02:
|
|
// 处理 UDS 指令 0x08 0x02
|
|
resp.data[0] = 0xC5;
|
|
resp.data[1] = 0x02;
|
|
memset(&resp.data[2], 0, 6);
|
|
resp.dlc = 8 ;
|
|
hwCanSend(resp.id, resp.data, resp.dlc);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
resp.data[0] = 0x7F;
|
|
resp.data[1] = f->data[0];
|
|
resp.data[2] = f->data[1];
|
|
memset(&resp.data[3], 0, 5);
|
|
resp.dlc = 8;
|
|
hwCanSend(resp.id, resp.data, resp.dlc);
|
|
break;
|
|
}
|
|
}
|
|
#else
|
|
if(f->id == 0x180)
|
|
{
|
|
uint8_t uds_cmd = f->data[0];
|
|
uint8_t uds_sub_cmd = f->data[1];
|
|
switch(uds_cmd)
|
|
{
|
|
default:
|
|
resp.id = f->id;
|
|
resp.data[0] = 0x7F;
|
|
resp.data[1] = f->data[0];
|
|
resp.data[2] = f->data[1];
|
|
memset(&resp.data[3], 0, 5);
|
|
resp.dlc = 8;
|
|
hwCanSend(resp.id, resp.data, resp.dlc);
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|