一. 简介

本人就职于北京的一家汽车电子科技公司,接到了广汽的订单。22年4月份接到一个订单:广汽乘用车M8,OTA升级的开发。OTA(Over-the-Air Technology),理解的话就是:无线传输技术。本次的开发,运用到的知识包括:TCP/IP协议,DoIP协议,UDS协议,开发语言为C语言,开发环境为Linux,gcc编译,Linux环境下调试,Make文件等等。

二. 协议简述

TCP/IP协议就不说了,它是互联网通信的最常用的一个通信协议,自我20年开始工作以来,首先负责的就是网络通信这一块。

DoIP是基于TCP/IP协议的一个通信协议,协议格式如下图:

这个协议栈,是公司买的AUTOSAR的软件,可以根据需求直接在软件上进行配置,然后直接生成代码。软件如下图:

UDS协议,本次OTA开发,运用了多种协议,协议之间的关系为嵌套。UDS嵌套入DoIP协议,DoIP协议嵌入TCP协议。下图简单介绍了,何为UDS协议,UDS具体划分为哪些功能。

 三. 程序流程

整个升级流程分为两个阶段,预升级阶段,升级阶段。

第一阶段,为预升级阶段,验证版本号,会话模式切换,例程控制,DTC控制设置,通信控制。

第二阶段,到了实际的升级流程。其流程图如下:

会话模式切换,秘钥申请,写入ID,下载flash driver文件,例程控制

OTA的核心部分是下面三个步骤:

#34 请求下载

#36 传输数据

#37 下载结束

 四. 程序简要

所有的程序都在INVO-OTA文件下面,整体的架构为,OTA功能,在整个工程中相当于线程;编译这个程序后,会生成静态库文件.so ,供其他地方调用。

工程文件如下图左侧

lib_ota.c ota初始化部分,及与上位机直接调用的接口。程序的设计思路是,写一个结构体,结构里面包含了上位机所需要调用到的函数接口。

#include "Network_DoIP_SoAd_Sys.h"
#include "Dcm/Dcm.h"
#include "Invo_Upgrade_Flag.h"
#include "invo_ota_lib.h"static InvoOtaObj ota_obj;
static doip_config_t g_config;static INVO_OTA_DATA_CALLBACK invo_ota_lib_get_data_callback_handler();
static INVO_OTA_UDS_MSG_CALLBACK invo_ota_lib_get_uds_msg_callback_handler();bool invo_ota_lib_init(doip_config_t *config)
{if (config){g_config = *config;}else{(void)memset(&g_config, 0, sizeof(g_config));}struct bl_mesg msg;bool ret = FALSE;bzero( &ota_obj, sizeof( ota_obj ) );ota_obj.dcmflag = TRUE;ota_obj.DoIPConfigObj = 1;if(1){TcpIp_Init();SoAd_Init();DoIP_Init( &ota_obj.DoIPConfigObj );Dcm_Init( NULL );DoIP_ActivationLineSwitchActive();ota_obj.inited = TRUE;ret = TRUE;PR_ERROR( "invo lib ota init successed!." );}else{ret = FALSE;}PR_ERROR("-----------------------------------------------");PR_ERROR("version :%d", 1);PR_ERROR("-----------------------------------------------");return ret;
}void invo_ota_lib_main()
{if ( ota_obj.inited ){SoAd_MainFunction();DoIP_MainFunction();Dcm_MainFunction();usleep(5000);}
}void invo_ota_lib_deinit()
{if ( ota_obj.inited ){TcpIp_DeInit();SoAd_DeInit();Dcm_DeInit();bzero( &ota_obj, sizeof( ota_obj ) );ota_obj.dcmstart = false;ota_obj.is_data_callback_inited = false;ota_obj.is_msg_callback_inited = false;ota_obj.inited = false;}
}/*------------------------------------------------------------------------------* doip_get_path-------------------------------------------------------------------------------*/
char *doip_get_path(void)
{return g_config.download_path;
}/*------------------------------------------------------------------------------* doip_space_check-------------------------------------------------------------------------------*/
int doip_space_check(uint64_t size)
{int  ret = -1;if(1) // (g_config.do_install){ret = g_config.do_space_check(size);}return ret;
}/*------------------------------------------------------------------------------* doip_do_install-------------------------------------------------------------------------------*/
void doip_do_install(char *path)
{if (g_config.do_install){g_config.do_install(path);}
}/*------------------------------------------------------------------------------* doip_write_did ***************************Start Change************************-------------------------------------------------------------------------------*/
void doip_write_did(uint16_t did, uint8_t *data, uint32_t size)
{if (g_config.do_write_did){g_config.do_write_did(did, data, size);}
}/*------------------------------------------------------------------------------* doip_read_did-------------------------------------------------------------------------------*/
void doip_read_did(uint16_t did, uint8_t *data)
{if (g_config.do_read_did){g_config.do_read_did(did, data);}
}/*------------------------------------------------------------------------------* doip_do_reboot-------------------------------------------------------------------------------*/
void doip_do_reboot(void)
{if (g_config.do_reboot){g_config.do_reboot();}
}/*------------------------------------------------------------------------------* doip_get_update_state-------------------------------------------------------------------------------*/
doip_install_state_t doip_get_update_state(void)
{if (g_config.get_update_state){return g_config.get_update_state();}return INSTALL_STATE_ERR;
}

