CANOVERSPIARCHITECTUREUPS产品开发部软件课张登2005/6/222/40内容简介系统架构功能架构MGECAN协议SPI性能分析实现架构数据流数据结构遗留问题和思考总结3/40系统架构背景介绍机种:MGEplaymobil15K/30K控制板:SCM3通讯对象:MGE显示板GDEV4/40系统架构GDEVCANHCANLCANLCANHModule1CAN2CAN1DSP2812MCUDJ128SantakcoreMISOMOSICLKSPIDSP2812MCUDJ128GDEVSantakcoreModule25/40系统架构通讯端点:GDEV和同一模块内的COREGDEV和另一模块内的COREGDEV和GDEV不同模块的CORE同一模块内的DSP和MCU6/40系统架构通讯的内容:GDEV获得UPS内部的测量数据GDEV发送命令给CORE执行相应动作GDEV执行单机/并机初始化的流程参数的设置7/40功能架构MCU的主要功能转发DSP和GDEV之间的通讯,不对数据做任何的解释EEPROM的数据的传输与DSP交换相关的采样数据8/40功能架构DSP的主要功能分析GDEV的数据,做出相应的回复主动发送数据给GDEV通过CAN2转发GDEV的数据接受CAN2收到的数据并转发给GDEV与MCU交换EEPROM的数据与MCU交换相关的采样数据9/40MGECAN协议传输特性波特率:500Kbit/s帧格式:CAN2.0Bextendedframe最快传输速度:3ms/frame10/40MGECAN协议CANIDfield11/40MGECAN协议CANDatafield:在一帧的8个byte的数据当中,1个byte用来对数据分片进行控制:第一个bit用来表示是否是第一帧数据,后面7个bit用来表示共有几帧数据以及该帧的编号:最长支持7*127=889bytes数据12/40MGECAN协议MGECAN协议分析CAN最快的发送速度是每3ms一帧数据,因此,MCU处理CAN数据帧(转发给DSP)的速度必须快于3ms,否则需要做FIFO处理。在CAN协议中存在两种不同优先级的数据帧,因此每一种优先级必须有独立的FIFO。由于数据的分片,我们需要对分片的数据进行重组。在重组的过程中,由于两种不同的优先级的数据的存在,可以出现同一ID数据的两个分片当中存在高优先级的其他ID的数据。需要对这种情况进行处理需要数据的目的地址进行转发或者处理13/40SPI协议性能分析SPI帧格式SPI物理特性由于MCU的SPI没有硬件的接收Buffer,因此我们采用的底层机制必须在保证系统能够正常工作的基础上提高传输速率,那么我们暂时将波特率定义为100kbits/s,也就是12.5kbytes/s。考虑到其他开销,实际上传送一个byte的时间是100us,就是说,mcu和dsp必须每100us处理一次spi中断。传送一帧CAN数据的最长时间(不考虑转义字节)为100us×(1+1+4+8+1+1)=1.6ms14/40SPI协议性能分析SPI传输机制通讯由MASTER(DSP)发起,采用半双工的通讯,每次发送一帧数据,如果不需要发送数据,那么发送一帧空数据。同样,SLAVE如果没有数据要发送,发送一帧空数据。如果需要发送数据,发送的内容由高层来决定。传输机制如图:Master(DSP)Slave(MCU)1mstimer15/40SPI协议性能分析SPI时间分析时间对比图如下:16/40SPI协议性能分析SPI时间分析从整个传输上来看,基本上达到了半双工通讯的极限,额外的开销仅为master和slave的处理时延,该时延应该是us级的时延,一个传送周期如下图示每发送一帧数据最长的时间是1.6ms,因此交换一次数据的最长时间可能是3.2ms。超过gdev的发送间隔,因此,MCU必须通过FIFO来缓存17/40CAN2传送能力分析CAN2的速度决定了是否需要转发的FIFO对于目前的CAN协议,传送速度是每4ms4个byte,因此,需要转发FIFO来处理需要转发的数据。18/40实现架构FilterHeadDJ128RxFIFOCAN1FragmentationListHighprioTXFIFOUserDataTransmitFIFOLowPrioTXFIFOSPIFrameSPIFrameFormatConvertTXREQTimerMGECANIDMGECANfragmentationdataMGECANdataSPIoverheadSANTAKCANIDDSP2812HighprioTXFIFOLowPrioTXFIFOTXREQFilterDJ128SPIFrameCAN2CAN1parsingFragReqFragReqSpidriverSpidriverFormatConvertSpidriverFormatConvertSpidriverSpidriverSpidriver19/40数据流同一模组的GDEV到DSP的数据传输同一模组的GDEV到DSP的数据传输选取有两个分片的数据,数据长度为10,数据为0,1,2,3,4,5,6,7,8,9,那么这些数据需要用两个CAN帧来发送,两个CAN帧的数据分别是:CANFRAME1:CANID0x82,0,1,2,3,4,5,6CANFRAME2CANID0x02,7,8,9如下图示20/40数据流同一模组的GDEV到DSP的数据传输112211Head22Head1HeadnullUserdatanullHeadCAN1MCURXFIFOSPIRxListRxDatastep1step2step3step410x82,0,1,2,3,4,5,620x02,7,8,90,1,2,3,45,6,7,8,9UserdataCANIDSPIoverhead21/40数据流同一模组的GDEV到DSP的数据传输Step1:MCU接收到第一帧数据,并将其存入接收FIFOStep2MCU将第一帧数据封装在SPI的数据区,发送给DSP,DSP将其存入接收链表。第二帧数据可能在此之前也可能在此之后被存入MCU的FIFObuffer.Step3:MCU将第二帧数据通过SPI发送给DSP,DSP将其加入到接收链表Step4:DSP搜索整个接收链表,发现有完整的数据收到,去掉分片的开销,将数据copy到输出buffer,交给AP层进行解析。22/40数据流同一模组的DSP发送数据给GDEV同一模组的DSP发送数据给GDEV当DSP需要发送数据给GDEV的时候,执行如下的动作::我们仍然以以上数据为例,step2step3step410x82,0,1,2,3,4,5,620x02,7,8,90,1,2,3,45,6,7,8,9Userdata1CANIDSPIoverhead1Userdata11112Userdata2222...step1Formatconverter12FormatconverterAPPDataTxFIFORequestSPIMCUCAN123/40数据流同一模组的DSP发送数据给GDEVStep1:用户有数据需要发送,申请数据节点,将用户请求压入发送队列,可以根据数据类型决定压入高优先级还是低优先级队列Step2:取出当前需要发送的用户请求,高优先级的队列优先,这时如果还有其他用户数据需要发送,在队列中排队。发送当前用户请求的第一帧数据。Step3:发送当前用户请求的第二帧数据,发送完毕后,释放用户数据节点。Step4:继续取出发送队列中的内容,继续发送数据24/40数据流不同GDEV间的通讯不同GDEV间的通讯当AP收到的数据经过filter动作后发现是需要转发的给其他模组的gdev的数据时,需要将所有的数据进行转发,由于内部CAN协议(CAN2)和CAN1的格式不同,因此MGECAN数据帧的ID也必须在CAN2的数据当中传输假设需要转发的数据ID=0xCC502,数据部分有4个byte,分别为0,1,2,3。共长8byte,如下图:25/40数据流不同GDEV间的通讯step2step3step40,1,2,3,4,5,6,7Userdata1CANID0xCC502SANTAKCANIDUserdata1Userdata22...step1APPDataTransmitFIFORequestCAN2112112112Userdata1SANTAKFragmentation1=4byteID+0,11SANTAKFragmentation2=2,3,4,5,6,72RxbufferTXFIFOModule1Module2226/40数据流不同GDEV间的通讯Step1:将需要转发的数据压入转发队列Step2:取出需要转发的数据,把id和数据都当成CAN2的净荷进行发送,CAN2每帧中有4个Byte可以用于传送数据,因此需要两帧进行传送,发送第一帧数据Step3:发送第二帧数据,接收的DSP收齐两帧数据后,将数据压入发送队列Step4:发送后续数据27/40数据结构memory管理为节省memory使用,必须使用动态的内存分配,以满足不同请求的需要。在以下场合需要分配ram插入一个发送请求插入一个转发请求插入一个接收数据帧为提高AP程序的效率和透明性,使用了一种固定大小的动态内存分配方案:每个节点均有一个长度标示和一个数据域用来存储用户的数据,同时利用一个next指针组成单向链表LengthData*pNextLengthData*pNextLengthData*pNextpFreeList28/40数据结构memory管理每次需要分配一个节点的时候,取出pFreeList指向的数据节点即可,同时将pFreeList指向下一个节点当使用完这个节点时,将其插入链表的最前端即可。对应不同的数据请求,有不同的数据长度,为节省ram的使用,使用三种不同长度的数据节点分别构成三个不同的链表来进行处理。三种典型的长度分别是8,16和120分别对应1个分片,2个分片和15个分片的CAN数据。根据AP的需求,三种长度数据的节点个数分别是30,20,2。对于高层来讲,只看到两个操作,get操作和free操作,会根据需要分配单元的大小自动寻找合适大小的节点。void*spGetSpiMem(INT16Ulength);voidsFreeSpiMem(void*pnode);29/40数据结构数据请求在需要发送或者需要转发或者需要接收的时候,需要对数据进行队列处理。队列的内容需要保存CAN的所有数据。存储CAN帧的数据结构如下:IDFieldbPrio1bitbDataSort1bitbPDU1bitwID12bitSrcequipment4bitSrcboard3bitDesequipment4bitDesboard3bitReserved2bitMSBLSBHighwordLowword30/40数据结构数据请求CANrequest一个CAN的数据请求包括一个CANID和一个指向数据节点的指针。通过对REQUEST的队列处理。可以实现CAN数据的缓存,如下图示:*pDataRequestunCanIdLengthData[]*pNextCanRequest31/40数据结构MCUFIFO由于MCU侧的接收队列仅对一帧CAN数据进行缓存,而不是重组后的数据,因此MCU的接收队列不需要动态的分配节点的大小,而是使用固定的长度为8的队列。其控制逻辑如下图:D使用ADD和GET操作插入和取出一个CAN帧*pOut*pIn*pStart*pEndwLengthwSizeCanIDCanData[8]......CanIDCanIDCanIDCanData[8]CanData[8]CanData[8]32