牛卧堂MCU技术交流

标题: 请问M467控制器不同CANFD的FIFO的RAM区域地址分配! [打印本页]

作者: 匿名    时间: 2024-6-16 20:36
标题: 请问M467控制器不同CANFD的FIFO的RAM区域地址分配!
请问M467控制器不同CANFD的FIFO的RAM区域地址分配!
问题1:如果我要定义4个通道的RAM区域,按照8条的报文数量,请问后面的几个通道应该如何分配?请指点一下,下面这样定义对吗?
CANFD_BUF_T __attribute__((section(".ARM.__at_0x40020200+0x240*0"))) CANFD0_TxBuff[8]; // size=8*(8+64)=0x240Bytes

CANFD_BUF_T __attribute__((section(".ARM.__at_0x40020200+0x240*1"))) CANFD1_TxBuff[8]; // size=8*(8+64)=0x240Bytes
CANFD_BUF_T __attribute__((section(".ARM.__at_0x40020200+0x240*2"))) CANFD2_TxBuff[8]; // size=8*(8+64)=0x240Bytes
CANFD_BUF_T __attribute__((section(".ARM.__at_0x40020200+0x240*3"))) CANFD3_TxBuff[8]; // size=8*(8+64)=0x240Bytes



问题2:如果我定义的是16条报文,是应该这样理解吗?size=16*(8+64)=0x480Bytes

作者: chrishu    时间: 2024-6-18 16:02
本帖最后由 chrishu 于 2024-6-18 16:04 编辑

不明白四个通道的RAM区域是什么意思?
M467的 CANFD 的TX buffer最多可以配置32个成员,也就是可以同时有最多32条等待发送的报文存放在 tx buffer的专用RAM区域。
1、每个报文的格式 =“8字节ID +数据字节”



2、需要在寄存器里定义TX buffer的起始偏移量。


在EC_M460_CANFD_Tx_Simply_V1.00例程里的如下定义:
CANFD_BUF_T __attribute__((section(".ARM.__at_0x40020200"))) CANFD_TxBuff[8]; // size=8*(8+64)=0x240Bytes
1、定义了TX buffer地址在0x40020200,也就是它的基地址偏移量是0
2、定义TX buffer有8个成员,  每个成员的数据长度64字节,也就是每个成员占用的RAM大小是8+64字节

微信截图_20240611112104.png (493.6 KB, 下载次数: 336)

微信截图_20240611112104.png

作者: 匿名    时间: 2024-6-18 17:30
chrishu 发表于 2024-6-18 16:02
不明白四个通道的RAM区域是什么意思?
M467的 CANFD 的TX buffer最多可以配置32个成员,也就是可以同时有最 ...

“不明白四个通道的RAM区域是什么意思?“
我的意思是,如果四个CANFD通道,CAN0,1,2,3 ,同时需要分配RAM区域的情况!
是这个意思。
这个”M467的 CANFD 的TX buffer最多可以配置32个成员“,是指不区分通道0,1,2,3,而是同CANFD外设的情况吗?
作者: Angus    时间: 2024-6-20 14:49
游客 121.29.98.x 发表于 2024-6-18 17:30
“不明白四个通道的RAM区域是什么意思?“
我的意思是,如果四个CANFD通道,CAN0,1,2,3 ,同时需要分配RAM ...

CANFD0123的内RAM区,首址分别是 :
CANFD0:0x40020200,
CANFD1:0x40024200,
CANFD2:0x40028200,
CANFD3:0x4002C200,

如果定义了CANFD0的数组工作正常,再定义其它三个CANFD数组时,只改 HXE 地址的第4位就可以了。
作者: 匿名    时间: 2024-6-20 15:55
Angus 发表于 2024-6-20 14:49
CANFD0123的内RAM区,首址分别是 :
CANFD0:0x40020200,
CANFD1:0x40024200,

