This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DMA 多通道发送CAN 数据

Expert 1222 points

Ken,

如下是DAM CAN1 IF1发送数据, 请帮我查看寄存器配置是否出现问题?关于IFUEy寄存器 DATASHEET 好像没有说明?

/* USER CODE BEGIN (0) */
#include "rti.h"
#include "can.h"
#include "sys_dma.h"
/* USER CODE END */

/* Include Files */

#include "sys_common.h"

/* USER CODE BEGIN (1) */
#define D_SIZE      8

uint8 TX_DATA1[D_SIZE]={0x30,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8};     /* transmit buffer in sys ram */
uint8 TX_DATA2[D_SIZE]={0x30,0x03,14,15,16,17,18};                    /* transmit buffer in sys ram */
uint8 TX_DATA3[D_SIZE]={21,22,23,24,25,26,27,28};                     /* transmit buffer in sys ram */
uint8 RX_DATA1[D_SIZE]= {0};                                          /* receive  buffer in sys ram */
uint8 RX_DATA2[D_SIZE]= {0};                                          /* receive  buffer in sys ram */
uint8 RX_DATA3[D_SIZE]= {0};

/* USER CODE END */

/** @fn void main(void)
*   @brief Application main function
*   @note This function is empty by default.
*
*   This function is called after startup.
*   The user can use this function to implement the application.
*/

/* USER CODE BEGIN (2) */
uint32 DMAFlag=0x00;
uint32 DMA_Comp_Flag;
uint32 timer0 = 0;
uint32 CpuCount = 0;
uint8  senderFlag = 0;
g_dmaCTRL g_dmaCTRLPKT;    /* dma control packet configuration stack */


void dmaConfigCtrlRxPacket(uint32 sadd,uint32 dadd,uint32 dsize);
/* USER CODE END */

void main(void)
{
/* USER CODE BEGIN (3) */
    rtiInit();
    rtiStartCounter(rtiCOUNTER_BLOCK0);
    rtiDisableNotification(rtiNOTIFICATION_COMPARE0);
    canInit();
    _enable_IRQ();
  
    canREG1->CTL |= (uint32)(1<<18);           // enable DMA for IF2
    dmaReqAssign(DMA_CH1, 8);                  // DMA Configuration and Enable DMA
    dmaConfigCtrlRxPacket((uint32)(&TX_DATA1), (uint32)(&(canREG1->IF1DATx[0])), 1);
    dmaSetCtrlPacket(DMA_CH1, g_dmaCTRLPKT);   // setting dma control packets for transmit
    dmaSetChEnable(DMA_CH1, DMA_HW);
    dmaEnableInterrupt(DMA_CH1, FTC);                     // Enable Interrupt after reception of data


    while(1)
    {
          CpuCount = canIsTxMessagePending(canREG1, canMESSAGE_BOX1);
    }

/* USER CODE END */
}

/* USER CODE BEGIN (4) */
#pragma WEAK(rtiNotification)
void rtiNotification(uint32 notification)
{
/*  enter user code between the USER CODE BEGIN and USER CODE END. */
/* USER CODE BEGIN (9) */
/* Reset the Flag */
    timer0 ++;
}

