首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Atmel SAMD21 DMA中止问题

Atmel SAMD21 DMA中止问题
EN

Stack Overflow用户
提问于 2015-11-17 06:18:45
回答 1查看 855关注 0票数 4

由于某些设计需求,我需要在运行时更改DMA描述符。为实现这一目标,我将采取以下步骤:

  1. 中断DMA通道。然后DMA硬件将保存当前正在执行的描述符在write_back内存位置相同的DMA通道。
  2. 等待中止完成
  3. 修改write_back内存位置上的DMA描述符。
  4. 再次启用DMA通道

这是我正在使用的代码片段:

代码语言:javascript
复制
//Select DMA channel
DMAC->CHID.reg = DMAC_CHID_ID(cSPIDMAResource0.channel_id);

//Abort Selected DMA channel
DMAC->CHCTRLA.reg &= ~DMA_CHANNEL_ENABLE_BIT_POS;

//Wait until Abort completed
while((DMAC->CHCTRLA.reg & DMA_CHANNEL_ENABLE_BIT_POS) == DMA_CHANNEL_ENABLE_BIT_POS);

/*
    Modify Descriptor here 
*/

//Enable DMA channel
DMAC->CHCTRLA.reg |= DMA_CHANNEL_ENABLE_BIT_POS;

上面提到的步骤运行良好,没有任何问题,但从长远来看,我面临描述符损坏问题。

在执行DMA中止时,DMA硬件正在将当前执行描述符存储在另一个DMA信道的write_back RAM位置(而不是自己的write_back RAM位置)。

如果有人知道出了什么问题,或者知道如何才能完全避免描述符腐败问题,我想尝试一下。

EN

回答 1

Stack Overflow用户

发布于 2015-11-24 15:59:46

为什么不使用atmel软件框架的dma驱动程序呢?这是他们做流产的方法。

代码语言:javascript
复制
void dma_abort_job(struct dma_resource *resource)
{
    uint32_t write_size;
    uint32_t total_size;

    Assert(resource);
    Assert(resource->channel_id != DMA_INVALID_CHANNEL);

    system_interrupt_enter_critical_section();

    DMAC->CHID.reg = DMAC_CHID_ID(resource->channel_id);
    DMAC->CHCTRLA.reg = 0;

    system_interrupt_leave_critical_section();

    /* Get transferred size */
    total_size = descriptor_section[resource->channel_id].BTCNT.reg;
    write_size = _write_back_section[resource->channel_id].BTCNT.reg;
    resource->transfered_size = total_size - write_size;

    resource->job_status = STATUS_ABORTED;
}

可以解释这一问题的一个不同之处是,在寄存器写入终止dma通道时,通过system_interrupt_leave_critical_section()禁用中断。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33750367

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档