一. 简介

本人就职于北京的一家汽车电子科技公司,接到了广汽的订单。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. window10+python3.7安装tensorflow--gpu tensorflow 安装
  2. 隔空操作之通过简单计算识别手的挥动反向
  3. linux centos 使用 alpine 编译的二进制文件 报错 /lib/ld-musl-x86_64.so.1: bad ELF interpreter 解决方法
  4. HDU 1846 Brave Game
  5. ORACLE ROLLUP CUBE
  6. ASP.NET Core on K8S学习初探(3)部署API到K8S
  7. nacl溶解度_运用溶解度曲线判断混合物分离、提纯的方法
  8. 机器学习算法基础5-决策树与随机森林
  9. 鳄梨种植者使用传感器节省种植成本
  10. ffempge常用指令_fluent-ffmpeg 常用函数
  11. Python命令行command not found
  12. Java并发编程实战10:线程池
  13. 2021中国医疗机器人产业创新大会参会指南
  14. 强化学习--蒙特卡洛法
  15. MP4 全介绍【转载】
  16. 7-2 程序改错题4 (5 分)
  17. 【统计计算】关于Jackknife的理解和推导
  18. 二、赛普拉斯EZ-USB FX3示例烧录验证
  19. H.264 序列参数集(SPS)
  20. python樱花手绘_宫崎骏动画里的新垣结衣见过没?这个开源动漫生成器让你的照片秒变手绘日漫...

热门文章

  1. (2)source和sink详解
  2. 第十章 :hbase集群搭建,测试
  3. 2020年7月 :国产数据库名录和产品信息一览
  4. SVN 打补丁 Apply Patch ***
  5. 第二篇:mybatis核心接口
  6. rocketmq 消息出现 NOT_CONSUME_YET
  7. oracle日期格式和java日期格式区别 HH24:mm:ss和HH24:mi:ss的区别
  8. 编程中无穷大常量的设定技巧(ox3f3f3f3f)
  9. 【11款最全最新】Java游戏开发项目合集_Java项目实战_Java练手项目
  10. SweetAlert 插件