查看: 2470|回复: 7

[分享] KL46的串口0DMA发送

[复制链接]

该用户从未签到

6

主题

314

帖子

0

高级会员

Rank: 4

积分
726
最后登录
2016-6-27
发表于 2015-4-3 10:13:15 | 显示全部楼层 |阅读模式
本帖最后由 shock 于 2015-4-3 10:18 编辑

请教一个kl46dma串口发送的问题,配置为UART0_TX触发DMA发送, 参考了http://community.freescale.com/docs/DOC-99476此文档说的是关于kl26的uart0_dma发送,不知道跟kl46是不是有区别。程序配置如下:
uint8_t sData[64];
int main(void)
{
    UART_QuickInit(UART0_RX_PA01_TX_PA02, 115200);
    for(i=0;i<ARRAY_SIZE(sData);i++)
    {
        sData
= i;
    }
    UART0->C5 |= UART0_C5_TDMAE_MASK;                      // Turn on DMA request(Transmit) for UART0
    DMA_InitTypeDef DMA_InitStruct1 = {0};

    DMA_InitStruct1.chl = HW_DMA_CH0;
    DMA_InitStruct1.chlTriggerSource = UART0_TRAN_DMAREQ;
    DMA_InitStruct1.transferByteCnt = sizeof(sData);
    DMA_InitStruct1.triggerSourceMode = kDMA_TriggerSource_Normal;

    DMA_InitStruct1.sMod = kDMA_ModuloDisable;
    DMA_InitStruct1.sAddrIsInc = 1;
    DMA_InitStruct1.sDataWidth = kDMA_DataWidthBit_8;
    DMA_InitStruct1.sAddr = (uint32_t)sData;

    DMA_InitStruct1.dMod = kDMA_ModuloDisable;
    DMA_InitStruct1.dAddrIsInc = 0;
    DMA_InitStruct1.dDataWidth = kDMA_DataWidthBit_8;
    DMA_InitStruct1.dAddr = (uint32_t)&UART0->D;

    DMA_Init(&DMA_InitStruct1);
    DMA_EnableRequest(HW_DMA_CH0);
//                DMA_CallbackInstall(HW_DMA_CH0, DMA_ISR);
//                DMA_ITConfig(HW_DMA_CH0, kDMA_IT_Major, true);
               
    while(1)
    {
//                                DMAMUX0->CHCFG[0] &= ~DMAMUX_CHCFG_ENBL_MASK;   
                                DMA0->DMA[HW_DMA_CH0].DSR_BCR |= DMA_DSR_BCR_DONE_MASK;              //Clear Done bit
                                DMA0->DMA[HW_DMA_CH0].DSR_BCR = DMA_DSR_BCR_BCR(sizeof(sData));      //Reset BCR
                                DMA0->DMA[HW_DMA_CH0].SAR  = (uint32_t)sData;         //设置源地址,如果不设置,地址会一直增加
                                DMA_EnableRequest(HW_DMA_CH0);                                
//                                DMAMUX0->CHCFG[0] |= DMAMUX_CHCFG_ENBL_MASK;
                                GPIO_ToggleBit(HW_GPIOB, 23);
                                DelayMs(1000);                          
    }
}
现发现一个问题,就是当dma串口发送的时候,源地址为0x2000003C,然后发送完64个字节后,源地址变为0x2000007C,且下次发送是从0x2000007C开始发,发送完之后,源地址又变成0x200000AC,导致数据发送错误,因此在下次使能发送前,设置地址,红色那句,但是这样应该不算解决问题吧,是不是哪里配置错了,求FAE线上支持解答,谢谢!! SMOD  DMOD.png




回复

使用道具 举报

该用户从未签到

6

主题

314

帖子

0

高级会员

Rank: 4

积分
726
最后登录
2016-6-27
 楼主| 发表于 2015-4-3 10:17:43 | 显示全部楼层
本帖最后由 shock 于 2015-4-3 10:34 编辑

