嵌入式眼光看Ecu

都云作者痴,谁解其中味?  协议大师

 

(刚开始分析源码,有新的挑战在等待。放弃bs1800分析挺可惜、挺遗憾的)



 

ECU开发软件架构:

 

1      顺序+中断

 

2      队列+中断

                      VDO:11BS1800

                               深析:分优先级、分配时间片的管理模式。

3      函数指针队列(ipc服务)

 

4      简单RTOS    (ecos  bosch;  mtos   siemens ..... )

 

5      符合OSEK标准的RTOS(OSRK-WORKS)

 

6      符合AUTO-SAR标准的RTOS(绝对的UML的产物)

 

       满足任务管理的复杂型和时间的实时性是关键。多数研究机构跟随外国的步伐,可没一个很成熟的。个人愚见是做太不深入。

深入了解计算机和深入了解发动机才是成功的关键。


 

深入了解计算机:

                            数据结构:结构体、队列、链表、函数指针、函数指针数组(处理通信妙用);

                            内存管理:flash技术、自适应数据管理、故障诊断内存管理;

                            全局变量的管理:全局变量  大型软件的双刃剑;

                            IPC服务管理(信号量,消息队列,邮箱,内存碎片管理,堆栈管理);

 

                            时间:        1  处理器自身时间资源分配

                                                       输入捕捉输出比较、定时器(重中之重)、计数器

                                                       PWM信号、SPI、UART的波特率、KWP、CAN位定时

                                             2  采集时间分配

                                                       空气流量传感器------油位传感器---------车速传感器

                                                       函数执行的时间分配

                                             3   协议时间满足

                                                       从UART到CAN到FLEXRAY 时间要求越来越复杂。

                            编程技巧:

                                             1    不用浮点运算

                                             2    查表计算的运算速度

                                             3    switch(jump-table)比if要快7-8倍

                                             4   指针妙用 不愧有人说C语言的精华在指针

                           bug:

                                              作为一个复杂的嵌入式系统,bug不免在其中,国际组织从c语言这个源头就开始重视,毕竟c是存在缺陷

 

 

                            软件加密: 

                                             加密算法分析:

 

                            CRC16效验:  

                                              查表数据:和linux的一模一样

