GD32F10x DMA Flash to RAM transfer

一、DMA传输主要特性:

1,数据传输长度,最大65536

2,7个通道,每个通道都配置

3,AHB\APB外设,片上闪存和SRAM都可以作为访问的源端和目的端;

4,支持软件优先级:低、中、高、极高,硬件优先级:通道号越低,优先级越高

5,存储器和外设数据传输支持固定寻址和增量寻址;

6,支持循环传输模式

7,支持外设到存储器,存储器到外设,存储器到存储器的数据传输;

8, 每个通道有 3 种类型的事件标志和独立的中断,支持中断的使能和清除;

9,支持中断使能和清除。

二、功能描述

DMA传输分为两步操作:从源地址读取数据,之后将读取的数据存储到目的地址。

DMA控制器基于DMA_CHxPADDR、 DMA_CHxMADDR、 DMA_CHxCTL寄存器的值计算下一次操作的源/目的地址。

DMA_CHxCNT 寄存器用于控制传输的次数。

DMA_CHxCTL 寄存器的PWIDTH 和 MWIDTH 位域决定每次发送和接收的字节数(字节/半字/字)。

将 DMA_CHxCTL 寄存器的 CHEN 位清零,可以停止DMA 传输。

三、通道配置

要启动一次新的 DMA 数据传输,建议遵循以下步骤进行操作:

1. 读取 CHEN 位,如果为 1(通道已使能),清零该位。当 CHEN 为 0 时,请按照下列步骤

配置 DMA 开始新的传输。

2. 配置 DMA_CHxCTL 寄存器的 M2M 及 DIR 位,选择传输模式;

3. 配置 DMA_CHxCTL 寄存器的 CMEN 位,选择是否使能循环模式;

4. 配置 DMA_CHxCTL 寄存器的 PRIO 位域,选择该通道的软件优先级;

5. 通过DMA_CHxCTL寄存器配置存储器和外设的传输宽度以及存储器和外设地址生成算

法;

6. 通过DMA_CHxCTL寄存器配置传输完成中断,半传输完成中断,传输错误中断的使能位;

7. 通过 DMA_CHxPADDR 寄存器配置外设基地址;

8. 通过 DMA_CHxMADDR 寄存器配置存储器基地址;

9. 通过 DMA_CHxCNT 寄存器配置数据传输总量;

10. 将 DMA_CHxCTL 寄存器的 CHEN 位置1,使能 DMA 通道。

四、DMA寄存器

1,中断标志位寄存器 (DMA_INTF)

2,中断标志位清除寄存器 (DMA_INTC)

3,通道 x 外设基地址寄存器(DMA_CHxPADDR)

4,通道 x 存储器基地址寄存器 (DMA_CHxMADDR)

5,通道 x 计数寄存器 (DMA_CHxCNT)

6,通道 x 控制寄存器 (DMA_CHxCTL)

b0:[CHEN]通道使能

b1:[FTFIE]通道传输完成中断使能位

b2:[HTFIE]通道半传输完成中断使能位

b3:[ERRIE]通道错误中断使能位

b4:[DIR]传输方向:外设到存储器、存储器到外设

b5:[CMEN]循环模式使能

b6:[PNAGA]外设的地址生成算法:固定地址模式、增量地址模式

b7:[MNAGA]存储器的地址生成算法

b8:9:[PWIDTH]外设传输数据宽度

b11:10:[MWIDTH]存储器传输数据宽度

b13:12:[PRIO]软件优先级

b14:[M2M]存储器到存储器模式

四、实例

/* DMA initialize struct */
typedef struct
{
    uint32_t periph_addr;   /*!<外设的基地址 */
    uint32_t periph_width;  /*!< 传输外设的数据大小 */
    uint32_t periph_inc;    /*!< 外设增加模式 */
    uint32_t memory_addr;   /*!< 存储器基地址 */
    uint32_t memory_width;  /*!< 存储器传输数据大小 */
    uint32_t memory_inc;    /*!< 存储器增加模式 */
    uint32_t direction;     /*!< 通道传输方向 */
    uint32_t number;        /*!< 通道传输次数 */
    uint32_t priority;      /*!< 通道优先级 */
} dma_parameter_struct;