还有一个问题,就是关于DMA->DCR寄存器中的SMOD和DMOD,应该是指循环的字节个数吧,但是如何使用呢,我将SMOD和DMOD设置为64字节后,地址是不会递增了,但是数据却是错误的。发送的数据一直是<---- 接收帧:00 00 00 00 00 0E 27 07 78 00 00 00 C0 D4 01 00 00 A0 06 40 00 B0 06 40 00 C0 06 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00,搞不灵清
回复 支持 反对

使用道具 举报

  • TA的每日心情
    难过
    2021-12-15 16:01
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    305

    主题

    4701

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    377
    最后登录
    2023-8-16
    发表于 2015-4-3 11:31:14 | 显示全部楼层
    应该用SMOD,这个达到最大值以后会自动恢复到源地址.我发送的时候一般不用DMA,因为每次发送的数据都不一样.
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    6

    主题

    314

    帖子

    0

    高级会员

    Rank: 4

    积分
    726
    最后登录
    2016-6-27
     楼主| 发表于 2015-4-3 11:55:13 | 显示全部楼层
    安 发表于 2015-4-3 11:31
    应该用SMOD,这个达到最大值以后会自动恢复到源地址.我发送的时候一般不用DMA,因为每次发送的数据都不一样. ...

    你好,我就将smod设置为64字节,发现传输的数据错误,虽然地址还是源地址。
    另外就是dma可以发送不一样的数据的啊,你可以将数组赋值,此时再使能dma实现发送
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    124

    主题

    3600

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    5781
    最后登录
    1970-1-1
    发表于 2015-4-3 15:54:13 | 显示全部楼层
    shock 发表于 2015-4-3 11:55
    你好,我就将smod设置为64字节,发现传输的数据错误,虽然地址还是源地址。
    另外就是dma可以发送不一样的 ...

    安建议是正确的,最好使用SMOD的功能,我贴上使用SMOD的测试函数,你可以参考一下。
    1. /*******************************************************************************
    2. * This function will perform the basic transfer using a DMA SMOD feature and
    3. * using software start and will check for errors in transmission, if any.
    4. * Points to note:
    5. *  - SMOD size should be equal to the buffer_size defined
    6. *  - data size defined for src and dest xfr should be same
    7. *  as the MEM_FILL_* enum called.
    8. *  
    9. *  Result: This is validated by checking if the data at same source address is
    10. *  taken to be copied to destination address
    11. *  i.e Source address is wrapped after SMOD boundary.
    12. *  
    13. *  For eg:
    14. *    SMOD  =32 bytes
    15. *    nbytes=64 bytes
    16. *   
    17. *            0                   32                 64  
    18. *    SADDR:  |-------------------|-------------------|
    19. *            <-------data x-----><-------data y------>
    20. *
    21. *            0                   32                 64  
    22. *    DADDR:  |-------------------|-------------------|
    23. *            <-------data x-----><-------data x------>
    24. *            
    25. ******************************************************************************/
    26. void dma_smod(void)
    27. {
    28.         int dma_ch, loop_count;
    29.         uint32 dest_addr;
    30.         uint32 buffer_size;
    31.         uint32 Nbytes = 64;  //=16*4
    32.         //uint32 Nbytes = 128; //=64*2
    33.         //uint32 Nbytes = 256; //=64*4
    34.         //uint32 Nbytes = 1024;  //512*2
    35.         //uint32 Nbytes = 4096;  //2K*2
    36.         //uint32 Nbytes = 8192;  //4K*2 L2K has 16K Sram, 0x1FFFF000 - 0x20003000, so SMOD < 9
    37.        
    38.         printf("\n DMA transfer test using SMOD feature.");
    39.         
    40.         /* Initialize test variables */
    41.         tcd.saddr = SRAM_SADDRESS;
    42.         tcd.daddr = SRAM_DADDRESS;
    43.         tcd.nbytes = Nbytes;
    44.         tcd.ctrl  =   DMA_DCR_SSIZE_LONGWORD   //long word transfer
    45.                     | DMA_DCR_SINC_MASK
    46.                     | DMA_DCR_DSIZE_LONGWORD   //long word transfer
    47.                     | DMA_DCR_DINC_MASK
    48.                     | DMA_DCR_SMOD(0x1);       //circular buffer size of 16 bytes
    49.                     //| DMA_DCR_SMOD(0x3);       //circular buffer size of 64 bytes
    50.                     //| DMA_DCR_SMOD(0x6);       //circular buffer size of 512 bytes
    51.                     //| DMA_DCR_SMOD(0x8);       //circular buffer size of 2K bytes
    52.                     //| DMA_DCR_SMOD(0x9);       //circular buffer size of 4K bytes
    53.         /* Note: This is simple DMA transfer, so Auto Align and interrupt
    54.          * are not used.
    55.          * Also, if AA is enabled, DINC and SINC will increase no matter
    56.          * what value they have */
    57.    
    58.         /* Note: For this test the no of bytes to be xfred must be evenly divisible
    59.          * by the buffer_size; else the for loop used to check the end results,
    60.          * will not work correctly */               
    61.         /* Size of the circular source buffer, Must be a power of 2 and should be
    62.          * equal to SMOD size. */
    63.         buffer_size = 16;   //0x10  
    64.         //buffer_size = 64;   //0x40
    65.         //buffer_size = 512;  //0x200
    66.         //buffer_size = 2048; //0x800
    67.         //buffer_size = 4096; //0x1000  P0FC has 16K Sram, 0x1FFFE000 - 0x20002000, so SMOD < 9

    68.         /* Use all 4 DMA channels to check the basic transmission of data */
    69.         for(dma_ch = 0; dma_ch < 4; dma_ch++)
    70.         {
    71.           /* Initialize data at source location */
    72.           for(int j = 0; j < buffer_size; j++)
    73.             *((uint8 *)(tcd.saddr + j)) = j + dma_ch;       
    74.          
    75.           tcd.channelno = dma_ch;

    76.           /* Clear status */
    77.           DMA_DSR_BCR(dma_ch) |= DMA_DSR_BCR_DONE_MASK;
    78.          
    79.           /* Configure DMA registers */
    80.           dma_config(CONFIG_BASIC_XFR,&tcd);
    81.                
    82.           /* Start DMA transmission */
    83.           dma_config(DMA_SOFT_START, &tcd);               
    84.                
    85.           /* Wait till transfer is done */
    86.           dma_config(XFR_OVER_WAIT, &tcd);
    87.                
    88.           /* Check data coherence */
    89.           dest_addr = tcd.daddr;
    90.           for(loop_count = 0; loop_count < (Nbytes/buffer_size); loop_count++)
    91.           {
    92.             tcd.daddr = dest_addr + (loop_count * buffer_size) ;
    93.             tcd.nbytes = buffer_size;
    94.             dma_config(CMP_MEM, &tcd);
    95.           }       
    96.           tcd.daddr = dest_addr;
    97.           tcd.nbytes = Nbytes;

    98.           printf("\nDMA channel %01x test complete.\n", dma_ch);
    99.           printf("\n Press a character to proceed to next DMA CHANNEL...");
    100.           in_char();
    101.         }
    102.         
    103.         if(dma_error)
    104.           {
    105.               printf("\nTESTCASE FAIL\r\n");
    106.         }
    107.           else
    108.           {
    109.               printf("\nTESTCASE PASS\r\n");
    110.         }
    111. }
    复制代码


    回复 支持 反对

    使用道具 举报

    该用户从未签到

    6

    主题

    314

    帖子

    0

    高级会员

    Rank: 4

    积分
    726
    最后登录
    2016-6-27
     楼主| 发表于 2015-4-4 16:20:35 | 显示全部楼层
    FSL_TICS_ZP 发表于 2015-4-3 15:54
    安建议是正确的,最好使用SMOD的功能,我贴上使用SMOD的测试函数,你可以参考一下。

    ...

    最终还是失败了- -
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    124

    主题

    3600

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    5781
    最后登录
    1970-1-1
    发表于 2015-4-7 10:12:09 | 显示全部楼层
    shock 发表于 2015-4-4 16:20
    最终还是失败了- -

    根据参考代码修改过吗?还是同样的问题的吗?
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    难过
    2021-12-15 16:01
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    305

    主题

    4701

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    377
    最后登录
    2023-8-16
    发表于 2015-4-7 10:57:25 | 显示全部楼层
    失败的情况描述一下。
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-7-23 05:01 , Processed in 0.098278 second(s), 27 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表