0, 0C0C1h, 0C181h, 140h, 0C301h, 3C0h, 280h, 0C241h, 0C601h, 6C0h, 780h, 0C741h, 500h, 0C5C1h, 0C481h, 440h 0CC01h, 0CC0h, 0D80h, 0CD41h, 0F00h, 0CFC1h, 0CE81h, 0E40h, 0A00h, 0CAC1h, 0CB81h, 0B40h, 0C901h, 9C0h, 880h, 0C841h ;  0D801h, 18C0h, 1980h, 0D941h, 1B00h, 0DBC1h, 0DA81h, 1A40h, 1E00h, 0DEC1h, 0DF81h, 1F40h, 0DD01h, 1DC0h, 1C80h, 0DC41400h, 0D4C1h, 0D581h, 1540h, 0D701h, 17C0h, 1680h, 0D641h, 0D201h, 12C0h, 1380h, 0D341h, 1100h, 0D1C1h,  0F001h, 30C0h, 3180h, 0F141h, 3300h, 0F3C1h, 0F281h, 3240h, 3600h, 0F6C1h, 0F781h, 3740h, 0F501h, 35C0h, 3480h, 0F441h3C00h, 0FCC1h, 0FD81h, 3D40h, 0FF01h, 3FC0h, 3E80h, 0FE41h, 0FA01h, 3AC0h, 3B80h, 0FB41h, 3900h, 0F9C1h, 0F881h, 3840h2800h, 0E8C1h, 0E981h, 2940h, 0EB01h, 2BC0h, 2A80h, 0EA41h, 0EE01h, 2EC0h, 2F80h, 0EF41h, 2D00h, 0EDC1h, 0EC81h, 2C40h0E401h, 24C0h, 2580h, 0E541h, 2700h, 0E7C1h, 0E681h, 2640h, 2200h, 0E2C1h, 0E381h, 2340h, 0E101h, 21C0h, 2080h, 0E041h  0A001h, 60C0h, 6180h, 0A141h, 6300h, 0A3C1h, 0A281h, 6240h, 6600h, 0A6C1h, 0A781h, 6740h, 0A501h, 65C0h, 6480h, 0A441h,,6C00h, 0ACC1h, 0AD81h, 6D40h, 0AF01h, 6FC0h, 6E80h, 0AE41h, 0AA01h, 6AC0h, 6B80h, 0AB41h, 6900h, 0A9C1h, 0A881h, 6840h7800h, 0B8C1h, 0B981h, 7940h, 0BB01h, 7BC0h, 7A80h, 0BA41h, 0BE01h, 7EC0h, 7F80h, 0BF41h, 7D00h, 0BDC1h, 0BC81h, 7C40h0B401h, 74C0h, 7580h, 0B541h, 7700h, 0B7C1h, 0B681h, 7640h, 7200h, 0B2C1h, 0B381h, 7340h, 0B101h, 71C0h, 7080h, 0B04 5000h, 90C1h, 9181h, 5140h, 9301h, 53C0h, 5280h, 9241h, 9601h, 56C0h, 5780h, 9741h, 5500h, 95C1h, 9481h, 5440h9C01h, 5CC0h, 5D80h, 9D41h, 5F00h, 9FC1h, 9E81h, 5E40h, 5A00h, 9AC1h, 9B81h, 5B40h, 9901h, 59C0h, 5880h, 9841h8801h, 48C0h, 4980h, 8941h, 4B00h, 8BC1h, 8A81h, 4A40h, 4E00h, 8EC1h, 8F81h, 4F40h, 8D01h, 4DC0h, 4C80h, 8C41h4400h, 84C1h, 8581h, 4540h, 8701h, 47C0h, 4680h, 8641h, 8201h, 42C0h, 4380h, 8341h, 4100h, 81C1h, 8081h, 4040h

 

 

 

                             CPU_LOAD负荷计算:   平淡无奇的数字中隐藏着科学的魅力

 

                              Bootloader分析:

 

                                               1: 总线检查    嵌入式c++编程有介绍

 

                                            mov     r8, #1          ;

                          L1                          
                                             mov     [r0], r8        ;
                                             nop                     ;
                                             cmp     r8, [r0]        ;
                                             jmpr    cc_NZ, ERR_TASK  ; 总线错误处理
                                             shl     r8, #1 

                                             jmpr    cc_NC,L1 ;

 

 

 

 

 


 

 

深入了解发动机:

                           信号处理:

                                      氧传感器信号处理是最复杂的  

                                      滤波(在动态情况下尽量放映实际情况) 

 

                           闭环控制器:

                                         可靠性和鲁棒性以及可控性

 

                                         经典PID控制处处可见

 

                                         扭矩控制

 

                                         spi外围件控制

 

 

 


 

 

需求分析: 

                             ECU做为嵌入式软件的软件指标,可靠性、实时性、安全性。

                             满足接口标定和诊断

                             多个传感器采集(采集时间分配的合理性)、数据处理的正确性,诊断以及输出功率器件的管理

                             复杂的有限状态机转换(发动机工况转换和步进电机状态转化、氧传加热状态、碳管状态)

                             真实计算出发动机特性参数(流体力学方程)

                             近千张MAP查询(尽量避免浮点运算)

                             近2千个变量的管理(数据共享问题是最头疼的问题)

                            通信协议

 

 

软件数据流分析:

 

 

 

 


 

