1. DMA简介
系统总线分别受到 CPU 和 DMAC 这两个部件的控制,即 CPU 可以向地址总线、 数据总线和控制总线发送信息(非 DMA 方式),DMAC 也可以向地址总线、数据总线和控制总线发送信息(DMA 方式)。但在同一时刻,系统总线只能受一个部 件的控制。究竟是哪个部件来控制系统总线,是由这两个部件之间的“联络信号” 控制实现的。DMA 取得总线控制权前处于受控状态,此时,CPU 可对 DMAC 进行初始化编程,也可以从 DMAC 中读出状态,这时 DMA 处于从态,DMAC 上电或复位时,DMAC 自动处于从态。在 DMAC 获得总线控制权之后,DMAC 取代 CPU 而成为系统总线的主控者,接管和控制系统总线。通过总线向存储器或 IO 设备发出地址、读/ 写信号,以控制在两个实体之前的数据传送。这时候 DMA 处于主动态。
DMA 数据传输是基于事件触发的,这就意味着 DMA 需要外设中断触发来启动DMA 的数据传输。F28335 共有 18 个不同的触发源,上图右边即为触发源,外设触发源有如下所示几种:
其中有 8 个外部中断触发源,全部来至 GPIO 引脚,这样 DMA 的时间触发是 很灵活的。DMA 不能通过自身数据源定时触发,若要定时触发可以借助外设中断 触发源中的 CPU 定时器来实现。F28335 共有 6 个 DMA 通道,每个通道都可以有 各自的触发源,通过各自独立的 PIE 中断告知 CPU DMA 数据传输的开始和结束,这 6 个通道中,第一通道有着更高的优先级。DMA 模块的核心其实是一个与地址控制逻辑紧密关联的状态机,在数据传输过程中让数据块自动的重新配置,就好像是两个缓冲器之间在打乒乓球一样,因此也把这种机制称为 DMA 的乒乓机制。DMA 总线结构包括一个 22 位地址总线,一个 32 位地址总线,一个 32 位数据读总线和一个 32 位数据写总线,与 DMA 总线相连的资源,好比乒乓球运动员,分别是数据传送的地址源与数据源,地址源与数据源的接口通过总线互相相连,这个接口 DMA 可能会访问,CPU 也会访问。与 DMA 总线相连的资源如上图左边部分(①XINTF 区域 0、6、7、8,L4 SARAM、L5 SARAM、L6 SARAM、L7 SARAM;②ADC 存储器映射结果寄存器;③MCBSP-A 和 MCBSP-B 数据接收寄存器(DDR2/DDR1)和数据发送寄存器(DXR2/DXR1);④映射到外设 3 的 ePWM1-6/HRPWM1-6 寄存器)。
(2)DMA 模块的流水线机制
有个例外情况是,当将 MCBSP 作为数据源时,读取 MCBSP DDR 寄存器的值时, 会拖延 DMA 一个时钟周期,如下图所示:
此外还有一些其他操作也会影响到 DMA 通道的吞吐,如下:
2 DMA 配置步骤
EALLOW;
SysCtrlRegs.PCLKCR3.bit.DMAENCLK = 1; // DMA Clock
EDIS;
void DMAInitialize(void);
void DMAInitialize(void)
{
EALLOW;
// Perform a hard reset on DMA
DmaRegs.DMACTRL.bit.HARDRESET = 1;
// Allow DMA to run free on emulation suspend
DmaRegs.DEBUGCTRL.bit.FREE = 1;
EDIS;
}
#define ADC_usDELAY 5000L
//---------------------------------------------------------------------------
// InitAdc:
//---------------------------------------------------------------------------
// This function initializes ADC to a known state.
//
void InitAdc(void)
{
extern void DSP28x_usDelay(Uint32 Count);
// *IMPORTANT*
// The ADC_cal function, which copies the ADC calibration values from TI reserved
// OTP into the ADCREFSEL and ADCOFFTRIM registers, occurs automatically in the
// Boot ROM. If the boot ROM code is bypassed during the debug process, the
// following function MUST be called for the ADC to function according
// to specification. The clocks to the ADC MUST be enabled before calling this
// function.
// See the device data manual and/or the ADC Reference
// Manual for more information.
EALLOW;
SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1;
ADC_cal();
EDIS;
// To powerup the ADC the ADCENCLK bit should be set first to enable
// clocks, followed by powering up the bandgap, reference circuitry, and ADC core.
// Before the first conversion is performed a 5ms delay must be observed
// after power up to give all analog circuits time to power up and settle
// Please note that for the delay function below to operate correctly the
// CPU_CLOCK_SPEED define statement in the DSP2833x_Examples.h file must
// contain the correct CPU clock period in nanoseconds.
AdcRegs.ADCTRL3.all = 0x00E0; // Power up bandgap/reference/ADC circuits/顺序采样
DELAY_US(ADC_usDELAY); // Delay before converting ADC channels
}
// This function initializes the DMA to a known state.
//
void DMAInitialize(void)
{
EALLOW;
// Perform a hard reset on DMA
DmaRegs.DMACTRL.bit.HARDRESET = 1;
// Allow DMA to run free on emulation suspend
DmaRegs.DEBUGCTRL.bit.FREE = 1;
EDIS;
}
void DMACH1AddrConfig(volatile Uint16 *DMA_Dest,volatile Uint16 *DMA_Source)
{
EALLOW;
// Set up SOURCE address:
DmaRegs.CH1.SRC_BEG_ADDR_SHADOW = (Uint32)DMA_Source; // Point to beginning of source buffer
DmaRegs.CH1.SRC_ADDR_SHADOW = (Uint32)DMA_Source;
// Set up DESTINATION address:
DmaRegs.CH1.DST_BEG_ADDR_SHADOW = (Uint32)DMA_Dest; // Point to beginning of destination buffer
DmaRegs.CH1.DST_ADDR_SHADOW = (Uint32)DMA_Dest;
EDIS;
}
void DMACH1BurstConfig(Uint16 bsize, int16 srcbstep, int16 desbstep)
{
EALLOW;
// Set up BURST registers:
DmaRegs.CH1.BURST_SIZE.all = bsize; // Number of words(X-1) x-ferred in a burst
DmaRegs.CH1.SRC_BURST_STEP = srcbstep; // Increment source addr between each word x-ferred
DmaRegs.CH1.DST_BURST_STEP = desbstep; // Increment dest addr between each word x-ferred
EDIS;
}
void DMACH1TransferConfig(Uint16 tsize, int16 srctstep, int16 deststep)
{
EALLOW;
// Set up TRANSFER registers:
DmaRegs.CH1.TRANSFER_SIZE = tsize; // Number of bursts per transfer, DMA interrupt will occur after completed transfer
DmaRegs.CH1.SRC_TRANSFER_STEP = srctstep; // TRANSFER_STEP is ignored when WRAP occurs
DmaRegs.CH1.DST_TRANSFER_STEP = deststep; // TRANSFER_STEP is ignored when WRAP occurs
EDIS;
}
void DMACH1WrapConfig(Uint16 srcwsize, int16 srcwstep, Uint16 deswsize, int16 deswstep)
{
EALLOW;
// Set up WRAP registers:
DmaRegs.CH1.SRC_WRAP_SIZE = srcwsize; // Wrap source address after N bursts
DmaRegs.CH1.SRC_WRAP_STEP = srcwstep; // Step for source wrap
DmaRegs.CH1.DST_WRAP_SIZE = deswsize; // Wrap destination address after N bursts
DmaRegs.CH1.DST_WRAP_STEP = deswstep; // Step for destination wrap
EDIS;
}
void DMACH1ModeConfig(Uint16 persel, Uint16 perinte, Uint16 oneshot, Uint16 cont, Uint16 synce, Uint16 syncsel, Uint16 ovrinte, Uint16 datasize, Uint16 chintmode, Uint16 chinte)
{
EALLOW;
// Set up MODE Register:
DmaRegs.CH1.MODE.bit.PERINTSEL = persel; // Passed DMA channel as peripheral interrupt source
DmaRegs.CH1.MODE.bit.PERINTE = perinte; // Peripheral interrupt enable
DmaRegs.CH1.MODE.bit.ONESHOT = oneshot; // Oneshot enable
DmaRegs.CH1.MODE.bit.CONTINUOUS = cont; // Continous enable
DmaRegs.CH1.MODE.bit.SYNCE = synce; // Peripheral sync enable/disable
DmaRegs.CH1.MODE.bit.SYNCSEL = syncsel; // Sync effects source or destination
DmaRegs.CH1.MODE.bit.OVRINTE = ovrinte; // Enable/disable the overflow interrupt
DmaRegs.CH1.MODE.bit.DATASIZE = datasize; // 16-bit/32-bit data size transfers
DmaRegs.CH1.MODE.bit.CHINTMODE = chintmode; // Generate interrupt to CPU at beginning/end of transfer
DmaRegs.CH1.MODE.bit.CHINTE = chinte; // Channel Interrupt to CPU enable
// Clear any spurious flags:
DmaRegs.CH1.CONTROL.bit.PERINTCLR = 1; // Clear any spurious interrupt flags
DmaRegs.CH1.CONTROL.bit.SYNCCLR = 1; // Clear any spurious sync flags
DmaRegs.CH1.CONTROL.bit.ERRCLR = 1; // Clear any spurious sync error flags
// Initialize PIE vector for CPU interrupt:
PieCtrlRegs.PIEIER7.bit.INTx1 = 1; // Enable DMA CH1 interrupt in PIE
EDIS;
}
// This function starts DMA Channel 1.
void StartDMACH1(void)
{
EALLOW;
DmaRegs.CH1.CONTROL.bit.RUN = 1;
EDIS;
}
void DMACH2AddrConfig(volatile Uint16 *DMA_Dest,volatile Uint16 *DMA_Source)
{
EALLOW;
// Set up SOURCE address:
DmaRegs.CH2.SRC_BEG_ADDR_SHADOW = (Uint32)DMA_Source; // Point to beginning of source buffer
DmaRegs.CH2.SRC_ADDR_SHADOW = (Uint32)DMA_Source;
// Set up DESTINATION address:
DmaRegs.CH2.DST_BEG_ADDR_SHADOW = (Uint32)DMA_Dest; // Point to beginning of destination buffer
DmaRegs.CH2.DST_ADDR_SHADOW = (Uint32)DMA_Dest;
EDIS;
}
void DMACH2BurstConfig(Uint16 bsize, int16 srcbstep, int16 desbstep)
{
EALLOW;
// Set up BURST registers:
DmaRegs.CH2.BURST_SIZE.all = bsize; // Number of words(X-1) x-ferred in a burst
DmaRegs.CH2.SRC_BURST_STEP = srcbstep; // Increment source addr between each word x-ferred
DmaRegs.CH2.DST_BURST_STEP = desbstep; // Increment dest addr between each word x-ferred
EDIS;
}
void DMACH2TransferConfig(Uint16 tsize, int16 srctstep, int16 deststep)
{
EALLOW;
// Set up TRANSFER registers:
DmaRegs.CH2.TRANSFER_SIZE = tsize; // Number of bursts per transfer, DMA interrupt will occur after completed transfer
DmaRegs.CH2.SRC_TRANSFER_STEP = srctstep; // TRANSFER_STEP is ignored when WRAP occurs
DmaRegs.CH2.DST_TRANSFER_STEP = deststep; // TRANSFER_STEP is ignored when WRAP occurs
EDIS;
}
void DMACH2WrapConfig(Uint16 srcwsize, int16 srcwstep, Uint16 deswsize, int16 deswstep)
{
EALLOW;
// Set up WRAP registers:
DmaRegs.CH2.SRC_WRAP_SIZE = srcwsize; // Wrap source address after N bursts
DmaRegs.CH2.SRC_WRAP_STEP = srcwstep; // Step for source wrap
DmaRegs.CH2.DST_WRAP_SIZE = deswsize; // Wrap destination address after N bursts
DmaRegs.CH2.DST_WRAP_STEP = deswstep; // Step for destination wrap
EDIS;
}
void DMACH2ModeConfig(Uint16 persel, Uint16 perinte, Uint16 oneshot, Uint16 cont, Uint16 synce, Uint16 syncsel, Uint16 ovrinte, Uint16 datasize, Uint16 chintmode, Uint16 chinte)
{
EALLOW;
// Set up MODE Register:
DmaRegs.CH2.MODE.bit.PERINTSEL = persel; // Passed DMA channel as peripheral interrupt source
DmaRegs.CH2.MODE.bit.PERINTE = perinte; // Peripheral interrupt enable
DmaRegs.CH2.MODE.bit.ONESHOT = oneshot; // Oneshot enable
DmaRegs.CH2.MODE.bit.CONTINUOUS = cont; // Continous enable
DmaRegs.CH2.MODE.bit.SYNCE = synce; // Peripheral sync enable/disable
DmaRegs.CH2.MODE.bit.SYNCSEL = syncsel; // Sync effects source or destination
DmaRegs.CH2.MODE.bit.OVRINTE = ovrinte; // Enable/disable the overflow interrupt
DmaRegs.CH2.MODE.bit.DATASIZE = datasize; // 16-bit/32-bit data size transfers
DmaRegs.CH2.MODE.bit.CHINTMODE = chintmode; // Generate interrupt to CPU at beginning/end of transfer
DmaRegs.CH2.MODE.bit.CHINTE = chinte; // Channel Interrupt to CPU enable
// Clear any spurious flags:
DmaRegs.CH2.CONTROL.bit.PERINTCLR = 1; // Clear any spurious interrupt flags
DmaRegs.CH2.CONTROL.bit.SYNCCLR = 1; // Clear any spurious sync flags
DmaRegs.CH2.CONTROL.bit.ERRCLR = 1; // Clear any spurious sync error flags
// Initialize PIE vector for CPU interrupt:
PieCtrlRegs.PIEIER7.bit.INTx2 = 1; // Enable DMA CH2 interrupt in PIE
EDIS;
}
// This function starts DMA Channel 2.
void StartDMACH2(void)
{
EALLOW;
DmaRegs.CH2.CONTROL.bit.RUN = 1;
EDIS;
}
void DMACH3AddrConfig(volatile Uint16 *DMA_Dest,volatile Uint16 *DMA_Source)
{
EALLOW;
// Set up SOURCE address:
DmaRegs.CH3.SRC_BEG_ADDR_SHADOW = (Uint32)DMA_Source; // Point to beginning of source buffer
DmaRegs.CH3.SRC_ADDR_SHADOW = (Uint32)DMA_Source;
// Set up DESTINATION address:
DmaRegs.CH3.DST_BEG_ADDR_SHADOW = (Uint32)DMA_Dest; // Point to beginning of destination buffer
DmaRegs.CH3.DST_ADDR_SHADOW = (Uint32)DMA_Dest;
EDIS;
}
void DMACH3BurstConfig(Uint16 bsize, int16 srcbstep, int16 desbstep)
{
EALLOW;
// Set up BURST registers:
DmaRegs.CH3.BURST_SIZE.all = bsize; // Number of words(X-1) x-ferred in a burst
DmaRegs.CH3.SRC_BURST_STEP = srcbstep; // Increment source addr between each word x-ferred
DmaRegs.CH3.DST_BURST_STEP = desbstep; // Increment dest addr between each word x-ferred
EDIS;
}
void DMACH3TransferConfig(Uint16 tsize, int16 srctstep, int16 deststep)
{
EALLOW;
// Set up TRANSFER registers:
DmaRegs.CH3.TRANSFER_SIZE = tsize; // Number of bursts per transfer, DMA interrupt will occur after completed transfer
DmaRegs.CH3.SRC_TRANSFER_STEP = srctstep; // TRANSFER_STEP is ignored when WRAP occurs
DmaRegs.CH3.DST_TRANSFER_STEP = deststep; // TRANSFER_STEP is ignored when WRAP occurs
EDIS;
}
void DMACH3WrapConfig(Uint16 srcwsize, int16 srcwstep, Uint16 deswsize, int16 deswstep)
{
EALLOW;
// Set up WRAP registers:
DmaRegs.CH3.SRC_WRAP_SIZE = srcwsize; // Wrap source address after N bursts
DmaRegs.CH3.SRC_WRAP_STEP = srcwstep; // Step for source wrap
DmaRegs.CH3.DST_WRAP_SIZE = deswsize; // Wrap destination address after N bursts
DmaRegs.CH3.DST_WRAP_STEP = deswstep; // Step for destination wrap
EDIS;
}
void DMACH3ModeConfig(Uint16 persel, Uint16 perinte, Uint16 oneshot, Uint16 cont, Uint16 synce, Uint16 syncsel, Uint16 ovrinte, Uint16 datasize, Uint16 chintmode, Uint16 chinte)
{
EALLOW;
// Set up MODE Register:
DmaRegs.CH3.MODE.bit.PERINTSEL = persel; // Passed DMA channel as peripheral interrupt source
DmaRegs.CH3.MODE.bit.PERINTE = perinte; // Peripheral interrupt enable
DmaRegs.CH3.MODE.bit.ONESHOT = oneshot; // Oneshot enable
DmaRegs.CH3.MODE.bit.CONTINUOUS = cont; // Continous enable
DmaRegs.CH3.MODE.bit.SYNCE = synce; // Peripheral sync enable/disable
DmaRegs.CH3.MODE.bit.SYNCSEL = syncsel; // Sync effects source or destination
DmaRegs.CH3.MODE.bit.OVRINTE = ovrinte; // Enable/disable the overflow interrupt
DmaRegs.CH3.MODE.bit.DATASIZE = datasize; // 16-bit/32-bit data size transfers
DmaRegs.CH3.MODE.bit.CHINTMODE = chintmode; // Generate interrupt to CPU at beginning/end of transfer
DmaRegs.CH3.MODE.bit.CHINTE = chinte; // Channel Interrupt to CPU enable
// Clear any spurious flags:
DmaRegs.CH3.CONTROL.bit.PERINTCLR = 1; // Clear any spurious interrupt flags
DmaRegs.CH3.CONTROL.bit.SYNCCLR = 1; // Clear any spurious sync flags
DmaRegs.CH3.CONTROL.bit.ERRCLR = 1; // Clear any spurious sync error flags
// Initialize PIE vector for CPU interrupt:
PieCtrlRegs.PIEIER7.bit.INTx3 = 1; // Enable DMA CH3 interrupt in PIE
EDIS;
}
// This function starts DMA Channel 3.
void StartDMACH3(void)
{
EALLOW;
DmaRegs.CH3.CONTROL.bit.RUN = 1;
EDIS;
}
void DMACH4AddrConfig(volatile Uint16 *DMA_Dest,volatile Uint16 *DMA_Source)
{
EALLOW;
// Set up SOURCE address:
DmaRegs.CH4.SRC_BEG_ADDR_SHADOW = (Uint32)DMA_Source; // Point to beginning of source buffer
DmaRegs.CH4.SRC_ADDR_SHADOW = (Uint32)DMA_Source;
// Set up DESTINATION address:
DmaRegs.CH4.DST_BEG_ADDR_SHADOW = (Uint32)DMA_Dest; // Point to beginning of destination buffer
DmaRegs.CH4.DST_ADDR_SHADOW = (Uint32)DMA_Dest;
EDIS;
}
void DMACH4BurstConfig(Uint16 bsize, int16 srcbstep, int16 desbstep)
{
EALLOW;
// Set up BURST registers:
DmaRegs.CH4.BURST_SIZE.all = bsize; // Number of words(X-1) x-ferred in a burst
DmaRegs.CH4.SRC_BURST_STEP = srcbstep; // Increment source addr between each word x-ferred
DmaRegs.CH4.DST_BURST_STEP = desbstep; // Increment dest addr between each word x-ferred
EDIS;
}
void DMACH4TransferConfig(Uint16 tsize, int16 srctstep, int16 deststep)
{
EALLOW;
// Set up TRANSFER registers:
DmaRegs.CH4.TRANSFER_SIZE = tsize; // Number of bursts per transfer, DMA interrupt will occur after completed transfer
DmaRegs.CH4.SRC_TRANSFER_STEP = srctstep; // TRANSFER_STEP is ignored when WRAP occurs
DmaRegs.CH4.DST_TRANSFER_STEP = deststep; // TRANSFER_STEP is ignored when WRAP occurs
EDIS;
}
void DMACH4WrapConfig(Uint16 srcwsize, int16 srcwstep, Uint16 deswsize, int16 deswstep)
{
EALLOW;
// Set up WRAP registers:
DmaRegs.CH4.SRC_WRAP_SIZE = srcwsize; // Wrap source address after N bursts
DmaRegs.CH4.SRC_WRAP_STEP = srcwstep; // Step for source wrap
DmaRegs.CH4.DST_WRAP_SIZE = deswsize; // Wrap destination address after N bursts
DmaRegs.CH4.DST_WRAP_STEP = deswstep; // Step for destination wrap
EDIS;
}
void DMACH4ModeConfig(Uint16 persel, Uint16 perinte, Uint16 oneshot, Uint16 cont, Uint16 synce, Uint16 syncsel, Uint16 ovrinte, Uint16 datasize, Uint16 chintmode, Uint16 chinte)
{
EALLOW;
// Set up MODE Register:
DmaRegs.CH4.MODE.bit.PERINTSEL = persel; // Passed DMA channel as peripheral interrupt source
DmaRegs.CH4.MODE.bit.PERINTE = perinte; // Peripheral interrupt enable
DmaRegs.CH4.MODE.bit.ONESHOT = oneshot; // Oneshot enable
DmaRegs.CH4.MODE.bit.CONTINUOUS = cont; // Continous enable
DmaRegs.CH4.MODE.bit.SYNCE = synce; // Peripheral sync enable/disable
DmaRegs.CH4.MODE.bit.SYNCSEL = syncsel; // Sync effects source or destination
DmaRegs.CH4.MODE.bit.OVRINTE = ovrinte; // Enable/disable the overflow interrupt
DmaRegs.CH4.MODE.bit.DATASIZE = datasize; // 16-bit/32-bit data size transfers
DmaRegs.CH4.MODE.bit.CHINTMODE = chintmode; // Generate interrupt to CPU at beginning/end of transfer
DmaRegs.CH4.MODE.bit.CHINTE = chinte; // Channel Interrupt to CPU enable
// Clear any spurious flags:
DmaRegs.CH4.CONTROL.bit.PERINTCLR = 1; // Clear any spurious interrupt flags
DmaRegs.CH4.CONTROL.bit.SYNCCLR = 1; // Clear any spurious sync flags
DmaRegs.CH4.CONTROL.bit.ERRCLR = 1; // Clear any spurious sync error flags
// Initialize PIE vector for CPU interrupt:
PieCtrlRegs.PIEIER7.bit.INTx4 = 1; // Enable DMA CH4 interrupt in PIE
EDIS;
}
// This function starts DMA Channel 4.
void StartDMACH4(void)
{
EALLOW;
DmaRegs.CH4.CONTROL.bit.RUN = 1;
EDIS;
}
void DMACH5AddrConfig(volatile Uint16 *DMA_Dest,volatile Uint16 *DMA_Source)
{
EALLOW;
// Set up SOURCE address:
DmaRegs.CH5.SRC_BEG_ADDR_SHADOW = (Uint32)DMA_Source; // Point to beginning of source buffer
DmaRegs.CH5.SRC_ADDR_SHADOW = (Uint32)DMA_Source;
// Set up DESTINATION address:
DmaRegs.CH5.DST_BEG_ADDR_SHADOW = (Uint32)DMA_Dest; // Point to beginning of destination buffer
DmaRegs.CH5.DST_ADDR_SHADOW = (Uint32)DMA_Dest;
EDIS;
}
void DMACH5BurstConfig(Uint16 bsize, int16 srcbstep, int16 desbstep)
{
EALLOW;
// Set up BURST registers:
DmaRegs.CH5.BURST_SIZE.all = bsize; // Number of words(X-1) x-ferred in a burst
DmaRegs.CH5.SRC_BURST_STEP = srcbstep; // Increment source addr between each word x-ferred
DmaRegs.CH5.DST_BURST_STEP = desbstep; // Increment dest addr between each word x-ferred
EDIS;
}
void DMACH5TransferConfig(Uint16 tsize, int16 srctstep, int16 deststep)
{
EALLOW;
// Set up TRANSFER registers:
DmaRegs.CH5.TRANSFER_SIZE = tsize; // Number of bursts per transfer, DMA interrupt will occur after completed transfer
DmaRegs.CH5.SRC_TRANSFER_STEP = srctstep; // TRANSFER_STEP is ignored when WRAP occurs
DmaRegs.CH5.DST_TRANSFER_STEP = deststep; // TRANSFER_STEP is ignored when WRAP occurs
EDIS;
}
void DMACH5WrapConfig(Uint16 srcwsize, int16 srcwstep, Uint16 deswsize, int16 deswstep)
{
EALLOW;
// Set up WRAP registers:
DmaRegs.CH5.SRC_WRAP_SIZE = srcwsize; // Wrap source address after N bursts
DmaRegs.CH5.SRC_WRAP_STEP = srcwstep; // Step for source wrap
DmaRegs.CH5.DST_WRAP_SIZE = deswsize; // Wrap destination address after N bursts
DmaRegs.CH5.DST_WRAP_STEP = deswstep; // Step for destination wrap
EDIS;
}
void DMACH5ModeConfig(Uint16 persel, Uint16 perinte, Uint16 oneshot, Uint16 cont, Uint16 synce, Uint16 syncsel, Uint16 ovrinte, Uint16 datasize, Uint16 chintmode, Uint16 chinte)
{
EALLOW;
// Set up MODE Register:
DmaRegs.CH5.MODE.bit.PERINTSEL = persel; // Passed DMA channel as peripheral interrupt source
DmaRegs.CH5.MODE.bit.PERINTE = perinte; // Peripheral interrupt enable
DmaRegs.CH5.MODE.bit.ONESHOT = oneshot; // Oneshot enable
DmaRegs.CH5.MODE.bit.CONTINUOUS = cont; // Continous enable
DmaRegs.CH5.MODE.bit.SYNCE = synce; // Peripheral sync enable/disable
DmaRegs.CH5.MODE.bit.SYNCSEL = syncsel; // Sync effects source or destination
DmaRegs.CH5.MODE.bit.OVRINTE = ovrinte; // Enable/disable the overflow interrupt
DmaRegs.CH5.MODE.bit.DATASIZE = datasize; // 16-bit/32-bit data size transfers
DmaRegs.CH5.MODE.bit.CHINTMODE = chintmode; // Generate interrupt to CPU at beginning/end of transfer
DmaRegs.CH5.MODE.bit.CHINTE = chinte; // Channel Interrupt to CPU enable
// Clear any spurious flags:
DmaRegs.CH5.CONTROL.bit.PERINTCLR = 1; // Clear any spurious interrupt flags
DmaRegs.CH5.CONTROL.bit.SYNCCLR = 1; // Clear any spurious sync flags
DmaRegs.CH5.CONTROL.bit.ERRCLR = 1; // Clear any spurious sync error flags
// Initialize PIE vector for CPU interrupt:
PieCtrlRegs.PIEIER7.bit.INTx5 = 1; // Enable DMA CH5 interrupt in PIE
EDIS;
}
// This function starts DMA Channel 5.
void StartDMACH5(void)
{
EALLOW;
DmaRegs.CH5.CONTROL.bit.RUN = 1;
EDIS;
}
void DMACH6AddrConfig(volatile Uint16 *DMA_Dest,volatile Uint16 *DMA_Source)
{
EALLOW;
// Set up SOURCE address:
DmaRegs.CH6.SRC_BEG_ADDR_SHADOW = (Uint32)DMA_Source; // Point to beginning of source buffer
DmaRegs.CH6.SRC_ADDR_SHADOW = (Uint32)DMA_Source;
// Set up DESTINATION address:
DmaRegs.CH6.DST_BEG_ADDR_SHADOW = (Uint32)DMA_Dest; // Point to beginning of destination buffer
DmaRegs.CH6.DST_ADDR_SHADOW = (Uint32)DMA_Dest;
EDIS;
}
void DMACH6BurstConfig(Uint16 bsize,Uint16 srcbstep, int16 desbstep)
{
EALLOW;
// Set up BURST registers:
DmaRegs.CH6.BURST_SIZE.all = bsize; // Number of words(X-1) x-ferred in a burst
DmaRegs.CH6.SRC_BURST_STEP = srcbstep; // Increment source addr between each word x-ferred
DmaRegs.CH6.DST_BURST_STEP = desbstep; // Increment dest addr between each word x-ferred
EDIS;
}
void DMACH6TransferConfig(Uint16 tsize, int16 srctstep, int16 deststep)
{
EALLOW;
// Set up TRANSFER registers:
DmaRegs.CH6.TRANSFER_SIZE = tsize; // Number of bursts per transfer, DMA interrupt will occur after completed transfer
DmaRegs.CH6.SRC_TRANSFER_STEP = srctstep; // TRANSFER_STEP is ignored when WRAP occurs
DmaRegs.CH6.DST_TRANSFER_STEP = deststep; // TRANSFER_STEP is ignored when WRAP occurs
EDIS;
}
void DMACH6WrapConfig(Uint16 srcwsize, int16 srcwstep, Uint16 deswsize, int16 deswstep)
{
EALLOW;
// Set up WRAP registers:
DmaRegs.CH6.SRC_WRAP_SIZE = srcwsize; // Wrap source address after N bursts
DmaRegs.CH6.SRC_WRAP_STEP = srcwstep; // Step for source wrap
DmaRegs.CH6.DST_WRAP_SIZE = deswsize; // Wrap destination address after N bursts
DmaRegs.CH6.DST_WRAP_STEP = deswstep; // Step for destination wrap
EDIS;
}
void DMACH6ModeConfig(Uint16 persel, Uint16 perinte, Uint16 oneshot, Uint16 cont, Uint16 synce, Uint16 syncsel, Uint16 ovrinte, Uint16 datasize, Uint16 chintmode, Uint16 chinte)
{
EALLOW;
// Set up MODE Register:
DmaRegs.CH6.MODE.bit.PERINTSEL = persel; // Passed DMA channel as peripheral interrupt source
DmaRegs.CH6.MODE.bit.PERINTE = perinte; // Peripheral interrupt enable
DmaRegs.CH6.MODE.bit.ONESHOT = oneshot; // Oneshot enable
DmaRegs.CH6.MODE.bit.CONTINUOUS = cont; // Continous enable
DmaRegs.CH6.MODE.bit.SYNCE = synce; // Peripheral sync enable/disable
DmaRegs.CH6.MODE.bit.SYNCSEL = syncsel; // Sync effects source or destination
DmaRegs.CH6.MODE.bit.OVRINTE = ovrinte; // Enable/disable the overflow interrupt
DmaRegs.CH6.MODE.bit.DATASIZE = datasize; // 16-bit/32-bit data size transfers
DmaRegs.CH6.MODE.bit.CHINTMODE = chintmode; // Generate interrupt to CPU at beginning/end of transfer
DmaRegs.CH6.MODE.bit.CHINTE = chinte; // Channel Interrupt to CPU enable
// Clear any spurious flags:
DmaRegs.CH6.CONTROL.bit.PERINTCLR = 1; // Clear any spurious interrupt flags
DmaRegs.CH6.CONTROL.bit.SYNCCLR = 1; // Clear any spurious sync flags
DmaRegs.CH6.CONTROL.bit.ERRCLR = 1; // Clear any spurious sync error flags
// Initialize PIE vector for CPU interrupt:
PieCtrlRegs.PIEIER7.bit.INTx6 = 1; // Enable DMA CH6 interrupt in PIE
EDIS;
}
// This function starts DMA Channel 6.
void StartDMACH6(void)
{
EALLOW;
DmaRegs.CH6.CONTROL.bit.RUN = 1;
EDIS;
}
void DMACH1_ADC_Init(volatile Uint16 *DMA_Dest,volatile Uint16 *DMA_Source)
{
EALLOW;
SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1; // ADC
EDIS;
// Specific clock setting for this example:
EALLOW;
SysCtrlRegs.HISPCP.all = 3; // HSPCLK = SYSCLKOUT/ADC_MODCLK
EDIS;
InitAdc(); // For this example, init the ADC
// Specific ADC setup for this example:
AdcRegs.ADCTRL1.bit.ACQ_PS = 0x0f;
AdcRegs.ADCTRL3.bit.ADCCLKPS = 0x01;
AdcRegs.ADCTRL1.bit.SEQ_CASC = 0; // 0 Non-Cascaded Mode
AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 0x1;
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 0x1;
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0;
AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0; // Set up ADC to perform 4 conversions for every SOC
// Start SEQ1
AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 0x1;
#ifdef DMA_INT_ENABLE
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
EALLOW; // Allow access to EALLOW protected registers
PieVectTable.DINTCH1= &local_DINTCH1_ISR;
EDIS; // Disable access to EALLOW protected registers
IER = M_INT7 ; //Enable INT7 (7.1 DMA Ch1)
EnableInterrupts();
#endif
EALLOW;
SysCtrlRegs.PCLKCR3.bit.DMAENCLK = 1; // DMA Clock
EDIS;
// Initialize DMA
DMAInitialize();
// Configure DMA Channel
DMACH1AddrConfig(DMA_Dest,DMA_Source);
DMACH1BurstConfig(15,0,1); //Will set up to use 32-bit datasize, pointers are based on 16-bit words
DMACH1TransferConfig(9,0,1); //so need to increment by 2 to grab the correct location
DMACH1WrapConfig(40,0,40,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 time
DMACH1ModeConfig(DMA_SEQ1INT,PERINT_ENABLE,ONESHOT_DISABLE,CONT_DISABLE,SYNC_DISABLE,
SYNC_SRC,OVRFLOW_DISABLE,SIXTEEN_BIT,CHINT_END,CHINT_ENABLE);
StartDMACH1();
}
interrupt void local_DINTCH1_ISR(void) // DMA Channel 1
{
// To receive more interrupts from this PIE group, acknowledge this interrupt
PieCtrlRegs.PIEACK.bit.ACK7 = 1;
// asm (" ESTOP0");//ok
// for(;;);
}
#pragma DATA_SECTION(DMABuf1,"DMARAML4");
#define DMA_BUF_SIZE 40
volatile Uint16 DMABuf1[DMA_BUF_SIZE];
void main()
{
int i=0;
InitSysCtrl();
InitPieCtrl();
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
LED_Init();
TIM0_Init(150,200000);//200ms
UARTa_Init(4800);
// Initialize Tables
for (i=0; i<DMA_BUF_SIZE; i++)
{
DMABuf1[i] = 0;
}
DMACH1_ADC_Init(DMABuf1,&AdcMirror.ADCRESULT0);
while(1)
{
}
}
(2)DMA_ram_to_ram
void DMAInitialize(void)
{
EALLOW;
// Perform a hard reset on DMA
DmaRegs.DMACTRL.bit.HARDRESET = 1;
// Allow DMA to run free on emulation suspend
DmaRegs.DEBUGCTRL.bit.FREE = 1;
EDIS;
}
void DMACH1_Init(volatile Uint16 *DMA_Dest,volatile Uint16 *DMA_Source)
{
EALLOW;
SysCtrlRegs.PCLKCR3.bit.DMAENCLK = 1; // DMA Clock
EDIS;
#ifdef DMA_INT_ENABLE
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
EALLOW; // Allow access to EALLOW protected registers
PieVectTable.DINTCH1= &local_DINTCH1_ISR;
EDIS; // Disable access to EALLOW protected registers
IER = M_INT7 ; //Enable INT7 (7.1 DMA Ch1)
EnableInterrupts();
#endif
// Initialize DMA
DMAInitialize();
// init_zone7();
// Configure DMA Channel
DMACH1AddrConfig(DMA_Dest,DMA_Source);
DMACH1BurstConfig(31,2,2); //Will set up to use 32-bit datasize, pointers are based on 16-bit words
DMACH1TransferConfig(31,2,2); //so need to increment by 2 to grab the correct location
DMACH1WrapConfig(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 time
DMACH1ModeConfig(DMA_TINT0,PERINT_ENABLE,ONESHOT_ENABLE,CONT_DISABLE,SYNC_DISABLE,SYNC_SRC,OVRFLOW_DISABLE,THIRTYTWO_BIT,CHINT_END,CHINT_ENABLE);
StartDMACH1();
}
#pragma DATA_SECTION(DMABuf1,"DMARAML4");
#pragma DATA_SECTION(DMABuf2,"DMARAML5");
#define DMA_BUF_SIZE 1024
volatile Uint16 DMABuf1[DMA_BUF_SIZE];
volatile Uint16 DMABuf2[DMA_BUF_SIZE];
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
int i=0;
InitSysCtrl();
InitPieCtrl();
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
LED_Init();
TIM0_Init(150,200000);//200ms
UARTa_Init(4800);
// Initialize Tables
for (i=0; i<DMA_BUF_SIZE; i++)
{
DMABuf1[i] = 0;
DMABuf2[i] = i;
}
DMACH1_Init(DMABuf1,DMABuf2);
while(1)
{
}
}
(3)DMA_xintf_to_ram
// Configure the timing paramaters for Zone 7.
// Notes:
// This function should not be executed from XINTF
// Adjust the timing based on the data manual and
// external device requirements.
void init_zone7(void)
{
EALLOW;
// Make sure the XINTF clock is enabled
SysCtrlRegs.PCLKCR3.bit.XINTFENCLK = 1;
EDIS;
// Configure the GPIO for XINTF with a 16-bit data bus
// This function is in DSP2833x_Xintf.c
InitXintf16Gpio();
// All Zones---------------------------------
// Timing for all zones based on XTIMCLK = SYSCLKOUT
EALLOW;
XintfRegs.XINTCNF2.bit.XTIMCLK = 0;
// Buffer up to 3 writes
XintfRegs.XINTCNF2.bit.WRBUFF = 3;
// XCLKOUT is enabled
XintfRegs.XINTCNF2.bit.CLKOFF = 0;
// XCLKOUT = XTIMCLK
XintfRegs.XINTCNF2.bit.CLKMODE = 0;
// Zone 7------------------------------------
// When using ready, ACTIVE must be 1 or greater
// Lead must always be 1 or greater
// Zone write timing
XintfRegs.XTIMING7.bit.XWRLEAD = 1;
XintfRegs.XTIMING7.bit.XWRACTIVE = 2;
XintfRegs.XTIMING7.bit.XWRTRAIL = 1;
// Zone read timing
XintfRegs.XTIMING7.bit.XRDLEAD = 1;
XintfRegs.XTIMING7.bit.XRDACTIVE = 3;
XintfRegs.XTIMING7.bit.XRDTRAIL = 0;
// don't double all Zone read/write lead/active/trail timing
XintfRegs.XTIMING7.bit.X2TIMING = 0;
// Zone will not sample XREADY signal
XintfRegs.XTIMING7.bit.USEREADY = 0;
XintfRegs.XTIMING7.bit.READYMODE = 0;
// 1,1 = x16 data bus
// 0,1 = x32 data bus
// other values are reserved
XintfRegs.XTIMING7.bit.XSIZE = 3;
EDIS;
//Force a pipeline flush to ensure that the write to
//the last register configured occurs before returning.
asm(" RPT #7 || NOP");
}
void DMACH1_Init(volatile Uint16 *DMA_Dest,volatile Uint16 *DMA_Source)
{
EALLOW;
SysCtrlRegs.PCLKCR3.bit.DMAENCLK = 1; // DMA Clock
EDIS;
EALLOW;
SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK = 1; // CPU Timer 0
EDIS;
CpuTimer0Regs.TCR.bit.TSS = 1; //Stop Timer0 for now
#ifdef DMA_INT_ENABLE
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
EALLOW; // Allow access to EALLOW protected registers
PieVectTable.DINTCH1= &local_DINTCH1_ISR;
EDIS; // Disable access to EALLOW protected registers
IER = M_INT7 ; //Enable INT7 (7.1 DMA Ch1)
EnableInterrupts();
#endif
// Initialize DMA
DMAInitialize();
init_zone7();
// Configure DMA Channel
DMACH1AddrConfig(DMA_Dest,DMA_Source);
DMACH1BurstConfig(31,2,2); //Will set up to use 32-bit datasize, pointers are based on 16-bit words
DMACH1TransferConfig(31,2,2); //so need to increment by 2 to grab the correct location
DMACH1WrapConfig(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 time
DMACH1ModeConfig(DMA_TINT0,PERINT_ENABLE,ONESHOT_ENABLE,CONT_DISABLE,SYNC_DISABLE,SYNC_SRC,OVRFLOW_DISABLE,THIRTYTWO_BIT,CHINT_END,CHINT_ENABLE);
StartDMACH1();
//Init the timer 0
CpuTimer0Regs.TIM.half.LSW = 512; //load low value so we can start the DMA quickly
CpuTimer0Regs.TCR.bit.SOFT = 1; //Allow to free run even if halted
CpuTimer0Regs.TCR.bit.FREE = 1;
CpuTimer0Regs.TCR.bit.TIE = 1; //Enable the timer0 interrupt signal
CpuTimer0Regs.TCR.bit.TSS = 0; //restart the timer 0
}
#define DMA_BUF_SIZE 1024
#pragma DATA_SECTION(DMABuf1,"DMARAML4");
#pragma DATA_SECTION(DMABuf2,"ZONE7DATA");
volatile Uint16 DMABuf1[DMA_BUF_SIZE];
volatile Uint16 DMABuf2[DMA_BUF_SIZE];
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
Uint16 i=0;
Uint16 j=0;
InitSysCtrl();
InitPieCtrl();
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
LED_Init();
TIM0_Init(150,200000);//200ms
UARTa_Init(4800);
DMACH1_Init(DMABuf1,DMABuf2);
// Initialize Tables
for (i=0; i<DMA_BUF_SIZE; i++)
{
DMABuf1[i] = 0;
DMABuf2[i] = i;
}
StartDMACH1();
while(1)
{
j++;
if(j%200==0)
{
LED6_TOGGLE;
}
DELAY_US(1000);
}
}