lib_ota_lib_if.h 头文件,包含了结构体类型的函数接口,宏定义数据,ENUM变量,函数引用

#ifndef _INVO_OTA_LIB_IF_H_
#define _INVO_OTA_LIB_IF_H_#ifdef __cplusplus
extern "C" {
#endif
/*
** ===================================================================
**     Include files.
** ===================================================================
*/#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>/*
** ===================================================================
**     Macro definition.
** ===================================================================
*/
typedef enum
{INVO_OTA_UDS_NORMAL_MSG_PROCESS  = 0x1U,INVO_OTA_UDS_ERROR_MSG_PROCESS   = 0x2U,INVO_OTA_BEING_DATA_PROCESS      = 0x3U,INVO_OTA_SUSPEND_DATA_PROCESS    = 0x4U,INVO_OTA_FINISH_DATA_PROCESS     = 0x5U
} INVO_OTA_PROCESS_STATUS;typedef enum
{OTA_LIB_CMD_NONE = 0,OTA_LIB_CMD_UDS = 1U,OTA_LIB_CMD_RESET = 2U,OTA_LIB_CMD_RESERVED
} INVO_OTA_LIB_CMD;typedef struct
{INVO_OTA_PROCESS_STATUS status;INVO_OTA_LIB_CMD cmd;int length;unsigned char* data;
} ota_lib_message_t;typedef enum
{INSTALL_STATE_NOSTART,INSTALL_STATE_RUNNING,INSTALL_STATE_OK,INSTALL_STATE_ERR,
} doip_install_state_t;typedef enum
{STATE_ACTIVATE,STATE_NEGATIVE,
} doip_activeline_state_t;typedef struct
{char download_path[128];int  (*do_space_check)(uint64_t size);int  (*do_install)(char *path);int  (*do_write_did)(uint16_t did, uint8_t *data, uint32_t size);int  (*do_read_did)(uint16_t did, uint8_t *data);void (*do_reboot)(void);doip_install_state_t (*get_update_state)(void);doip_activeline_state_t (*get_activeline_state)(void);
} doip_config_t;typedef void ( *INVO_OTA_DATA_CALLBACK )( INVO_OTA_PROCESS_STATUS status,void* data, uint32_t data_size );typedef void ( *INVO_OTA_UDS_MSG_CALLBACK )( ota_lib_message_t msg );/*
** ===================================================================
**     func definition.
** ===================================================================
*/
extern bool invo_ota_lib_init(doip_config_t *config);
extern void invo_ota_lib_main();
extern void invo_ota_lib_deinit();
extern bool invo_ota_lib_get_init_flag();
extern bool invo_ota_lib_get_dcm_flag();
extern bool invo_ota_lib_get_sys_flag();
extern int invo_ota_lib_get_upgrade_flag();extern void invo_ota_lib_set_uds_msg( unsigned char* usdmsg, int len );
extern void invo_ota_lib_register_data_callback( INVO_OTA_DATA_CALLBACK callback );
extern void invo_ota_lib_register_uds_msg_callback( INVO_OTA_UDS_MSG_CALLBACK callback );extern void invo_ota_lib_SndPragramSessResp( void );
extern void invo_ota_lib_SndRespPending( void );
extern void invo_ota_lib_DoIP_SndEcuResetResp( void );
extern void invo_ota_lib_SndEcuUpgradeFailure();#ifdef __cplusplus
}
#endif /* extern "C" */#endif /* INVO_OTA_IFS_H */