ECU协议:

 

 

 1    CAN协议栈

 2    kwp协议  uds协议

                                 先分析基于串口的KWP2000协议及其具体实现:

 

 

                               已经完成的uds协议      贴出数据处理的解码部分程序 数据结构和算法都很先进   性能还不错 挺满意

 

 

                        unsigned char Decode(unsigned char *buff)
{
          
    unsigned int thr[4]={0x6e69,0x6961,0x6e69,0x6e62};
   keys=bytek(&thr[0],SCANTOOL_DATE,4);
   switch (puff>>4)
   {      
         
       case  type_sf:
            
             sf.type=type_sf;
             sf.data_len=puff&0x0f;
             buff++;
            
             if((sf.data_len)>0&&(sf.data_len<8))
             {
                for(i=0;i<=sf.data_len;i++,buff++)
                {
                 sf.data[i]=*buff;                          
                }
             }
             else
             {
                 return err_date;
             }
            
              sev_id=sf.data[0];
              dec_stat=1;
              break;
             
       case  type_ff : 
                /*在接受数据方面还需完善*/
               
             ff.type=type_ff;
             ff.data_len=(puff&0x0f)<<8;
             buff++;
             ff.data_len=(ff.data_len|(*buff++))&0x0fff;
             //printf("%d/n",ff.data_len);
             i_ff=0;
            
             if(ff.data_len<7)
              return err_date;
              
                 sev_id=ff.data[0];
           
                  /*何时发送起始帧?*/
              break;
             
       case  type_cf :

             cf.type=type_cf;
             cf.data_len=puff&0x0f;
             buff++;             
             for(i=0;i<7;i_ff++,*buff++,i++)
             {
                if(i_ff<ff.data_len)
                ff.data[i_ff]=*buff;
                else
                dec_stat=1;
             }
            
              break;
       case  type_fc:
            
              fc.fs=puff&0x0f;
                         
              dec_stat=1;
              fc_stat=1;      
              buff++;
              fc.bs=*buff++;
              fc.stmin=*buff++;//需细化处理 
              break;
           
       default:
               break;
   }
  
   return err_no;     
}

 

 

 3    1939协议

 4     CCP协议    贴出俺的ccp协议的部分服务程序

                case CC_START_STOP: /* Cyclic aquisition start/stop */
        {
          #define ssCmd                 com[2]  /* Start or Stop */
          #define ssDaq                 com[3]  /* DAQ list */
          #define ssLast                com[4]  /* Last ODT to send */
          #define ssEventChannel        com[5]  /* Event Channel Number */
          #define ssPrescaler (*(CCP_WORD*)&com[6]) /* Prescaler */

          #ifdef CCP_SEED_KEY
            if (!(ccp.ProtectionStatus&PL_DAQ))
              ccp.Crm[1] = CRC_ACCESS_DENIED;
            else
          #endif
          if (!(ccp.SessionStatus&SS_DAQ)) { /* Not initialized */
           ccp.Crm[1] = CRC_DAQ_INIT_REQUEST;
          }
          else {
            switch (ssCmd) {
              case 0: /* stop */
                ccpStopDaq(ssDaq);
                break;
              case 1: /* start */
                ccpPrepareDaq(ssDaq,ssLast,ssEventChannel,ssPrescaler);
                ccpStartDaq(ssDaq);
                #ifdef CCP_TESTMODE
                  if (gDebugLevel) ccpPrintDaqList(ssDaq);
                #endif
                break;
              case 2: /* prepare */
                ccpPrepareDaq(ssDaq,ssLast,ssEventChannel,ssPrescaler);
                #ifdef CCP_TESTMODE
                  if (gDebugLevel) ccpPrintDaqList(ssDaq);
                #endif
                break;
              default:
                ccp.Crm[1] = CRC_CMD_SYNTAX;
                break;
            }
          }

          #ifdef CCP_TESTMODE
            if (gDebugLevel) CCPPRINT("%u: START_STOP cmd=%u,daq=%u,last=%u,eventChannel=%u,prescaler=%u/n",ctr,ssCmd,ssDaq,ssLast,ssEventChannel,ssPrescaler);
          #endif

          #undef ssCmd
          #undef ssDaq
          #undef ssLast
          #undef ssEventChannel
          #undef ssPrescaler
        }
        break;

      case CC_START_STOP_ALL: /* Cyclic aquisition start/stop */
        {
          #define ssCmd                 com[2]  /* Start or Stop */

          #ifdef CCP_SEED_KEY
            if (!(ccp.ProtectionStatus&PL_DAQ))
              ccp.Crm[1] = CRC_ACCESS_DENIED;
            else
          #endif
          if (!(ccp.SessionStatus&SS_DAQ)) { /* Not initialized */
           ccp.Crm[1] = CRC_DAQ_INIT_REQUEST;
          } else {
            switch (ssCmd) {
              case 0: /* Stop */
                ccpStopAllDaq();
                break;
              case 1: /* Start */
                ccpStartAllPreparedDaq();
                break;
              default:
                ccp.Crm[1] = CRC_CMD_SYNTAX;
                break;
            }
          }
          #ifdef CCP_TESTMODE
            if (gDebugLevel) CCPPRINT("%u: START_STOP_ALL cmd=%u/n",ctr,ssCmd);
          #endif

          #undef ssCmd
        }
        break;

      #endif /* CCP_DAQ */

      #ifdef CCP_CHECKSUM

      case CC_BUILD_CHKSUM: /* Build Checksum */
        {
          CCP_DWORD s;

          /* Initialize Responce */
          ccp.Crm[3] = sizeof(CCP_CHECKSUM_TYPE); /* Checksum Size */
          #ifdef CCP_CHECKSUM_CCITT               /* Checksum */
            *(CCP_DWORD*)&ccp.Crm[4] = 0xFFFFFFFF;
          #else
            *(CCP_DWORD*)&ccp.Crm[4] = 0;
          #endif
          ccp.MTA[CCP_INTERNAL_MTA] = ccp.MTA[0];        /* MTA[0] is not affected */
          #ifdef CCP_MOTOROLA
            s = (*(CCP_WORD*)&com[4]) | ((*(CCP_WORD*)&com[2])<<16);
          #else
            s = (*(CCP_WORD*)&com[2]) | ((*(CCP_WORD*)&com[4])<<16);
          #endif
          #ifdef CCP_TESTMODE
            if (gDebugLevel) CCPPRINT("%u: BUILD_CHKSUM size=%u/n",ctr,s);
          #endif
          #ifndef CCP_CPUTYPE_32BIT
            if (s&0xffff0000) ccp.Crm[1] = CRC_OUT_OF_RANGE; /* Range, max. 64K-1 on <32Bit CPUs */
            ccp.CheckSumSize = (CCP_WORD)s;
          #else
            ccp.CheckSumSize = s;
          #endif
          if (ccp.Crm[1]==0) {
            RST_PORT_BIT(1); /* Timingtest */
            return; /* Checksum calculation will be performed by ccpBackground() */
          }

        }
        break;

      #endif /* CCP_CHECKSUM */

      /* Flash Programming Kernel Download */
      #ifdef CCP_BOOTLOADER_DOWNLOAD

      case CC_PROGRAM_PREPARE: /* Prepare flash kernel download */
        {
          #ifdef CCP_TESTMODE
            if (gDebugLevel) CCPPRINT("%u: PROGRAM_PREPARE/n",ctr);
          #endif
          if (!ccpDisableNormalOperation(ccp.MTA[0],*(CCP_WORD*)&com[2])) {
            ccp.Crm[1] = CRC_ACCESS_DENIED;
          }
        }
        break;

 

 

 5     SPI通信协议

 6     obd诊断分析

7   栈

 

int PopElement ( Stack *this_stack,
                 struct StkElement * destination )
{
    if ( this_stack->top == -1 ) /* stack empty, return error */
        return ( 0 );

    memmove ( destination,
                &(( this_stack->base )[this_stack->top] ),
                sizeof ( struct StkElement ));

    this_stack->top -= 1;

    return ( 1 );
}

/*---------------------------------------------------------------
 *  push an element onto the stack. If stack is not already full,
 *  point StackTop to the next slot, and copy the new element.
 *-------------------------------------------------------------*/
int PushElement ( Stack *this_stack, struct StkElement * to_push )
{
    /* is stack full? */
    if ( this_stack->top == this_stack->max_stack )
        return ( 0 );

    this_stack->top += 1;

    memmove ( &(( this_stack->base )[this_stack->top] ), to_push,
                        sizeof ( struct StkElement ));

    return ( 1 );
}

 

 

 


 

ECU 硬件:

 

  1    电磁干扰

  2    高温

  3    复杂时序

  4    故障诊断

  5    硬件加密

  6    小电阻小电容大作用

 

          :: 待续::                           ********** 嵌入式软件硬件学习之路*********

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值