/*!
    \brief      this function handles DMA_Channel0_IRQHandler interrupt
    \param[in]  none
    \param[out] none
    \retval     none
*/
void DMA_Channel0_IRQHandler(void)
{
    if(dma_interrupt_flag_get(DMA_CH0,DMA_INT_FLAG_FTF)){     
        int_num++;
        dma_interrupt_flag_clear(DMA_CH0,DMA_INT_FLAG_FTF);
        dma_interrupt_flag_clear(DMA_CH0,DMA_INT_FLAG_G);
    }
}

int main()
{
    /* unlock the flash bank1 program erase controller */
    fmc_unlock();
    
    /* define the number of page to be erased */
    pagenum = (BANK1_WRITE_END_ADDR - BANK1_WRITE_START_ADDR) / FMC_PAGE_SIZE;
    
    /* clear all pending flags */
    fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_WPERR | FMC_FLAG_END);
    
    /* erase the flash pages */
    for(erasenum = 0; erasenum < pagenum; erasenum++){
          fmcstatus = fmc_page_erase(BANK1_WRITE_START_ADDR + (FMC_PAGE_SIZE * erasenum));
          wperror += (fmcstatus == FMC_WPERR);
          fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_WPERR | FMC_FLAG_END);
    }

    /* unlock the flash bank1 program erase controller */
    fmc_lock();
    
    ptrd = (uint32_t*)BANK1_WRITE_START_ADDR;
    for(i = 0; i < 256; i++){
        if(0xFFFFFFFF != *ptrd){ 
            accessflag = ERROR;
            break;
        }
        ptrd++;
    }

    /* unlock the flash bank1 program erase controller */
    fmc_unlock();
    
    /* define the number of page to be erased */
    pagenum = (BANK1_WRITE_END_ADDR - BANK1_WRITE_START_ADDR) / FMC_PAGE_SIZE;
    
    /* clear all pending flags */
    fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_WPERR | FMC_FLAG_END);    
    
    /* program flash bank1 */
    address = BANK1_WRITE_START_ADDR;
    wperror2 = 0;
    while(address < BANK1_WRITE_END_ADDR){
        fmcstatus = fmc_word_program(address, transdata);
        address = address + 4; 
        wperror2 += (FMC_WPERR == fmcstatus);
        fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_WPERR | FMC_FLAG_END);
    }
    
    fmc_lock();
    
     /* DMA channel0 initialize */
    //复位DMA通道0的所有寄存器
    dma_deinit(DMA_CH0);
    //通道传输方向 : 外设到内存
    dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
    //目标地址:存储器地址
    dma_init_struct.memory_addr = (uint32_t)destdata;
    //存储器地址增加方式:增量式
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    //传输宽度:8Bit
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
    //传输长度:1024Byte
    dma_init_struct.number = ACCESSSUM;
    //源地址:外设地址
    dma_init_struct.periph_addr = (uint32_t)BANK1_WRITE_START_ADDR;
    //外设地址增加方式:增量式
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_ENABLE;
    //传输宽度:8Bit
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
    //传输优先级:最高级
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
    
    dma_init(DMA_CH0,dma_init_struct);
    /* 禁用循环模式 */
    dma_circulation_disable(DMA_CH0);
    /* 使能内存到内存模式 */
    dma_memory_to_memory_enable(DMA_CH0);
    /* 中断使能,DMA通道传输完成中断 */
    dma_interrupt_enable(DMA_CH0, DMA_INT_FTF);
    /* DMA通道0传输使能 */
    dma_channel_enable(DMA_CH0);

    /* 等待DMA传输中断 */
    for(i = 0; i < 10000; i++){
        if(int_num)
        break;
    }    
    
    /* 比较外设和内存数据 */
    ptrd = destdata;
    for(i = 0; i < 256; i++){
        if(transdata != *ptrd)
        { 
            accessflag = ERROR;
            break;
        }
        ptrd++;
    }
    while(1);
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xtudj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值