只改 HXE 地址的第4位就可以了;
请问一下,这句话怎么理解?
作者: 匿名    时间: 2024-6-20 16:42
CANFD_BUF_T __attribute__((section(".ARM.__at_0x40020200"))) CANFD0_Txfifo[2];
CANFD_BUF_T __attribute__((section(".ARM.__at_0x40024200"))) CANFD1_Txfifo[2];
CANFD_BUF_T __attribute__((section(".ARM.__at_0x40028200"))) CANFD2_Txfifo[2];
CANFD_BUF_T __attribute__((section(".ARM.__at_0x4002C200"))) CANFD3_Txfifo[2];

uint8_t u8Item = 0;

uint32_t u32TimeOutCnt0 = 0;
uint32_t u32TimeOutCnt1 = 0;
uint32_t u32TimeOutCnt2 = 0;
uint32_t u32TimeOutCnt3 = 0;


void TIM1_Init(void)
{
    TIMER_Open(TIMER1, TIMER_PERIODIC_MODE, 100000);//1khz中断一次
    TIMER_EnableInt(TIMER1);
    NVIC_EnableIRQ(TMR1_IRQn);
    TIMER_Start(TIMER1);
}

void TMR1_IRQHandler(void)
{
    if (++u8Item > 1) u8Item = 0;

    TIMER_ClearIntFlag(TIMER1);
}

作者: 匿名    时间: 2024-6-20 16:42
void SYS_Init(void)
{

    /* Set PF multi-function pins for XT1_OUT(PF.2) and XT1_IN(PF.3) */
    SET_XT1_OUT_PF2();
    SET_XT1_IN_PF3();

    /*---------------------------------------------------------------------------------------------------------*/
    /* Init System Clock                                                                                       */
    /*---------------------------------------------------------------------------------------------------------*/

    /* Enable HIRC and HXT clock */
    CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk | CLK_PWRCTL_HXTEN_Msk);

    /* Wait for HIRC and HXT clock ready */
    CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk | CLK_STATUS_HXTSTB_Msk);

    /* Set PCLK0 and PCLK1 to HCLK/2 */
    CLK->PCLKDIV = (CLK_PCLKDIV_APB0DIV_DIV1 | CLK_PCLKDIV_APB1DIV_DIV1);

    /* Set core clock to 200MHz */
    CLK_SetCoreClock(200000000);

    /* Enable all GPIO clock */
    CLK->AHBCLK0 |= CLK_AHBCLK0_GPACKEN_Msk | CLK_AHBCLK0_GPBCKEN_Msk | CLK_AHBCLK0_GPCCKEN_Msk | CLK_AHBCLK0_GPDCKEN_Msk |
                    CLK_AHBCLK0_GPECKEN_Msk | CLK_AHBCLK0_GPFCKEN_Msk | CLK_AHBCLK0_GPGCKEN_Msk | CLK_AHBCLK0_GPHCKEN_Msk;
    CLK->AHBCLK1 |= CLK_AHBCLK1_GPICKEN_Msk | CLK_AHBCLK1_GPJCKEN_Msk;

    CLK_EnableSysTick(CLK_CLKSEL0_STCLKSEL_HCLK_DIV2, 0);


    CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HIRC, CLK_CLKDIV0_UART0(1));
    CLK_EnableModuleClock(UART0_MODULE);

    /* Set IP clock */
    CLK_SetModuleClock(CANFD0_MODULE, CLK_CLKSEL0_CANFD0SEL_HCLK, CLK_CLKDIV5_CANFD0(1));
    CLK_SetModuleClock(CANFD1_MODULE, CLK_CLKSEL0_CANFD1SEL_HCLK, CLK_CLKDIV5_CANFD1(1));
    CLK_SetModuleClock(CANFD2_MODULE, CLK_CLKSEL0_CANFD2SEL_HCLK, CLK_CLKDIV5_CANFD2(1));
    CLK_SetModuleClock(CANFD3_MODULE, CLK_CLKSEL0_CANFD3SEL_HCLK, CLK_CLKDIV5_CANFD3(1));
    /* Enable IP clock */
    CLK_EnableModuleClock(CANFD0_MODULE);
    CLK_EnableModuleClock(CANFD1_MODULE);
    CLK_EnableModuleClock(CANFD2_MODULE);
    CLK_EnableModuleClock(CANFD3_MODULE);

    CLK_SetModuleClock(TMR1_MODULE, CLK_CLKSEL1_TMR1SEL_PCLK0, MODULE_NoMsk);
    CLK_EnableModuleClock(TMR1_MODULE);

    /*--------------------------------------------------------------------------------------------*/
    /* Init I/O Multi-function                                                                    */
    /*--------------------------------------------------------------------------------------------*/

    SET_UART0_RXD_PB12();       // Set multi-function pins for UART0 RXD and TXD
    SET_UART0_TXD_PB13();


    //CAN
    SET_CAN0_TXD_PD11();
    SET_CAN0_RXD_PD10();

    SET_CAN1_TXD_PC13();
    SET_CAN1_RXD_PD12();

    SET_CAN2_TXD_PB9();
    SET_CAN2_RXD_PB8();

    SET_CAN3_TXD_PF11();
    SET_CAN3_RXD_PF10();

}
作者: 匿名    时间: 2024-6-20 16:43
void CANFD0_TX_fifo_Init(void)
{
    CANFD0_Txfifo[0].u32Id       = 0x001 << 18 ;                    // SID = 0x111
    CANFD0_Txfifo[0].u32Config   = 0x00300000 + 0x000F0000 ;        // DLC=8 mean 8 Bytes

    CANFD0_Txfifo[1].u32Id       = 0x002 << 18 ;                    // SID = 0x113
    CANFD0_Txfifo[1].u32Config   = 0x00300000 + 0x000F0000 ;        // DLC=9 =12 Bytes

    CANFD0_Txfifo[0].au32Data[0] = 0x11111111;
    CANFD0_Txfifo[1].au32Data[0] = 0x22222222;
}

