云途SDK默认的配置中每一个缓冲区块(RAM Block/region/MBDSRn)都是相同的,没办法独立配置,以云途HA系列的CAN0为例,有4个缓冲区,如果配置成64字节负载的话,总共只有28个邮箱(4*7)。在很多情况下,并不是发送的每个报文都是64字节,这样会造成一些浪费。 本文介绍把不同的region配置成不同的字节负载 ,以增加邮箱数量
为什么负载字节数不同,邮箱的数量会有差异? 在云途MCU中,一个block大小为512字节。
8字节负载的邮箱需要占用16字节的空间,所有最大邮箱数量为(512/16 == 32 )
16字节负载的邮箱需要占用24字节的空间,所有最大邮箱数量为(512/24 == 21 )
32字节负载的邮箱需要占用40字节的空间,所有最大邮箱数量为(512/40 == 12 )
64字节负载的邮箱需要占用72字节的空间,所有最大邮箱数量为(512/72 == 7 )
本文的目的是将region0、region1配置成8字节负载(64个邮箱),region2、region3配置成64字节负载(14个邮箱)。总共78个邮箱 需要对flexcan_hw_access.c做如下修改(除非你真的知道自己做什么,别轻易去修改驱动文件): 将FLEXCAN_GetPayloadSize函数增加一个msgBuffIdx,当idx小于64时,返回payloadSize为8字节,大于时返回payloadSize为64字节。不过这里的处理有点粗糙了,最好还是根据CAN_FDCTRL_MBDSRn_MASK来获取负载字节数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 uint8_t FLEXCAN_GetPayloadSize (const CAN_Type * base) { uint32_t payloadSize; if (!FLEXCAN_IsFDEnabled(base)) { payloadSize = 8U ; } else { payloadSize = 1UL << (((base->FDCTRL & CAN_FDCTRL_MBDSR0_MASK) >> CAN_FDCTRL_MBDSR0_SHIFT) + 3U ); } return (uint8_t )payloadSize; }
将上面函数修改成如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 uint8_t FLEXCAN_GetPayloadSize (const CAN_Type * base, uint32_t msgBuffIdx) { uint32_t payloadSize; if (!FLEXCAN_IsFDEnabled(base)) { payloadSize = 8U ; } else { if (msgBuffIdx < 64 ) { payloadSize = 8U ; } else { payloadSize = 64U ; } } return (uint8_t )payloadSize; }
修改FLEXCAN_SetPayloadSize函数,使region0、region1配置成8字节负载,region2、region3为64字节负载,这里也可以看到原驱动程序中,所有的region都是统一配置成了payloadSize. 其中CAN_FDCTRL_MBDSRn_MASK为block负载配置的寄存器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 void FLEXCAN_SetPayloadSize ( CAN_Type * base, flexcan_fd_payload_size_t payloadSize) { uint32_t tmp; DEV_ASSERT(FLEXCAN_IsFDEnabled(base) || (payloadSize == FLEXCAN_PAYLOAD_SIZE_8)); if (FLEXCAN_IsFDEnabled(base)) { tmp = base->FDCTRL; tmp &= ~(CAN_FDCTRL_MBDSR0_MASK); tmp |= ((uint32_t )payloadSize) << CAN_FDCTRL_MBDSR0_SHIFT; #if FEATURE_CAN_HAS_MBDSR1 tmp &= ~(CAN_FDCTRL_MBDSR1_MASK); tmp |= ((uint32_t )payloadSize) << CAN_FDCTRL_MBDSR1_SHIFT; #endif #if FEATURE_CAN_HAS_MBDSR2 tmp &= ~(CAN_FDCTRL_MBDSR2_MASK); tmp |= ((uint32_t )payloadSize) << CAN_FDCTRL_MBDSR2_SHIFT; #endif #if defined (FEATURE_CAN_HAS_MBDSR3)&&(FEATURE_CAN_HAS_MBDSR3 == 1) tmp &= ~(CAN_FDCTRL_MBDSR3_MASK); tmp |= ((uint32_t )payloadSize) << CAN_FDCTRL_MBDSR3_SHIFT; #endif base->FDCTRL = tmp; } }
将上面函数修改成如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 void FLEXCAN_SetPayloadSize ( CAN_Type * base, flexcan_fd_payload_size_t payloadSize) { uint32_t tmp; DEV_ASSERT(FLEXCAN_IsFDEnabled(base) || (payloadSize == FLEXCAN_PAYLOAD_SIZE_8)); if (FLEXCAN_IsFDEnabled(base)) { tmp = base->FDCTRL; tmp &= ~(CAN_FDCTRL_MBDSR0_MASK); tmp |= ((uint32_t )FLEXCAN_PAYLOAD_SIZE_8) << CAN_FDCTRL_MBDSR0_SHIFT; #if FEATURE_CAN_HAS_MBDSR1 tmp &= ~(CAN_FDCTRL_MBDSR1_MASK); tmp |= ((uint32_t )FLEXCAN_PAYLOAD_SIZE_8) << CAN_FDCTRL_MBDSR1_SHIFT; #endif #if FEATURE_CAN_HAS_MBDSR2 tmp &= ~(CAN_FDCTRL_MBDSR2_MASK); tmp |= ((uint32_t )FLEXCAN_PAYLOAD_SIZE_64) << CAN_FDCTRL_MBDSR2_SHIFT; #endif #if defined (FEATURE_CAN_HAS_MBDSR3)&&(FEATURE_CAN_HAS_MBDSR3 == 1) tmp &= ~(CAN_FDCTRL_MBDSR3_MASK); tmp |= ((uint32_t )FLEXCAN_PAYLOAD_SIZE_64) << CAN_FDCTRL_MBDSR3_SHIFT; #endif base->FDCTRL = tmp; } }
由于初始化can时最大邮箱填的是64(也必须填64),但经过上面的修改后实际可用的邮箱是78,所有要在FLEXCAN_SetMaxMsgBuffNum函数中手动加14.
参考前64个邮箱的初始化代码,对后14个邮箱地址做初始化
FLEXCAN_GetMsgBuffRegion函数的作用是计算出邮箱号对应的地址 。在原函数中增加框选的部分使其能适合大小邮箱混合的region。 为什么要将msgBuffIdx减去50? 标准驱动公式假设所有邮箱大小相同,但我们的配置中前 64 个邮箱小(16字节),后面邮箱大(72字节)。为了让后面的大邮箱算出的地址能正确落在物理 RAM 的位置上,必须对索引进行手动修正 那为什么刚好是50呢?这部分有些绕,还是看AI的解释吧