本文内容需结合《CAN接收处理Rx handling》内容阅读,旨在结合具体AURIX Rx配置C样例代码进行较为详细的AURIX CAN通信Rx配置。
.rxConfig = { .rxMode = IfxCan_RxMode_dedicatedBuffers, .rxBufferDataFieldSize = IfxCan_DataFieldSize_8, .rxFifo0DataFieldSize = IfxCan_DataFieldSize_8, .rxFifo1DataFieldSize = IfxCan_DataFieldSize_8, .rxFifo0OperatingMode = IfxCan_RxFifoMode_blocking, .rxFifo1OperatingMode = IfxCan_RxFifoMode_blocking, .rxFifo0WatermarkLevel = 0, .rxFifo1WatermarkLevel = 0, .rxFifo0Size = 0, .rxFifo1Size = 0 },在对CAN node进行配置时,需要对CAN的Rx进行初始化和配置,下面结合Infineon iLLD对CAN Rx的配置进行介绍,首先先看Rx配置的结构体:
typedef struct { IfxCan_RxMode rxMode; /**< \brief Rx Buffers or FIFO 0 or combination Mode of reception */ IfxCan_DataFieldSize rxBufferDataFieldSize; /**< \brief Rx Buffer Data Field Size */ IfxCan_DataFieldSize rxFifo0DataFieldSize; /**< \brief Rx FIFO 0 Data Field Size */ IfxCan_DataFieldSize rxFifo1DataFieldSize; /**< \brief Rx FIFO 1 Data Field Size */ IfxCan_RxFifoMode rxFifo0OperatingMode; /**< \brief Rx FIFO 0 operating mode */ IfxCan_RxFifoMode rxFifo1OperatingMode; /**< \brief Rx FIFO 1 operating mode */ uint8 rxFifo0WatermarkLevel; /**< \brief Rx FIFO 0 watermark level */ uint8 rxFifo1WatermarkLevel; /**< \brief Rx FIFO 1 watermark level */ uint8 rxFifo0Size; /**< \brief Rx FIFO 0 Size */ uint8 rxFifo1Size; /**< \brief Rx FIFO 1 Size */ } IfxCan_Can_RxConfig;CPU的MCMCAN Rx配置包括Rx的模式配置、FIFO大小以及操作模式、Buffer大小等。
RxMode:
typedef enum { IfxCan_RxMode_dedicatedBuffers, /**< \brief Rx dedicated buffers operation */ IfxCan_RxMode_fifo0, /**< \brief Rx FIFO 0 operation */ IfxCan_RxMode_fifo1, /**< \brief Rx FIFO 1 operation */ IfxCan_RxMode_sharedFifo0, /**< \brief Rx shared dedicated buffers and Rx FIFO 0 operation */ IfxCan_RxMode_sharedFifo1, /**< \brief Rx shared dedicated buffers and Rx FIFO 1 operation */ IfxCan_RxMode_sharedAll /**< \brief Rx shared dedicated buffers and Rx FIFO 0 and Rx FIFO 1 operation */ } IfxCan_RxMode;RxMode描述的是Rx接收模式的组合,IfxCan_RxMode_fifo0、IfxCan_RxMode_fifo1、IfxCan_RxMode_dedicatedBuffers这三个枚举值的含义是只用单个模式接收,FIFO0、FIFO1、Buffer,单个模式接收。
IfxCan_RxMode_sharedFifo0指的是buffer和FIFO0 share,即Rx接收到的报文可存储到FIFO0以及Buffer当中;
IfxCan_RxMode_sharedFifo1指的是buffer和FIFO1 share,即Rx接收到的报文可存储到FIFO1以及Buffer当中;
IfxCan_RxMode_sharedAll指的是全部空间都可以接收,包含Buffer以及FIFO0和1。
注意:rxMode配置非芯片寄存器配置,而只用于软件配置逻辑区分,如下:
iLLD配置FIFO和buffer时使用巧妙的取“子集”的方式进行配置,如mode是Buffer或share,那么一定需要配置Buffer,那么buffer就是子集,先把buffer相关的数据长度以及地址配置完成;如果mode是FIFO0或者share,那么FIFO0就是子集,再把FIFO0相关的配置项给配好。
代码通过检查 rxMode配置值,动态选择配置不同的Rx Buffer或Rx FIFO,确保适应不同的 CAN 通信需求。所以,解释了RxMode 本身是一个软件配置项,它不是硬件寄存器中的一个直接属性。
IfxCan_DataFieldSize rxBufferDataFieldSize:
这个字段配置的是RxBuffer内部一个数据元素当中的数据字段的长度,分别有如下几个选项:
typedef enum { IfxCan_DataFieldSize_8, /**< \brief 8 byte data field */ IfxCan_DataFieldSize_12, /**< \brief 12 byte data field */ IfxCan_DataFieldSize_16, /**< \brief 16 byte data field */ IfxCan_DataFieldSize_20, /**< \brief 20 byte data field */ IfxCan_DataFieldSize_24, /**< \brief 24 byte data field */ IfxCan_DataFieldSize_32, /**< \brief 32 byte data field */ IfxCan_DataFieldSize_48, /**< \brief 48 byte data field */ IfxCan_DataFieldSize_64 /**< \brief 64 byte data field */ } IfxCan_DataFieldSize;IFX_INLINE void IfxCan_Node_setRxBufferDataFieldSize(Ifx_CAN_N *node, IfxCan_DataFieldSize size) { node->RX.ESC.B.RBDS = size; }为什么只关心数据字段的长度呢?因为除了数据字段之外,其他字段的长度都是固定的,不需要配置,其字段布置基本符合CAN帧的字段分布,所以一个FIFO/Buffer element的长度大小基本取决于数据段的大小
如上表是RBDS配置值和数据域段的字节数的对应关系,以及和FIFO Element Size的对应关系,可以看到FIFO Element Size的单位是RAM words,一个RAM words是4Byte,所以,其他字段占据的大小,以第一行为例,就为4 * 4Byte - 8Byte = 8Byte,也就是两个RAM words。
对比Buffer/FIFO element的域段定义也可知:
注意:该表第一行为bit域段,手册表格有所压缩
R0 (Rx Buffer / FIFO 元素的第一个字段):
- ANMF (Acceptance Filter Match Flag):表示该消息是否通过了接收过滤器的匹配。通常用来指示消息是否符合设定的过滤条件。
- ESI (Error State Indicator):错误状态指示器,指示消息是否有错误。
- XTD (Extended Identifier):扩展标识符标志位,标识该消息是标准CAN标识符(11 位)还是扩展标识符(29 位)。
- RTR (Remote Transmission Request):远程传输请求标志,表示该消息是否是远程请求帧(Remote Frame)。
- ID[28:0] (Identifier):存储消息的标识符(ID),通常包括标准或扩展帧的标识符。如果是扩展帧,会占用更多的位。
R1 (Rx Buffer / FIFO 元素的第二个字段):
- FIDX[6:0](Filter Index):表示该消息的过滤器索引,指示是哪一个过滤器匹配了这条消息。
- FDF(FD Format):表示该消息是否为CAN FD格式。CAN FD允许更大的数据段传输,最多64字节。
- BRS(Bit Rate Switch):指示该消息是否使用了Bit Rate Switching,即是否在CAN FD帧中使用不同的波特率传输数据部分。
- DLC[3:0](Data Length Code):表示数据字段的长度,以字节为单位。通常,这个字段的值表示数据字段的大小,CAN 2.0的最大数据长度为8字节,而CAN FD的最大数据长度可以达到64字节。
- RXTS[15:0] (Receive Timestamp):接收到的消息的时间戳,表示消息被接收的时间。
R2 (Rx Buffer / FIFO 元素的第三个字段):
- DB3[7:0] 到 DBm-1[7:0]:这些是数据字节字段(Data Bytes),用于存储实际的数据部分。每个DBx存储8位数据(即1字节)。消息的实际数据会被依次存储在这些字段中。
数据字段的排列方式:
- 这个表格将消息的字段按顺序排列,每一行代表Message Element中的一个字节段,包含标识符、控制信息、数据字段等。
由此可得,R0和R1为数据段之外的其他字段,占据64bit,即8个字节,2个RAM Words。
所以,该字段配置要区分是否为CAN FD帧,FD帧最大支持64字节的数据段,如果这里错配成标准帧的8字节,会导致数据丢失。
/* set Rx buffers start address in the Message RAM */ IfxCan_Node_setRxBuffersStartAddress(nodeSfr, config->messageRAM.rxBuffersStartAddress);另外,对于Rx Buffer的设置,除了需要设置数据段大小之外,还需要设置Buffer的起始地址,这部分寄存器属于message ram的配置组中定义
IfxCan_DataFieldSize rxFifo0DataFieldSize:
该字段配置的是FIFO的元素的数据段大小,大体跟RxBuffer是相同的,不予赘述
需要注意的还是,如果实际报文数据段的长度大于我们配置的数据段长度,那么多出来的那一部分就会被丢弃。
IfxCan_RxFifoMode rxFifo0OperatingMode;
uint8 rxFifo0WatermarkLevel;
uint8 rxFifo0Size;
这三个字段来自RXF0Ci寄存器,分别代表FIFO的操作模式、水位线、和FIFO的大小,具体释义如下:
配置代码:
IFX_INLINE void IfxCan_Node_setRxFifo0OperatingMode(Ifx_CAN_N *node, IfxCan_RxFifoMode mode) { node->RX.F0C.B.F0OM = mode; } IFX_INLINE void IfxCan_Node_setRxFifo0Size(Ifx_CAN_N *node, uint8 size) { node->RX.F0C.B.F0S = size; } IFX_INLINE void IfxCan_Node_setRxFifo0WatermarkLevel(Ifx_CAN_N *node, uint8 level) { node->RX.F0C.B.F0WM = level; }mode就是FIFO的block mode和over write mode,各个模式的介绍详见《CAN接收处理Rx handling》。