void CANFD1_TX_fifo_Init(void)
{
    CANFD1_Txfifo[0].u32Id       = 0x011 << 18 ;                    // SID = 0x111
    CANFD1_Txfifo[0].u32Config   = 0x00300000 + 0x000F0000 ;        // DLC=8 mean 8 Bytes

    CANFD1_Txfifo[1].u32Id       = 0x012 << 18 ;                    // SID = 0x113
    CANFD1_Txfifo[1].u32Config   = 0x00300000 + 0x000F0000 ;        // DLC=9 =12 Bytes

    CANFD1_Txfifo[0].au32Data[0] = 0x11111111;
    CANFD1_Txfifo[1].au32Data[0] = 0x22222222;
}

void CANFD2_TX_fifo_Init(void)
{
    CANFD2_Txfifo[0].u32Id       = 0x021 << 18 ;                    // SID = 0x111
    CANFD2_Txfifo[0].u32Config   = 0x00300000 + 0x000F0000 ;        // DLC=8 mean 8 Bytes

    CANFD2_Txfifo[1].u32Id       = 0x022 << 18 ;                    // SID = 0x113
    CANFD2_Txfifo[1].u32Config   = 0x00300000 + 0x000F0000 ;        // DLC=9 =12 Bytes

    CANFD2_Txfifo[0].au32Data[0] = 0x11111111;
    CANFD2_Txfifo[1].au32Data[0] = 0x22222222;
}

void CANFD3_TX_fifo_Init(void)
{
    CANFD3_Txfifo[0].u32Id       = 0x031 << 18 ;                    // SID = 0x111
    CANFD3_Txfifo[0].u32Config   = 0x00300000 + 0x000F0000 ;        // DLC=8 mean 8 Bytes

    CANFD3_Txfifo[1].u32Id       = 0x032 << 18 ;                    // SID = 0x113
    CANFD3_Txfifo[1].u32Config   = 0x00300000 + 0x000F0000 ;        // DLC=9 =12 Bytes

    CANFD3_Txfifo[0].au32Data[0] = 0x11111111;
    CANFD3_Txfifo[1].au32Data[0] = 0x22222222;
}

