云途CAN FD不同 region 配置不同payload size
GaoSheng Lv5

云途SDK默认的配置中每一个缓冲区块(RAM Block/region/MBDSRn)都是相同的,没办法独立配置,以云途HA系列的CAN0为例,有4个缓冲区,如果配置成64字节负载的话,总共只有28个邮箱(4*7)。在很多情况下,并不是发送的每个报文都是64字节,这样会造成一些浪费。
本文介绍把不同的region配置成不同的字节负载,以增加邮箱数量
图片1

为什么负载字节数不同,邮箱的数量会有差异?

在云途MCU中,一个block大小为512字节。

  • 8字节负载的邮箱需要占用16字节的空间,所有最大邮箱数量为(512/16 == 32
  • 16字节负载的邮箱需要占用24字节的空间,所有最大邮箱数量为(512/24 == 21
  • 32字节负载的邮箱需要占用40字节的空间,所有最大邮箱数量为(512/40 == 12
  • 64字节负载的邮箱需要占用72字节的空间,所有最大邮箱数量为(512/72 == 7
    图片10
    图片2
    图片3

本文的目的是将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;

    /* The standard payload size is 8 bytes */
    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;

    /* The standard payload size is 8 bytes */
    if (!FLEXCAN_IsFDEnabled(base))
    {
        payloadSize = 8U;
    }
    else
    {
        /* Return payload size based on index to match the hardcoded configuration */
        if (msgBuffIdx < 64)
        {
            /* Region 0 and 1 are 8 bytes */
            payloadSize = 8U;
        }
        else
        {
            /* Region 2 and 3 are 64 bytes */
            payloadSize = 64U;
        }
    }

    return (uint8_t)payloadSize;
}

修改FLEXCAN_SetPayloadSize函数,使region0、region1配置成8字节负载,region2、region3为64字节负载,这里也可以看到原驱动程序中,所有的region都是统一配置成了payloadSize.
其中CAN_FDCTRL_MBDSRn_MASK为block负载配置的寄存器
图片4

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 FD is not enabled, only 8 bytes payload is supported */
    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 FD is not enabled, only 8 bytes payload is supported */
    if (FLEXCAN_IsFDEnabled(base))
    {
        tmp = base->FDCTRL;
        /* Force Region 0 and Region 1 to 8 bytes, Region 2 and Region 3 to 64 bytes */
        /* Modified by boqiang: MBDS0 MBDS1 payload is 8, MBDS2 MBDS3 payload is 64 */
        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;
    }
}

图片5
由于初始化can时最大邮箱填的是64(也必须填64),但经过上面的修改后实际可用的邮箱是78,所有要在FLEXCAN_SetMaxMsgBuffNum函数中手动加14.
图片6

参考前64个邮箱的初始化代码,对后14个邮箱地址做初始化
图片7

FLEXCAN_GetMsgBuffRegion函数的作用是计算出邮箱号对应的地址。在原函数中增加框选的部分使其能适合大小邮箱混合的region。
图片8
为什么要将msgBuffIdx减去50?
标准驱动公式假设所有邮箱大小相同,但我们的配置中前 64 个邮箱小(16字节),后面邮箱大(72字节)。为了让后面的大邮箱算出的地址能正确落在物理 RAM 的位置上,必须对索引进行手动修正
那为什么刚好是50呢?这部分有些绕,还是看AI的解释吧
图片9

本站由 提供部署服务