查看: 3879|回复: 6

[已解决] MKL36Z128VLL4 DMA触发问题

[复制链接]
  • TA的每日心情
    开心
    2019-2-18 09:04
  • 签到天数: 23 天

    连续签到: 1 天

    [LV.4]偶尔看看III

    15

    主题

    71

    帖子

    2

    中级会员

    Rank: 3Rank: 3

    积分
    219
    最后登录
    2019-3-5
    发表于 2019-2-14 09:48:42 | 显示全部楼层 |阅读模式
    使用PIT触发DMA控制一组GPIO(GPIOC)输出从而控制片外并行DAC。PIT触发时间为1us,但是看实际效果,GPIO输出为13.4us,而非1us,个人感觉是DMA中断导致CPU处理不过来,有什么方式可以加快GPIO的输出速度(1us)。我目前的配置代码如下:

    uint32_t g_dacDataValueArray[] = {0x5a5a5a5a,0xa5a5a5a5};
    dma_handle_t g_DMA_Handle; /* DMA handler. */
    dma_transfer_config_t g_transferConfig;
    volatile uint32_t g_index = 0U; /* Index of the g_dacDataArray array. */

    static void DMAMUX_Configuration(void)
    {
            /* Configure DMAMUX. */
            DMAMUX_Init(DMAMUX0);
            DMAMUX_SetSource(DMAMUX0, 0, 51); /* Map ADC source to channel 0 */
            DMAMUX_EnablePeriodTrigger(DMAMUX0,0);
            DMAMUX_EnableChannel(DMAMUX0, 0);
    }
    static void DMA_Callback(struct _dma_handle *handle, void *userData)
    {
        /* Clear DMA interrupt flag. */
        DMA_ClearChannelStatusFlags(DEMO_DMA_BASEADDR, DEMO_DMA_CHANNEL, kDMA_TransactionsDoneFlag);
        /* Setup transfer. */
        g_index++;
        if (g_index ==2)
        {
            g_index = 0U;
        }
        DMA_PrepareTransfer(&g_transferConfig, (void *)(g_dacDataValueArray+g_index), sizeof(uint32_t),
                            (void *)GPIOC_DATA_REG_ADDR, sizeof(uint32_t),4,kDMA_MemoryToMemory);
        DMA_SubmitTransfer(&g_DMA_Handle, &g_transferConfig, kDMA_EnableInterrupt);
        /* Enable transfer. */
        DMA_StartTransfer(&g_DMA_Handle);
    }

    static void DMA_Configuration(void)
    {
            DMA_Init(DMA0);
    #if 1
            DMA_CreateHandle(&g_DMA_Handle, DMA0, 0);
            DMA_SetCallback(&g_DMA_Handle, DMA_Callback, NULL);
      DMA_PrepareTransfer(&g_transferConfig, (void *)(g_dacDataValueArray+g_index), sizeof(uint32_t),
                            (void *)GPIOC_DATA_REG_ADDR, sizeof(uint32_t),4,kDMA_MemoryToMemory);
            DMA_SubmitTransfer(&g_DMA_Handle, &g_transferConfig, kDMA_EnableInterrupt);
    #endif
            /* Enable transfer. */
            DMA_StartTransfer(&g_DMA_Handle);
    }
    /* Enable the trigger source of PIT. *///24Mhz
    static void PIT_Configuration(void)
    {
                    pit_config_t pitConfig;

                    PIT_GetDefaultConfig(&pitConfig);
                    /* Init pit module */
                    PIT_Init(PIT, &pitConfig);
                    /* Set timer period for channel 0 */
                    PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, 24);//t = 1/24(us)
    //                PIT_EnableInterrupts(PIT, kPIT_Chnl_0,PIT_TCTRL_TIE_MASK);
    //                NVIC_SetPriority(PIT_IRQn, 5);
    //                EnableIRQ(PIT_IRQn);
    }


    最佳答案

    神的罪名 发表于 2019-2-14 17:27 是的,我试过就是因为DMA中断导致的,SDK例程里都是使用DMA中断做传输的,触发一次,传一个数据,进入DMA ... 楼主你好,我看你的中断代码写的太冗余了。 你可以使用最简单的方式, ...
    每天都要开心
    回复

    使用道具 举报

    该用户从未签到

    712

    主题

    6371

    帖子

    0

    超级版主

    Rank: 8Rank: 8

    积分
    24891
    最后登录
    2025-7-21
    发表于 2019-2-14 10:53:03 | 显示全部楼层
    楼主,你主频,bus时钟是多少?
    你有没有试过,不用DMA,直接用PIT中断去控制GPIO的速度,看看你那边能到多少呢?
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2019-2-18 09:04
  • 签到天数: 23 天

    连续签到: 1 天

    [LV.4]偶尔看看III

    15

    主题

    71

    帖子

    2

    中级会员

    Rank: 3Rank: 3

    积分
    219
    最后登录
    2019-3-5
     楼主| 发表于 2019-2-14 11:07:52 | 显示全部楼层
    小恩GG 发表于 2019-2-14 10:53
    楼主,你主频,bus时钟是多少?
    你有没有试过,不用DMA,直接用PIT中断去控制GPIO的速度,看看你那边能到多 ...

    主频48M,bus总线24M。刚试了下直接PIT中断控制GPIO,1us及以上均可准确控制,低于1us(ns级)时设置的时间跟输出的就不对应了,最快能有750ns,我设置的为1/24us。另外我在主循环试了下(只有GPIO翻转指令)可达到225ns。
    每天都要开心
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    712

    主题

    6371

    帖子

    0

    超级版主

    Rank: 8Rank: 8

    积分
    24891
    最后登录
    2025-7-21
    发表于 2019-2-14 16:27:31 | 显示全部楼层
    神的罪名 发表于 2019-2-14 11:07
    主频48M,bus总线24M。刚试了下直接PIT中断控制GPIO,1us及以上均可准确控制,低于1us(ns级)时设置的时间 ...

    嗯,PIT中断比主循环下慢,主要是因为进入中断我记得要十几个core时钟,然后再反转,肯定没有主循环直接连续翻快。你DMA控制的方式,应该还是和代码有关,中断进入多肯定会影响执行时间。
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2019-2-18 09:04
  • 签到天数: 23 天

    连续签到: 1 天

    [LV.4]偶尔看看III

    15

    主题

    71

    帖子

    2

    中级会员

    Rank: 3Rank: 3

    积分
    219
    最后登录
    2019-3-5
     楼主| 发表于 2019-2-14 17:27:04 | 显示全部楼层
    本帖最后由 神的罪名 于 2019-2-14 17:36 编辑
    小恩GG 发表于 2019-2-14 16:27
    嗯,PIT中断比主循环下慢,主要是因为进入中断我记得要十几个core时钟,然后再反转,肯定没有主循环直接 ...

    是的,我试过就是因为DMA中断导致的,SDK例程里都是使用DMA中断做传输的,触发一次,传一个数据,进入DMA中断再重新配置。我现在是配置一次DMA传送多个数据(比如64个),传输完成后进DMA中断再重新配置DMA,这还是会带来问题,由于PIT触发频率太高(1us),DMA连续传送64个字节后,进中断就会耽误时间,DMA可不可以循环来传送,比如源数据第64个字节传送完成后,重新回到源数据第一个字节循环传送,不用DMA中断。
    每天都要开心
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    712

    主题

    6371

    帖子

    0

    超级版主

    Rank: 8Rank: 8

    积分
    24891
    最后登录
    2025-7-21
    发表于 2019-2-18 14:29:53 | 显示全部楼层
    神的罪名 发表于 2019-2-14 17:27
    是的,我试过就是因为DMA中断导致的,SDK例程里都是使用DMA中断做传输的,触发一次,传一个数据,进入DMA ...

    楼主你好,我看你的中断代码写的太冗余了。
    你可以使用最简单的方式,不用callback, 直接在中断向量表里面用寄存器方式写。
    你不用调用API, 这样进入函数也要耗时间。给你举个例子:
    void DMA0_IRQHandler(void) {

            dma_dsr_bcr_reg = DMA_DSR_BCR0 ;
            dma_dcr_reg = DMA_DCR0;

            // Clear pending errors or the done bit
                            if (((DMA_DSR_BCR0 & DMA_DSR_BCR_DONE_MASK) == DMA_DSR_BCR_DONE_MASK)
                                            | ((DMA_DSR_BCR0 & DMA_DSR_BCR_BES_MASK) == DMA_DSR_BCR_BES_MASK)
                                            | ((DMA_DSR_BCR0 & DMA_DSR_BCR_BED_MASK) == DMA_DSR_BCR_BED_MASK)
                                            | ((DMA_DSR_BCR0 & DMA_DSR_BCR_CE_MASK) == DMA_DSR_BCR_CE_MASK))
                            {
                                    DMA_DSR_BCR0 |= DMA_DSR_BCR_DONE_MASK;
                                    dma_done = 1;
                            }

                            dma_dsr_bcr_reg2 = DMA_DSR_BCR0;

                    }
    你这样方式再试试。
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2019-2-18 09:04
  • 签到天数: 23 天

    连续签到: 1 天

    [LV.4]偶尔看看III

    15

    主题

    71

    帖子

    2

    中级会员

    Rank: 3Rank: 3

    积分
    219
    最后登录
    2019-3-5
     楼主| 发表于 2019-2-19 17:14:01 | 显示全部楼层
    小恩GG 发表于 2019-2-18 14:29
    楼主你好,我看你的中断代码写的太冗余了。
    你可以使用最简单的方式,不用callback, 直接在中断向量表里 ...

    非常感谢,按照GG的意思,此MCU确定是没有DMA自动循环的功能么?必须进中断重新配置。若使用寄存器直接操作的确是可以缩短中断时间。
    每天都要开心
    回复 支持 反对

    使用道具 举报

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

    本版积分规则

    关闭

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

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

    GMT+8, 2025-7-22 03:06 , Processed in 0.098573 second(s), 28 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

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