void CANFD0_Tx_Init(CANFD_T *psCanfd, int16_t TxBuff_Quantity, int16_t DLC_Max, uint16_t TxBuff_StartAddr)
{
    psCanfd->TXBC = (TxBuff_Quantity << CANFD_TXBC_NDTB_Pos)
                    + TxBuff_StartAddr ;

    psCanfd->TXESC = DLC_Max <<  CANFD_TXESC_TBDS_Pos;
}
void CANFD1_Tx_Init(CANFD_T *psCanfd, int16_t TxBuff_Quantity, int16_t DLC_Max, uint16_t TxBuff_StartAddr)
{
    psCanfd->TXBC = (TxBuff_Quantity << CANFD_TXBC_NDTB_Pos)
                    + TxBuff_StartAddr ;

    psCanfd->TXESC = DLC_Max <<  CANFD_TXESC_TBDS_Pos;
}
void CANFD2_Tx_Init(CANFD_T *psCanfd, int16_t TxBuff_Quantity, int16_t DLC_Max, uint16_t TxBuff_StartAddr)
{
    psCanfd->TXBC = (TxBuff_Quantity << CANFD_TXBC_NDTB_Pos)
                    + TxBuff_StartAddr ;

    psCanfd->TXESC = DLC_Max <<  CANFD_TXESC_TBDS_Pos;
}
void CANFD3_Tx_Init(CANFD_T *psCanfd, int16_t TxBuff_Quantity, int16_t DLC_Max, uint16_t TxBuff_StartAddr)
{
    psCanfd->TXBC = (TxBuff_Quantity << CANFD_TXBC_NDTB_Pos)
                    + TxBuff_StartAddr ;

    psCanfd->TXESC = DLC_Max <<  CANFD_TXESC_TBDS_Pos;
}
作者: 匿名    时间: 2024-6-20 16:43
void CANFD0_TxTest(CANFD_T *psCanfd, uint8_t cnt)
{
    switch (cnt)
    {
        case 0:
            while (CANFD_GET_COMMUNICATION_STATE(psCanfd) != eCANFD_IDLE)
            {
                if (--u32TimeOutCnt0 == 0) break;
            }
            psCanfd->TXBAR = 1 << 0 ;
            break;

        case 1:
            while (CANFD_GET_COMMUNICATION_STATE(psCanfd) != eCANFD_IDLE)
            {
                if (--u32TimeOutCnt0 == 0) break;
            }
            psCanfd->TXBAR = 1 << 1 ;
            break;

        default:
            break ;
    }
}

void CANFD1_TxTest(CANFD_T *psCanfd, uint8_t cnt)
{
    switch (cnt)
    {
        case 0:
            while (CANFD_GET_COMMUNICATION_STATE(psCanfd) != eCANFD_IDLE)
            {
                if (--u32TimeOutCnt1 == 0) break;
            }
            psCanfd->TXBAR = 1 << 0 ;
            break;

        case 1:
            while (CANFD_GET_COMMUNICATION_STATE(psCanfd) != eCANFD_IDLE)
            {
                if (--u32TimeOutCnt1 == 0) break;
            }
            psCanfd->TXBAR = 1 << 1 ;
            break;

        default:
            break ;
    }
}