void dmaConfigCtrlRxPacket(uint32 sadd,uint32 dadd,uint32 dsize)
{
    g_dmaCTRLPKT.SADD      = sadd;              /* source address             */
    g_dmaCTRLPKT.DADD      = dadd;              /* destination  address       */
    g_dmaCTRLPKT.CHCTRL    = 0;                 /* channel control            */
    g_dmaCTRLPKT.FRCNT     = 1;                 /* frame count                */
    g_dmaCTRLPKT.ELCNT     = dsize;             /* element count              */
    g_dmaCTRLPKT.ELDOFFSET = 0;                 /* element destination offset */
    g_dmaCTRLPKT.ELSOFFSET = 0;                 /* element source offset      */
    g_dmaCTRLPKT.FRDOFFSET = 0;                 /* frame destination offset   */
    g_dmaCTRLPKT.FRSOFFSET = 0;                 /* frame source offset        */
    g_dmaCTRLPKT.PORTASGN  = 4;                 /* port b                     */
    g_dmaCTRLPKT.RDSIZE    = ACCESS_64_BIT;     /* read size                  */
    g_dmaCTRLPKT.WRSIZE    = ACCESS_64_BIT;     /* write size                 */
    g_dmaCTRLPKT.TTYPE     = FRAME_TRANSFER ;   /* transfer type              */
    g_dmaCTRLPKT.ADDMODERD = ADDR_FIXED;        /* address mode read          */
    g_dmaCTRLPKT.ADDMODEWR = ADDR_FIXED;        /* address mode write         */
    g_dmaCTRLPKT.AUTOINIT  = AUTOINIT_ON;      /* autoinit                   */
}
/* USER CODE END */

  • sam,

        canREG1->CTL |= (uint32)(1<<18);           // enable DMA for IF2
        dmaReqAssign(DMA_CH1, 8);                  // DMA Configuration and Enable DMA
        dmaConfigCtrlRxPacket((uint32)(&TX_DATA1), (uint32)(&(canREG1->IF1DATx[0])), 1);

     这几句话好像有点问题,你第一句设置的是enable IF2的DMA,后弦设置的硬件触发是request line是DCAN1 IF1。 是不是改下试试看。

    谢谢

  • Ken,

    不好意思,canREG1->CTL |= (uint32)(1<<18); 就使能DMA IF1, 注释出现的笔误;

    dmaReqAssign(DMA_CH1, 8);    // can1 的IF1 对应的request line 是8,

    测试后不成功。。

  • sam,

       我想了一下,我们用DMA去触发CAN总线的传输,这个其实不是太好操作。具体原因是:

    1. 我们操作的DMA触发CAN的终端地址是IF1DATA[0],没有设置其他一些参数,包括你需要选择哪个messagebox。这个是个很重要的参数,因为你不设置对的messagebox,就不能通过相应的CANID把数据发出去,同时接收端也不一定能接到你的数据。

    2.但我们用DMA去触发DMA的接收,这个操作确实可行的,因为它已经经过了CAN报文的解析,到达IF3里面的只是纯的数据了,这样就不会出错。

    所以说用DMA去触发CAN总线的操作,不是太有效。当然也不是说完全不可以,有一个解决办法就是,你手动的设置数据发出的messagebox number。我刚试了一下,这个办法能行,但是效率太低。

       具体的设置如下:

                           canREG2->IF1NO = canMESSAGE_BOX1;

    所以还是建议你考虑一下,是不是不用DMA去触发CAN的数据发送,想想其他的办法解决一下。

    有什么想法,我们再交流。

    谢谢

  • Ken,

    如果DMA发送数据部占优势的话, 那先就不考虑DMA发送数据了..

    目前还有个问题关于DMA channel:

    如果用DCAN1 DMA 接收数据 需要设置成dmaReqAssign(DMA_CH0, 4); 因为CAN1对应 request line 是 4 ..

    如果用DCAN2 DMA 接收数据 需要设置成dmaReqAssign(DMA_CH1, 16); 因为CAN1对应 request line 是 16 ..

    再这里我想问DMA_CH0这个通道的概念..DMA 有32个channel.  我大胆的猜想, 如果CAN1 将32个通道同时对应一个request line 4,  这样操作可行?

    如果可行是不是传输数据更快?

  • Sam,

        DMA channel只是为了方便设置DMA通道的优先级,因为我们芯片支持16个可独立配置的通道,如果一个系统里面用到了多个通道的话。他们在处理数据时,需要有相关的优先级仲裁,才能保证信息不被丢失。

       默认情况下,channel的ID越小,优先级越大,当然这个也可以通过相关的寄存器设置。

    如果你将32个通道连接到一个request line的话,这个数据传输可能会变慢。因为你32个通道都有数据发送,他们之间如果对应一个DMA request line的话,每一个CAN报文都需要等一个DMA传输结束后,才能去发送数据,然后在通过DMA去发送。还有一个问题就是,你需要在完成一次DMA操作后,再去配置新的DMA的寄存器,修改终端地址,这样效率会很低。

    谢谢

  • Ken,

    那就是一个CAN 对应一个channel, 每个channel对应一个request line, 每个源地址对应一个终端地址。这样是最常用的方式。

    如果用多channel 来接收数据的话,是不是意义不大. 因为每个CAN 只有一个源地址IF3DATx?  再去不对切换channel和更改终端地址。。有点得不偿失?

    效率也是没有提高。。反而再不断切换和修改Register 而浪费时间。。我理解的对吗?

  • sam,

       Bingo! 确实还是建议每个channel对应一个request line,每个源地址对应一个终端地址。

    这样无论是效率还是操作起来,都会比较简洁高效。

    谢谢

  • Ken,

    好的。明白了。谢谢!!