#34 写文件请求

/************************************************************************************
* Name         :  DiagServ_RequestDownload
* Called by    :  DiagServ_Task
* Preconditions:  None
* Parameters   :  None
* Return code  :  TRUE  - Request has been accepted.
*                 FALSE - Request is not allowed.
* Description  :  Request to start a download progress.
*************************************************************************************/boolean DiagServ_RequestDownload( uint32 uiMemAddr, unsigned long int uiMemSize )
{boolean ret = FALSE;do{//PR_INF("%s ucLogicType = %d", __func__, stSocUpdateInfo.ucLogicType);if ( ( TRUE == stSocUpdateInfo.bTransDataAllowed )|| ( LOGIC_TYPE_IDLE == stSocUpdateInfo.ucLogicType )|| ( LOGIC_TYPE_ERASING == stSocUpdateInfo.ucLogicType ) ){//PR_INF("%s, break", __func__);break;}stSocUpdateInfo.bTransDataAllowed = TRUE;stSocUpdateInfo.uiMemAddr = uiMemAddr;stSocUpdateInfo.uiMemSize = uiMemSize;stSocUpdateInfo.uiDataIdx = 0U;stSocUpdateInfo.uiDataLen = 0U;stSocUpdateInfo.ucSectionIdx = 0U;Dcm_WriteFileReq(uiMemSize);if ( LOGIC_TYPE_SOC_DRV == stSocUpdateInfo.ucLogicType ){PR_INF("LOGIC_TYPE_SOC_DRV == stSocUpdateInfo.ucLogicType");ret = TRUE;}else if ( LOGIC_TYPE_SOC_APP == stSocUpdateInfo.ucLogicType ){PR_INF("LOGIC_TYPE_SOC_APP == stSocUpdateInfo.ucLogicType");ret = TRUE;}else{//PR_INF("ret = FALSE");ret = FALSE;}}while ( 0 );if ( FALSE == ret ){_ClrSocUpdateInfo();}return ( ret );
}

#36 文件传输数据

/************************************************************************************
* Name         :  DiagServ_TransferData
* Called by    :  DiagServ_ProgramTask
* Preconditions:  None
* Parameters   :  None
* Return code  :  None
* Description  :  Transfer data request, write data into RAM or FLASH.
*************************************************************************************/
boolean DiagServ_TransferData( uint8 ucSectionIdx, uint16 usDateSize, uint8* pucData )
{boolean ret = FALSE;//PR_INF("%s ucLogicType = %d************************", __func__, stSocUpdateInfo.ucLogicType);do{if ( ( FALSE == stSocUpdateInfo.bTransDataAllowed )|| ( usDateSize > TRANS_DATA_LEN_MAX )|| ( ucSectionIdx != ( stSocUpdateInfo.ucSectionIdx + 1 ) )|| ( ( stSocUpdateInfo.uiDataLen + usDateSize ) > stSocUpdateInfo.uiMemSize ) ){if ( stSocUpdateInfo.ucSectionIdx == 0xFF ){stSocUpdateInfo.ucSectionIdx = 0x01;}else{PR_DEBUG( 1U, " SOC condition falied!  %d               %d     \n", usDateSize, stSocUpdateInfo.ucSectionIdx );break;}}stSocUpdateInfo.ucSectionIdx = ucSectionIdx;Ethernet_OTA_MemcpytoShmBufferData( &stSocUpdateInfo.ucDataBuffer, pucData, usDateSize );PR_DEBUG( 0U, "usDateSize:%u.\n", usDateSize );//uiCurrMemAddr = stSocUpdateInfo.uiMemAddr + stSocUpdateInfo.uiDataIdx;stSocUpdateInfo.uiDataIdx += usDateSize;stSocUpdateInfo.uiDataLen += usDateSize;stSocUpdateInfo.uiOldCrc32 = GetCrc32( stSocUpdateInfo.ucDataBuffer, usDateSize, stSocUpdateInfo.uiOldCrc32 );switch ( stSocUpdateInfo.ucLogicType ){case LOGIC_TYPE_SOC_DRV:{ret = TRUE;stSocUpdateInfo.count = 1;break;}case LOGIC_TYPE_SOC_APP:{if ( stSocUpdateInfo.count == 1 ){stSocUpdateInfo.count = 0;}//Ethernet_OTA_ProcessUpgradeData( stSocUpdateInfo.ucDataBuffer, usDateSize );Dcm_WriteDataToFile(stSocUpdateInfo.ucDataBuffer, usDateSize);ret = TRUE;break;}default:{PR_DEBUG( 1U, "SOC default falied!  %d               %d     \n", usDateSize, stSocUpdateInfo.ucSectionIdx );break;}}}while ( 0 );if ( FALSE == ret ){_ClrSocUpdateInfo();}return ( ret );
}

#37 传输结束

/************************************************************************************
* Name         :  DiagServ_TransferExit
* Called by    :  DiagServ_ProgramTask
* Preconditions:  None
* Parameters   :  None
* Return code  :  None
* Description  :  Transfer data end, new transfer request can be allowed.
*************************************************************************************/
boolean DiagServ_TransferExit( void )
{PR_INF(" %s start...", __func__);uint8 crc = 1;boolean ret = FALSE;do{PR_DEBUG( 0, "%s     \n", __func__ );PR_DEBUG( 0, "%ld  %ld  \n", stSocUpdateInfo.uiDataLen, stSocUpdateInfo.uiMemSize );PR_INF("bTransDataAllowed %ld ", stSocUpdateInfo.bTransDataAllowed);// PR_INF("stSocUpdateInfo.uiDataLen = %ld uiMemSize %ld  \n", stSocUpdateInfo.uiDataLen, stSocUpdateInfo.uiMemSize);if ( ( FALSE == stSocUpdateInfo.bTransDataAllowed )|| ( stSocUpdateInfo.uiDataLen != stSocUpdateInfo.uiMemSize )){PR_INF(" %s, break ", __func__);break;}stSocUpdateInfo.bTransDataAllowed = FALSE;if ( LOGIC_TYPE_SOC_DRV == stSocUpdateInfo.ucLogicType ){PR_INF("LOGIC_TYPE_SOC_DRV == stSocUpdateInfo.ucLogicType ");stSocUpdateInfo.ucLogicType = LOGIC_TYPE_ERASING;}else{//Ethernet_OTA_FinishUpgradeProcessing();Dcm_WriteFileEnd(&crc);PR_INF("%s else ",__func__);}ret = TRUE;PR_INF(" %s ret = TRUE", __func__);}while ( 0 );if ( FALSE == ret ){_ClrSocUpdateInfo();}PR_INF(" %s end...", __func__);return ( ret );
}

代码部分太多了,这里就不介绍了。

五.  总结

这个项目开发了三,四个月,并且后期也一直在维护。期间还去广州广汽研究院那边出过一次差。期间遇到了很多问题,比如需要找人协调调试设备,需要跟测试部沟通,然他们编写测试程序,需要组织讨论问题的解决方案;自己出差的时候要在实车上进行调试程序,需要给甲方讲解清问题原因,问题的解决方案等等。

这是我毕业两年多来,做的最有成就感的一个项目。

基于车载以太网的OTA升级相关推荐

  1. 车载以太网时间同步之EthTsync

    车载以太网时间同步之EthTsync 前言 首先,请问大家几个小小问题,你清楚: 你知道EthTsync模块的主要作用是什么吗? EthTsync模块与其他AUTOSAR基础软件模块交互关系: Eth ...

  2. 基于AUTOSAR的车载以太网通信技术与实现

    随着处理器运算能力和硬件的高速发展,汽车整车功能越来越多.越来越强.鉴于 ADAS 技术.高品质车载娱乐以及 OTA 远程升级等新增功能的需求,使得 ECU 的网络带宽需求也呈现爆发式增长.这一需求超 ...

  3. 乐鑫esp8266基于freeRtos实现私有服务器本地远程OTA升级

    代码地址如下: http://www.demodashi.com/demo/13533.html 文章目录 一.前言: 二.回顾下`OTA`的流程: 三.`lwip`网络框架的知识的使用: 四.如何处 ...

  4. 基于 Marvell 88Q2112 车载以太网 物理层收发器

    Marvell 88Q2112 车载以太网 物理层收发器 介绍 88Q2112 是一款基于 IEEE 802.3bw 和 IEEE 802.3bp 定义的 100/1000BASE-T1 以太网物理层 ...

  5. 基于OSI模型的车载以太网

    一. 车载以太网是汽车内部使用的网络连接技术,支持各个电子设备之间的传输和通信. 车载以太网的实现功能:娱乐系统.导航系统.车辆诊断维护.驾驶辅助. 车载以太网较传统以太网的差异:根据使用环境,车载以 ...

  6. 乐鑫esp8266学习rtos3.0笔记第6篇:esp8266-12模块基于rtos3.1版本ota功能远程空中升级固件,官网之上增加dns域名解析!(附带demo)

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 1. Esp8266之 搭建开发环境,开始一个"hello ...

  7. Android 系统 '七夕'巨献 VIVO Xplay 基于ViVo官方稳定内核,完美root,适度美化,降噪点,完美支持官方OTA升级

    ROM版本 VIVO-Xplay-PD2.13.2 ROM作者 大盛 http://weibo.com/DaShengdd Android版本 Android4.2.2 创建日期 2013.08.13 ...

  8. 车载以太网会是传统总线的末路吗?

    今天我们不聊高深的技术问题,怿星带大家看看车载以太网是怎么走到今天的. 2013年宝马X5的正式量产标志着以太网正式进入到车载领域,粗略计算已有7年的时间,它究竟有什么魔力让我们一个又一个的汽车人前赴 ...

  9. AUTOSAR OTA升级

    一.OTA技术概念 随着高级辅助驾驶的发展和自动驾驶的引入,汽车变得越来越智能,这些智能汽车被软件控制,装有巨量的软件程序,当出现一个软件程序问题或者更新时,如果 按照传统的解决方式 ,那都将是一项很 ...

最新文章

  1. python中的运算符举例_举例讲解Python中的身份运算符的使用方法
  2. 你的Windows电脑里有哪些效率翻倍的生产力软件?
  3. python爬虫可视化界面_python爬虫---垃圾分类可视化界面
  4. solrcloud集群搭建
  5. Linux下根据进程ID查看进程文件的路径
  6. ymodem协议c语言,STC单片机ISP-Demo-使用Y-Modem协议源码与库函数分享
  7. SVM基本思想及入门学习(转载+自己解释为什么minL(w)变成minmaxL(a,w))
  8. DataView的ToTable方法,类似数据库Distinct。
  9. 浅入浅出 Android 安全:第五章 Android 应用层安全
  10. 浅析SQL SERVER执行计划中的各类怪相
  11. 如何用MobaXterm查看日志信息以及xml
  12. 微软测试新工具:让Windows 10和Android设备文件同步更方便
  13. 分页组件change_javascript原生瀑布流+图片懒加载组件
  14. TML5 App 开发框架收集
  15. Java基础教程【第五章:Java数组】
  16. python自动检测网站_Web全自动化测试Python + Pytest+Selenium+ Saucelabs 转
  17. Hadoop的shell命令
  18. sublime使用LiveReload自动刷新
  19. 华为云文字识别服务关键技术、能力和产品落地需要注意的事宜(OCR系列二)
  20. 科普 | 金融衍生品系列——互换

热门文章

  1. SQL -- distinct 函数的用法
  2. Java多线程爬虫,爬取酷我音乐排行榜全部音乐示例
  3. 关于IjkVideoView或Android VideoView seekTo不精确问题
  4. 安卓java编辑器eclipse_Eclipse开发Android源码的详细教程
  5. 天猫优惠券面值可以随意修改
  6. 把域名和IP地址绑定后,利用域名+端口号访问自己搭建的网站
  7. C++实现员工管理系统
  8. 我写的诗 - 天外飞仙
  9. QQ炫舞分析 - 得分判断
  10. java时间复杂度计算_时间复杂度到底怎么算