void CANFD2_TxTest(CANFD_T *psCanfd, uint8_t cnt)
{
    switch (cnt)
    {
        case 0:
            while (CANFD_GET_COMMUNICATION_STATE(psCanfd) != eCANFD_IDLE)
            {
                if (--u32TimeOutCnt2 == 0) break;
            }
            psCanfd->TXBAR = 1 << 0 ;
            break;

        case 1:
            while (CANFD_GET_COMMUNICATION_STATE(psCanfd) != eCANFD_IDLE)
            {
                if (--u32TimeOutCnt2 == 0) break;
            }
            psCanfd->TXBAR = 1 << 1 ;
            break;

        default:
            break ;
    }
}

void CANFD3_TxTest(CANFD_T *psCanfd, uint8_t cnt)
{
    switch (cnt)
    {
        case 0:
            while (CANFD_GET_COMMUNICATION_STATE(psCanfd) != eCANFD_IDLE)
            {
                if (--u32TimeOutCnt3 == 0) break;
            }
            psCanfd->TXBAR = 1 << 0 ;
            break;

        case 1:
            while (CANFD_GET_COMMUNICATION_STATE(psCanfd) != eCANFD_IDLE)
            {
                if (--u32TimeOutCnt3 == 0) break;
            }
            psCanfd->TXBAR = 1 << 1 ;
            break;

        default:
            break ;
    }
}

void CANFD0_Init(void)
{
    CANFD_FD_T sCANFD_Config0;
    SYS_ResetModule(CANFD0_RST);
    CANFD_GetDefaultConfig(&sCANFD_Config0, CANFD_OP_CAN_FD_MODE);
    sCANFD_Config0.sBtConfig.sNormBitRate.u32BitRate = 500000;
    sCANFD_Config0.sBtConfig.sDataBitRate.u32BitRate = 2000000;
    CANFD_Open(CANFD0, &sCANFD_Config0);
}

void CANFD1_Init(void)
{
    CANFD_FD_T sCANFD_Config1;
    SYS_ResetModule(CANFD1_RST);
    CANFD_GetDefaultConfig(&sCANFD_Config1, CANFD_OP_CAN_FD_MODE);
    sCANFD_Config1.sBtConfig.sNormBitRate.u32BitRate = 500000;
    sCANFD_Config1.sBtConfig.sDataBitRate.u32BitRate = 2000000;
    CANFD_Open(CANFD1, &sCANFD_Config1);
}

void CANFD2_Init(void)
{
    CANFD_FD_T sCANFD_Config2;
    SYS_ResetModule(CANFD2_RST);
    CANFD_GetDefaultConfig(&sCANFD_Config2, CANFD_OP_CAN_FD_MODE);
    sCANFD_Config2.sBtConfig.sNormBitRate.u32BitRate = 500000;
    sCANFD_Config2.sBtConfig.sDataBitRate.u32BitRate = 2000000;
    CANFD_Open(CANFD2, &sCANFD_Config2);
}

void CANFD3_Init(void)
{
    CANFD_FD_T sCANFD_Config3;
    SYS_ResetModule(CANFD3_RST);
    CANFD_GetDefaultConfig(&sCANFD_Config3, CANFD_OP_CAN_FD_MODE);
    sCANFD_Config3.sBtConfig.sNormBitRate.u32BitRate = 500000;
    sCANFD_Config3.sBtConfig.sDataBitRate.u32BitRate = 2000000;
    CANFD_Open(CANFD3, &sCANFD_Config3);
}


