文章目录
- 概述
- 官方例程1 内部RAM to RAM Example_2833xDMA_ram_to_ram
- 源码
- 解析
- 要点
- 方法拓展 外部固定地址 TO RAM
- 完整程序:
对DMA 和 DMA有关的API请看这篇文章
DSP28335 DMA API介绍
概述
本篇主要分析官方提供的28335 DMA 有关的例程 在此基础上有一定的拓展
官方例程1 内部RAM to RAM Example_2833xDMA_ram_to_ram
源码
//###########################################################################
// Description:
//! \addtogroup f2833x_example_list
//! <h1> DMA Ram to Ram (dma_ram_to_ram)</h1>
//!
//! This example will perform a block copy from L5 SARAM to L4 SARAM of 1024
//! words. Transfer will be started by Timer0. Will use 32-bit data size to
//! decrease the transfer time.
//!
//! \b Watch \b Variables \n
//! - DMABuf1
//! - DMABuf2
//
//
//###########################################################################
// $TI Release: F2833x/F2823x Header Files and Peripheral Examples V142 $
// $Release Date: November 1, 2016 $
// $Copyright: Copyright (C) 2007-2016 Texas Instruments Incorporated -
// http://www.ti.com/ ALL RIGHTS RESERVED $
//############################################################################include "DSP28x_Project.h" // Device Headerfile and Examples Include File#define BUF_SIZE 1024 // Sample buffer size// DMA Defines
#define CH1_TOTAL DATA_POINTS_PER_CHANNEL
#define CH1_WORDS_PER_BURST ADC_CHANNELS_TO_CONVERT#pragma DATA_SECTION(DMABuf1,"DMARAML4");
#pragma DATA_SECTION(DMABuf2,"DMARAML5");volatile Uint16 DMABuf1[1024];
volatile Uint16 DMABuf2[1024];volatile Uint16 *DMADest;
volatile Uint16 *DMASource;__interrupt void local_DINTCH1_ISR(void);void main(void)
{Uint16 i;
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the DSP2833x_SysCtrl.c file.InitSysCtrl();// Step 2. Initialize GPIO:
// This example function is found in the DSP2833x_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
// InitGpio(); // Skipped for this example// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interruptsDINT;// Initialize the PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the DSP2833x_PieCtrl.c file.InitPieCtrl();// Disable CPU interrupts and clear all CPU interrupt flags:IER = 0x0000;IFR = 0x0000;// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example. This is useful for debug purposes.
// The shell ISR routines are found in DSP2833x_DefaultIsr.c.
// This function is found in DSP2833x_PieVect.c.InitPieVectTable();// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.EALLOW; // Allow access to EALLOW protected registersPieVectTable.DINTCH1= &local_DINTCH1_ISR;EDIS; // Disable access to EALLOW protected registersIER = M_INT7 ; //Enable INT7 (7.1 DMA Ch1)EnableInterrupts();CpuTimer0Regs.TCR.bit.TSS = 1; //Stop Timer0 for now//Step 5. User specific code, enable interrupts:// Initialize DMADMAInitialize();// Initialize Tablesfor (i=0; i<BUF_SIZE; i++){DMABuf1[i] = 0;DMABuf2[i] = i;}// Configure DMA ChannelDMADest = &DMABuf1[0];DMASource = &DMABuf2[0];DMACH1AddrConfig(DMADest,DMASource);DMACH1BurstConfig(31,2,2); //Will set up to use 32-bit datasize, pointers are based on 16-bit wordsDMACH1TransferConfig(31,2,2); //so need to increment by 2 to grab the correct locationDMACH1WrapConfig(0xFFFF,0,0xFFFF,0);//Use timer0 to start the x-fer.//Since this is a static copy use one shot mode, so only one trigger is needed//Also using 32-bit mode to decrease x-fer timeDMACH1ModeConfig(DMA_TINT0,PERINT_ENABLE,ONESHOT_ENABLE,CONT_DISABLE,SYNC_DISABLE,SYNC_SRC,OVRFLOW_DISABLE,THIRTYTWO_BIT,CHINT_END,CHINT_ENABLE);StartDMACH1();//Init the timer 0CpuTimer0Regs.TIM.half.LSW = 512; //load low value so we can start the DMA quicklyCpuTimer0Regs.TCR.bit.SOFT = 1; //Allow to free run even if haltedCpuTimer0Regs.TCR.bit.FREE = 1;CpuTimer0Regs.TCR.bit.TIE = 1; //Enable the timer0 interrupt signalCpuTimer0Regs.TCR.bit.TSS = 0; //restart the timer 0for(;;){}
}// INT7.1
__interrupt void local_DINTCH1_ISR(void) // DMA Channel 1
{// To receive more interrupts from this PIE group, acknowledge this interruptPieCtrlRegs.PIEACK.all = PIEACK_GROUP7;// Next two lines for debug only to halt the processor here// Remove after inserting ISR Code__asm (" ESTOP0");for(;;);
}
解析
- 常规系统的初始化
- 初始化DMA相关中断 所以需要有一个中断函数
local_DINTCH1_ISR
- 初始化用到的变量
DMABuf1
DMABuf2
DMAInitialize();
DMA初始化DMACH1AddrConfig(DMADest,DMASource);
确定了Soruce and Dest 的地址- Burst Config:
DMACH1BurstConfig(31,2,2)
- 参数1 代表 32bit 的 datasize
- 参数2 代表 发送步长为2(335 是 16位的单片机 所以步长为2)
- 参数3 代表 接收步长为2
- DMACH1TransferConfig(31, 2, 2);
- 参数1 代表 一个burst 传 32 个最小单位 也就是32个32bit
- 参数2 代表 发送步长为2(335 是 16位的单片机 所以步长为2)
- 参数3 代表 接收步长为2
- DMACH1WrapConfig(0xFFFF, 0, 0xFFFF, 0);
- DMACH1ModeConfig(DMA_TINT0, PERINT_ENABLE, ONESHOT_DISABLE, CONT_DISABLE, SYNC_DISABLE, SYNC_SRC, OVRFLOW_DISABLE, THIRTYTWO_BIT, CHINT_END,
CHINT_ENABLE);DMA_TINT0
: DMA触发源为定时器0PERINT_ENABLE
:启用外设中断ONESHOT_ENABLE
:触发一次中断就完成所有传输CONT_DISABLE
:转换后禁用DMASYNC_DISABLE
:禁用同步SYNC_SRC
:SRC包装计数器控制OVRFLOW_DISABLE
:禁用溢出中断THIRTYTWO_BIT
:DMA传输的位为32位CHINT_END
:传输结束后发生中断CHINT_ENABLE
:启用DMA中断
- StartDMACH1(); 启动转换
要点
我对于DMA的理解 它是有2个循环 一个内循环 是BURST内的循环 BURST循环传完后 进入到 Transfer循环
BURST循环
DMACH1BurstConfig(31,2,2)
source: DMA每读取一个 偏移2
Dest:DMA每写一个 偏移2
Transfer循环
TransferConfig(31, 2, 2);
source: DMA每传完一个bust 偏移2
Dest:DMA每写一个burst 偏移2
针对上面的 为什么要Transfer一个后要偏移2呢 因为最后是要在第32个地址处来赋值的 burst传完后是在第31个地址处赋值(因为写的是31) 这时候是32位 2个16位 所以就是2 如果写的是0 0 那么最后一个数据会被覆盖掉
重要参数
THIRTYTWO_BIT
:DMA传输的位为32位 这也导致如果想要顺序吧source里的数据转入到dest里面DMACH1BurstConfig(31,2,2)
后两个参数要均为2 这代表着内循环用时候的偏差
方法拓展 外部固定地址 TO RAM
有时候很多芯片以外部接口+固定地址的FIFO给出的数据 此时 source的地址是不变的 dest 地址是递增的 这种情况下用以下配置
如果是16位的数据总线
可以用以下配置
DMACH1BurstConfig(0,0,0)
DMACH1TransferConfig(31, 0,1);
字为16bit
一次传递一个单位的数据
在底下for循环内加个延时带改DMAsource的值
测试结果:
完整程序:
#include "DSP28x_Project.h" // Device Header file and Examples Include File
#include "HAL/Hal.h"
#include "FML/Fml.h"//---DMA--------------------#define BUF_SIZE 1024 // Sample buffer size// DMA Defines
#define CH1_TOTAL DATA_POINTS_PER_CHANNEL
#define CH1_WORDS_PER_BURST ADC_CHANNELS_TO_CONVERT#pragma DATA_SECTION(DMABuf1,"DMARAML4");
#pragma DATA_SECTION(DMABuf2,"DMARAML5");volatile Uint16 DMABuf1[1024];
volatile Uint16 DMABuf2[1024];volatile Uint16 *DMADest;
volatile Uint16 *DMASource;__interrupt void local_DINTCH1_ISR(void);typedef struct DMA_TS{int BurstConfig_bsize;int BurstConfig_srcbstep;int BurstConfig_desbstep;int TransferConfig_tsize;int TransferConfig_srctstep;int TransferConfig_deststep;int ModeConfig_persel;int ModeConfig_perinte;int ModeConfig_oneshot;int ModeConfig_cont;int ModeConfig_synce;int ModeConfig_syncsel;int ModeConfig_ovrinte;int ModeConfig_datasize;int ModeConfig_chintmode;int ModeConfig_chinte;}DMA_TS;DMA_TS dma_ts = {.BurstConfig_bsize = 0,.BurstConfig_srcbstep = 0,.BurstConfig_desbstep = 1,.TransferConfig_tsize = 31,.TransferConfig_srctstep = 0,.TransferConfig_deststep = 1,.ModeConfig_persel = DMA_TINT0,.ModeConfig_perinte = PERINT_ENABLE,.ModeConfig_oneshot = ONESHOT_DISABLE,.ModeConfig_cont = CONT_DISABLE,.ModeConfig_synce = SYNC_DISABLE,.ModeConfig_syncsel = SYNC_SRC,.ModeConfig_ovrinte = OVRFLOW_DISABLE,.ModeConfig_datasize = SIXTEEN_BIT,.ModeConfig_chintmode = CHINT_END,.ModeConfig_chinte = CHINT_ENABLE,
};
int flag = 1;
//---DMA--------------------
void main(void){Uint16 i;// Step 1. Initialize System Control:PLL, WatchDog, enable Peripheral ClocksInitSysCtrl();// Step 2. Initialize GPIO: This example function is found in the F2837xS_Gpio.c file and illustrates how to set the GPIO to it's default state.InitCpuTimers();InitGpio();configtestled();// Step 3. Clear all interrupts and initialize PIE vector table:// Disable CPU interruptsDINT;// Initialize the PIE control registers to their default state.// The default state is all PIE interrupts disabled and flags// are cleared.// This function is found in the F2837xS_PieCtrl.c file.InitPieCtrl();EnableInterrupts();// Disable CPU interrupts and clear all CPU interrupt flags:IER = 0x0000;IFR = 0x0000;// Initialize the PIE vector table with pointers to the shell Interrupt// Service Routines (ISR).// This will populate the entire table, even if the interrupt// is not used in this example. This is useful for debug purposes.// The shell ISR routines are found in F2837xS_DefaultIsr.c.// This function is found in F2837xS_PieVect.c.InitPieVectTable();InitXintf();EALLOW;// Allow access to EALLOW protected registersPieVectTable.DINTCH1 = &local_DINTCH1_ISR;EDIS;// Disable access to EALLOW protected registersIER = M_INT7; //Enable INT7 (7.1 DMA Ch1)EnableInterrupts();CpuTimer0Regs.TCR.bit.TSS = 1; //Stop Timer0 for now// Initialize DMADMAInitialize();// Initialize Tablesfor (i = 0; i < BUF_SIZE; i++) {DMABuf1[i] = 0;DMABuf2[i] = i + 1;}// Configure DMA ChannelDMADest = &DMABuf1[0];DMASource = &DMABuf2[0];DMACH1AddrConfig(DMADest, DMASource);DMACH1BurstConfig(dma_ts.BurstConfig_bsize, dma_ts.BurstConfig_srcbstep, dma_ts.BurstConfig_desbstep); //Will set up to use 32-bit datasize, pointers are based on 16-bit wordsDMACH1TransferConfig(dma_ts.TransferConfig_tsize, dma_ts.TransferConfig_srctstep, dma_ts.TransferConfig_deststep); //so need to increment by 2 to grab the correct locationDMACH1WrapConfig(0xFFFF, 0, 0xFFFF, 0);//Use timer0 to start the x-fer.//Since this is a static copy use one shot mode, so only one trigger is needed//Also using 32-bit mode to decrease x-fer timeDMACH1ModeConfig(dma_ts.ModeConfig_persel, dma_ts.ModeConfig_perinte, dma_ts.ModeConfig_oneshot, dma_ts.ModeConfig_cont, dma_ts.ModeConfig_synce,dma_ts.ModeConfig_syncsel, dma_ts.ModeConfig_ovrinte, dma_ts.ModeConfig_datasize, dma_ts.ModeConfig_chintmode, dma_ts.ModeConfig_chinte);StartDMACH1();//Init the timer 0CpuTimer0Regs.TIM.half.LSW = 512; //load low value so we can start the DMA quicklyCpuTimer0Regs.TCR.bit.SOFT = 1; //Allow to free run even if haltedCpuTimer0Regs.TCR.bit.FREE = 1;CpuTimer0Regs.TCR.bit.TIE = 1; //Enable the timer0 interrupt signalCpuTimer0Regs.TCR.bit.TSS = 0; //restart the timer 0DELAY_US(10);for (;;){int i;for (i = 0; i < 30; ++i) {DELAY_US((Uint32)1000000);}DMABuf2[0]++;};}// INT7.1
__interrupt void local_DINTCH1_ISR(void) // DMA Channel 1
{// To receive more interrupts from this PIE group, acknowledge this interruptPieCtrlRegs.PIEACK.all = PIEACK_GROUP7;// Next two lines for debug only to halt the processor here// Remove after inserting ISR Code__asm (" ESTOP0");for(;;);
}