一,认识 Message RAM
消息 RAM 是 FDCAN 里面非常重要的一个点,这也是和之前的 STM32 bxCAN 最大的不同。
STM32H7 自带了 10K 的消息 RAM,消息 RAM 的配置用来实现以下功能:
- 过滤器
- 接收 FIFO
- 接收 BUFF
- 发送事件 FIFO
- 发送 BUFF
- TTCAN
系统 不会 对 Message RAM 配置进行检查。Message RAM 在 FDCAN1 和 FDCAN2 模块之间共用,,用户在配置的时候需要注意,如果配置错误将会导致发生异常情况。
寄存器 | 功能 | 元素大小 | 描述 |
---|---|---|---|
SIDFC.FLSSA | 最大支持128个元素 | 最多占用 128个 word | 11 bit 标准帧滤波器设置 |
XIDFC.FLESA | 最大支持64个元素 | 最多占用 128 个 word | 29 bit 扩展帧滤波器设置 |
RXF0C.F0SA | 最大支持64个元素 | 最多占用 1152 个 word | RX FIFO0 的设置 |
RXF1C.F1SA | 最大支持64个元素 | 最多占用 1152 个 word | RX FIFO1 的设置 |
RXBC.RBSA | 最大支持64个元素 | 最多占用 1152 个 word | RX BUFF 的设置 |
TXEFC.EFSA | 最大支持32个元素 | 最多占用 64 个 word | TX EVENT FIFO 的设置 |
TXBC.TBSA | 最大支持32个元素 | 最多占用 576 个 word | TX BUFF 的设置 |
TMC.TMSA | 最大支持64个元素 | 最多占用 128 个 word | TT CAN 的设置 |
二,配置 Message RAM
Message RAM 的大小是 10K Bytes,也就是 2560 个 word。如果都按照最大的配置去计算则会超出 Message RAM 的可配置范围。
128 + 128 + 1152 + 1152 + 1152 + 64 + 576 + 128 = 4480
在未开启 FDCAN2 的情况下,4480 word 已经远远超过了 2560 word 的大小,所以只有对 Message RAM 的大小进行合理的配置才能保证 FDCAN 的正常工作。
uint32_t MessageRAMOffset; /*!< Specifies the message RAM start address.
This parameter must be a number between 0 and 2560 */
uint32_t StdFiltersNbr; /*!< Specifies the number of standard Message ID filters.
This parameter must be a number between 0 and 128 */
uint32_t ExtFiltersNbr; /*!< Specifies the number of extended Message ID filters.
This parameter must be a number between 0 and 64 */
uint32_t RxFifo0ElmtsNbr; /*!< Specifies the number of Rx FIFO0 Elements.
This parameter must be a number between 0 and 64 */
uint32_t RxFifo0ElmtSize; /*!< Specifies the Data Field Size in an Rx FIFO 0 element.
This parameter can be a value of @ref FDCAN_data_field_size */
uint32_t RxFifo1ElmtsNbr; /*!< Specifies the number of Rx FIFO 1 Elements.
This parameter must be a number between 0 and 64 */
uint32_t RxFifo1ElmtSize; /*!< Specifies the Data Field Size in an Rx FIFO 1 element.
This parameter can be a value of @ref FDCAN_data_field_size */
uint32_t RxBuffersNbr; /*!< Specifies the number of Dedicated Rx Buffer elements.
This parameter must be a number between 0 and 64 */
uint32_t RxBufferSize; /*!< Specifies the Data Field Size in an Rx Buffer element.
This parameter can be a value of @ref FDCAN_data_field_size */
uint32_t TxEventsNbr; /*!< Specifies the number of Tx Event FIFO elements.
This parameter must be a number between 0 and 32 */
uint32_t TxBuffersNbr; /*!< Specifies the number of Dedicated Tx Buffers.
This parameter must be a number between 0 and 32 */
uint32_t TxFifoQueueElmtsNbr; /*!< Specifies the number of Tx Buffers used for Tx FIFO/Queue.
This parameter must be a number between 0 and 32 */
uint32_t TxFifoQueueMode; /*!< Tx FIFO/Queue Mode selection.
This parameter can be a value of @ref FDCAN_txFifoQueue_Mode */
uint32_t TxElmtSize; /*!< Specifies the Data Field Size in a Tx Element.
This parameter can be a value of @ref FDCAN_data_field_size */
} FDCAN_InitTypeDef;
在以上的结构体中描述了 Message RAM 的配置。
与 Message RAM 配置表中的对应关系:
Message RAM 配置 | STM32 FDCAN 结构体成员 | 配置举例 | RAM 占用(word) |
---|---|---|---|
SIDFC.FLSSA(11 bit 标准帧滤波器配置) | StdFiltersNbr | 1(设置 1 个标准帧滤波器) | 1 |
XIDFC.FLESA(29 bit 标准帧滤波器配置) | ExtFiltersNbr | 1(设置 1 个扩展帧滤波器 | 2 |
RXF0C.F0SA(RX FIFO0 的设置) | RxFifo0ElmtsNbr * RxFifo0ElmtSize(可设置的大小是 8 ,12,16,20,24,32,48,64) | 10(深度为 10 的 RX FIFO0)* 18(每帧长度是 64 个字节) | 180 |
RXF1C.F1SA(RX FIFO1 的设置) | RxFifo1ElmtsNbr * RxFifo1ElmtSize(可设置的大小是 8 ,12,16,20,24,32,48,64) | 10(深度为 10 的 RX FIFO0)* 18(每帧长度是 64 个字节) | 180 |
RXBC.RBSA(RX BUFF 的设置) | RxBuffersNbr * RxBufferSize(可设置的大小是 8 ,12,16,20,24,32,48,64) | 10( 10 个 专用RX BUFF)* 18(每帧长度是 64 个字节) | 180 |
TXEFC.EFSA(TX EVENT FIFO 的设置) | TxEventsNbr | 1 | 2 |
TXBC.TBSA (TX BUFF 的设置) | TxBuffersNbr * TxElmtSize + TxFifoQueueElmtsNbr * TxElmtSize | 5 * 18(每帧长度是 64 个字节)+ 5 * 18 | 180 |
TMC.TMSA(TT CAN 的设置) | 无 | - | 0 |
STM32H7 的 HAL 库中提供了计算方法:
hfdcan->msgRam.StandardFilterSA = SRAMCAN_BASE + (hfdcan->Init.MessageRAMOffset * 4U);
hfdcan->msgRam.ExtendedFilterSA = hfdcan->msgRam.StandardFilterSA + (hfdcan->Init.StdFiltersNbr * 4U);
hfdcan->msgRam.RxFIFO0SA = hfdcan->msgRam.ExtendedFilterSA + (hfdcan->Init.ExtFiltersNbr * 2U * 4U);
hfdcan->msgRam.RxFIFO1SA = hfdcan->msgRam.RxFIFO0SA + (hfdcan->Init.RxFifo0ElmtsNbr * hfdcan->Init.RxFifo0ElmtSize * 4U);
hfdcan->msgRam.RxBufferSA = hfdcan->msgRam.RxFIFO1SA + (hfdcan->Init.RxFifo1ElmtsNbr * hfdcan->Init.RxFifo1ElmtSize * 4U);
hfdcan->msgRam.TxEventFIFOSA = hfdcan->msgRam.RxBufferSA + (hfdcan->Init.RxBuffersNbr * hfdcan->Init.RxBufferSize * 4U);
hfdcan->msgRam.TxBufferSA = hfdcan->msgRam.TxEventFIFOSA + (hfdcan->Init.TxEventsNbr * 2U * 4U);
hfdcan->msgRam.TxFIFOQSA = hfdcan->msgRam.TxBufferSA + (hfdcan->Init.TxBuffersNbr * hfdcan->Init.TxElmtSize * 4U);
hfdcan->msgRam.EndAddress = hfdcan->msgRam.TxFIFOQSA + (hfdcan->Init.TxFifoQueueElmtsNbr * hfdcan->Init.TxElmtSize * 4U);
上面的计算公式很好理解,就是每个 word 是 4 个字节,SRAMCAN_BASE 是 Message RAM 的起始地址。
MessageRAMOffset 在 FDCAN1 的时候一定要设置为 0 ,在 FDCAN2 的时候需要根据配置来进行计算,ST 这里很贴心的帮忙做了一个 EndAddress
,这样 FDCAN2 的 MessageRAMOffset 可以直接设置为 FDCAN1 的 EndAddress - SRAMCAN_BASE 。
以下的例子展示一个 Message RAM 的配置:
hfdcan->Init.MessageRAMOffset=0; //FDCAN1 信息RAM偏移为 0
hfdcan->Init.StdFiltersNbr=10; //标准信息ID滤波器个数为10
hfdcan->Init.ExtFiltersNbr=10; //扩展信息ID滤波器个数为10
hfdcan->Init.RxFifo0ElmtsNbr=10; //接收FIFO0元素个数
hfdcan->Init.RxFifo0ElmtSize=FDCAN_DATA_BYTES_64; //接收FIFO0 :64字节
hfdcan->Init.RxFifo1ElmtsNbr=0; //接收FIFO1元素个数
hfdcan->Init.RxFifo1ElmtSize=FDCAN_DATA_BYTES_64; //接收FIFO1:64字节
hfdcan->Init.RxBuffersNbr=0; //接收缓冲区个数
hfdcan->Init.RxBufferSize=FDCAN_DATA_BYTES_64; //接收BUFF:64字节
hfdcan->Init.TxEventsNbr=0; //发送事件个数
hfdcan->Init.TxBuffersNbr=0; //发送缓冲区个数
hfdcan->Init.TxFifoQueueElmtsNbr=10; //发送FIFO个数为10
hfdcan->Init.TxFifoQueueMode=FDCAN_TX_FIFO_OPERATION; //发送FIFO模式
hfdcan->Init.TxElmtSize=FDCAN_DATA_BYTES_64; //发送大小:64字节
根据前面的公司计算可以推导 Message RAM 的占用情况:
- MessageRAMOffset = 0
- StdFiltersNbr 占用 10 word
- ExtFiltersNbr 占用 10 * 2 word
- RxFifo0ElmtsNbr * RxFifo0ElmtSize 占用 10 * 18 word
- RxFifo1ElmtsNbr * RxFifo1ElmtSize 占用 0 * 18 word
- RxBuffersNbr * RxBufferSize 占用 0 * 18 word
- TxEventsNbr 占用 0 * 2 word
- TxBuffersNbr 占用 0 * 18 word
- TxFifoQueueElmtsNbr * TxElmtSize 占用 10 * 18 word
共计占用:10 + 20 + 180 + 180 = 390 word = 390 * 4 = 1560 byte = EndAddress = FDCAN2 的 MessageRAMOffset
有兴趣的可以在调试的时候看下手动计算的是否有误。
三,总结
- Message RAM 很灵活,为了保证正确 HAL 库做了很多检查,有兴趣的可以去看一下
- Message RAM 会影响到滤波器,接收模式,发送模式,后续章节将逐一讲解
- 距离第一篇鸽的时间有点久,以后不要再鸽了。