int32_t main(void)
{

    SYS_UnlockReg();                         // Unlock protected registers
    SYS_Init();                              // Init System, peripheral clock and multi-function I/O

    UART_Open(UART0, 115200);                           // Init UART to 115200-8n1 for print message

    SYS_ResetModule(CANFD0_RST);
    CANFD0->CCCR = CANFD_CCCR_CCE_Msk | CANFD_CCCR_INIT_Msk | CANFD_CCCR_BRSE_Msk | CANFD_CCCR_FDOE_Msk;

    SYS_ResetModule(CANFD1_RST);
    CANFD1->CCCR = CANFD_CCCR_CCE_Msk | CANFD_CCCR_INIT_Msk | CANFD_CCCR_BRSE_Msk | CANFD_CCCR_FDOE_Msk;

    SYS_ResetModule(CANFD2_RST);
    CANFD2->CCCR = CANFD_CCCR_CCE_Msk | CANFD_CCCR_INIT_Msk | CANFD_CCCR_BRSE_Msk | CANFD_CCCR_FDOE_Msk;

    SYS_ResetModule(CANFD3_RST);
    CANFD3->CCCR = CANFD_CCCR_CCE_Msk | CANFD_CCCR_INIT_Msk | CANFD_CCCR_BRSE_Msk | CANFD_CCCR_FDOE_Msk;

    CANFD0_Init();
    CANFD1_Init();
    CANFD2_Init();
    CANFD3_Init();

    CANFD0_TX_fifo_Init();
    CANFD1_TX_fifo_Init();
    CANFD2_TX_fifo_Init();
    CANFD3_TX_fifo_Init();
       

    CANFD0_Tx_Init(CANFD0, 2, 7, 0);
    CANFD0->CCCR = CANFD_CCCR_BRSE_Msk | CANFD_CCCR_FDOE_Msk ;    // Write is OK after 2 CLKs
       
    CANFD1_Tx_Init(CANFD1, 2, 7, 0);
    CANFD1->CCCR = CANFD_CCCR_BRSE_Msk | CANFD_CCCR_FDOE_Msk ;    // Write is OK after 2 CLKs

    CANFD2_Tx_Init(CANFD2, 2, 7, 0);
    CANFD2->CCCR = CANFD_CCCR_BRSE_Msk | CANFD_CCCR_FDOE_Msk ;    // Write is OK after 2 CLKs

    CANFD3_Tx_Init(CANFD3, 2, 7, 0);
    CANFD3->CCCR = CANFD_CCCR_BRSE_Msk | CANFD_CCCR_FDOE_Msk ;    // Write is OK after 2 CLKs

    SYS_LockReg();

    TIM1_Init();

    u32TimeOutCnt0 = CANFD_TIMEOUT;
    u32TimeOutCnt1 = CANFD_TIMEOUT;
    u32TimeOutCnt2 = CANFD_TIMEOUT;
    u32TimeOutCnt3 = CANFD_TIMEOUT;


    while (1)
    {
        CANFD0_TxTest(CANFD0, u8Item);
        CANFD1_TxTest(CANFD1,u8Item);
        CANFD2_TxTest(CANFD2,u8Item);
        CANFD3_TxTest(CANFD3,u8Item);
    }

}

作者: 匿名    时间: 2024-6-20 16:43
贴上源码,不知道哪里的问题。先这样吧。。。如果不行的话,就不搞了。。。
作者: Angus    时间: 2024-6-20 17:45
CANFD 用自己的 RAM 区存放收发数据,这个RAM 不在地址 0x20000000 开始的、通用 RAM 区。有6144个字节,只能按字读写,是1536个字。

CANFD0 的专用 RAM 区,首地址是 0x40020200,  往后 1536个字。
CANFD1 的专用 RAM 区,首地址是 0x40024200(加了0x4000),  往后 1536个字。
CNAFD2 的专用 RAM 区,首地址是 0x40028200,  往后 1536个字。
CNAFD3 的专用 RAM 区,首地址是 0x4002C200,  往后 1536个字。

如果你配置 CNAFD0 工作正常了,可以按相同结构配置 CANFD1。CANFD0的配置里,出现专用RAM 地址的地方,只要加 0x4000,就成了 CANFD1的相应配置。

让四个CANFD 同时工作的代码示例: EC_M460_uCOSii_4CANFD_TxRx_V1.00.zip (4.02 MB, 下载次数: 288)
作者: 匿名    时间: 2024-6-20 20:20
感谢指点~




欢迎光临 牛卧堂MCU技术交流 (http://nuvoton-mcu.com/) Powered by Discuz! X3.2