LPC2478(12)DMA

1、开发环境

LPC-2478STK+IAR+JINK

2、特性

GPDMA 使能外设到存储器、存储器到外设、外设到外设和存储器到存储器的传输。每个 DMA 流都可以为单个源和目标提供单向串行DMA 传输。例如,一个双向端口就需要一个发送流, 一个接收流。源和目标区可以是存储区或外设,可以通过 AHB 主机进行访问。

  • 2 个 DMA 通道。每个通道可支持一个单向传输; 
  • GPDMA 提供 16 根外设 DMA 请求线。某些请求线连接到支持 DMA 的外设:SD/MMC、 2 个 SSP 和 I2S 接口;
  • 单次 DMA 和突发 DMA 请求信号。每个连接到 GPDMA 的外设可以提交一个突发 DMA 请求或一个单次 DMA 请求。DMA 突发大小(burst size)通过编程 GPDMA来设置;
  • 存储器到存储器、存储器到外设、外设到存储器和外设到外设的传输;
  • 通过使用链表来支持分散或聚集的 DMA。这就意味者源区和目标区不一定要占用连续的存储区;
  • 硬件 DMA 通道优先级。每个 DMA 通道含有一个特定的硬件优先级。 DMA 通道0 的优先级最高,通道 1 的优先级最低。如果 2 个通道的请求同时有效,则先服务优先级最高的通道;
  • AHB 从机 DMA 编程接口。通过在 AHB 从机接口上写 DMA 控制寄存器来编程GPDMA;
  • 一个传输数据的 AHB 总线主机。这个接口在 DMA 请求有效时传输数据;
  • 32 位的 AHB 主机总线宽度;
  • 源或目标区的递增寻址或非递增寻址;
  • DMA 突发大小可编程。编程 DMA 突发大小可以提高传输数据的效率。通常,突发大小被设置成外设 FIFO 大小的一半;
  • 每个通道包含一个内部 4 个字的 FIFO;
  • 支持 8、 16 和 32 位宽的传输;
  • 支持大端和小端模式。复位后 GPDMA 默认为小端模式;
  • DMA 操作完成或出现 DMA 错误时可以产生一个处理器中断;
  • 中断屏蔽。可以屏蔽 DMA 错误中断请求和 DMA 终端计数中断请求;
  • 原始中断状态。 DMA 错误和 DMA 计数的原始中断状态可以在屏蔽之前被读出;
  • 测试寄存器可以用在模块和集成系统级别的测试中;
  • 专门识别 GPDMA 的标识寄存器。操作系统可以使用这些寄存器来对自身进行配置。

3、相关寄存器

3.1、中断状态寄存器DMACIntStatus

DMACIntStatus是一个只读寄存器,它显示了屏蔽后中断的状态。

3.2、中断终端计数状态寄存器DMACIntTCStatus

DMACIntTCStatus是一个只读寄存器,指示了屏蔽后终端计数的状态。

3.3、中断终端计数清除寄存器DMACIntClear

DMACIntTCClear寄存器只可写,它清除一个终端计数中断请求。

3.4、中断错误状态寄存器DMACIntErrorStatus

DMACIntErrorStatus是一个只读寄存器,它指示了屏蔽后错误请求的状态。

3.5、使能通道寄存器DMACEnbldChns

DMACIntErrClr是一个只写寄存器,它清除错误中断求。

3.6、原始中断终端计数状态寄存器DMACRawIntTCStatus

DMACRawIntTCStatus是一个只读寄存器,它指示在屏蔽前哪个DMA通道正在请求传输结束(终端计数中断)。值为 1 的位表明屏蔽前终端计数中断请求有效。

3.7、原始错误中断状态寄存器DMACRawIntErrorStatus

DMACRawIntErrorStatus是一个只读寄存器,它指示屏蔽前哪个DMA通道正在请求一个错误中断

3.8、使能通道寄存器DMACEnbldChns

DMACEnbldChns 是 一 个 只 读 寄 存 器 , 它 指 示 了 哪 个 DMA 通 道 被 使 能

3.9、软件突发请求寄存器DMACSoftBReq

DMACSoftBReq是一个可读/写寄存器,它使能软件产生DMA突发请求。

3.10、软件单次请求寄存器DMACSoftSReq

DMACSoftSReq是一个可读/写寄存器,它使能软件产生DMA单次请求。

3.11、软件最后一个突发请求寄存器DMACSoftLBreq

DMACSoftLBReq是一个可读/写的寄存器,它使能软件产生DMA最后一个突发请求。

3.12、软件最后一个单次请求寄存器DMACSoftLSReq

DMACSoftLSReq是一个可读/写寄存器,它使能软件产生DMA最后一个单次请求。

3.13、配置寄存器DMACConfiguration

DMACConfiguration是一个可读/写的寄存器,它配置GPDMA的操作。

3.14、同步寄存器DMACSync

DMACSync 是一个可读/写的寄存器,它使能或禁能 DMA 请求信号的同步逻辑。

3.15、通道源地址寄存器DMACCxSrcAddr

2 个可读/写的 DMACCxSrcAddr 寄存器包含当前要传输数据的源地址(字节对齐)。每个寄存器在相应的通道使能之前由软件直接编程。当 DMA 通道使能时,这个寄存器被更新:

  • 跟随源地址的增加而更新。
  • 当一个完整的数据包传输结束时源地址紧跟在链表之后。

在通道有效时读取这个寄存器不能提供有用的信息。这是因为那时软件已经处理了读取的值,通道可能已经继续向前执行了。规定只在通道停止后再读取寄存器,这样寄存器显示的是读出的最后一项的源地址。

3.16、通道目标地址寄存器DMACCxDestAddr

2 个可读/写的DMACCxDestAddr寄存器包含当前要传输数据的目标地址(字节对齐)。每个寄存器在相应的通道使能之前由软件直接编程。

3.17、通道链表项寄存器DMACCxLLI

两个可读/写的 DMACCxLLI 寄存器包含下个链表项(LLI)的字对齐地址,如果 LLI为 0,则当前的 LLI 是链的最后一项,当与之相关的所有 DMA 传输结束后 DMA 通道被禁能。

3.18、通道控制寄存器DMACCxControl

2 个可读/写的DMACCxControl寄存器包含传输大小、突发大小和传输宽度等DMA通道的控制信息。

3.19、通道配置寄存器DMACCxConfiguration

这 2 个DMACCxConfiguration寄存器是可读/写的,但位[17]除外,它是只读的。这两个寄存器用来配置DMA通道。

4、代码实现

代码功能:内存到内存

#include <nxp/iolpc2478.h>
#include <intrinsics.h>
typedef unsigned char  u8;
typedef unsigned short u16;
typedef unsigned int  u64;
typedef unsigned long  u32;

#ifndef NULL
#define NULL ((void*)0)
#endif
/* P1[13] 低电平导通 */
#define led1            13
/* P1[18] 低电平导通 */
#define led2            18
/* P2[19] 按下低电平,悬空高电平 */
#define but1            19
/* P2[21] 按下低电平,悬空高电平 */
#define but2            21

#define led1_on         (FIO1CLR |= 0x01 << led1)
#define led1_off        (FIO1SET |= 0x01 << led1)
#define led2_on         (FIO1CLR |= 0x01 << led2)
#define led2_off        (FIO1SET |= 0x01 << led2)

#define DMA_SRC			0x7FD00000
#define DMA_DST			0x7FD01000
#define DMA_SIZE		0x1000

#define M2M				0x00
#define M2P				0x01
#define P2M				0x02
#define P2P				0x03

void enable_fast_port()
{
  SCS |= 1 << 0;
}
void gpio_init()
{
  PINSEL2 &= ~(0x03 << led1*2);  
  FIO1DIR &= ~(0x01 << led1);  
  FIO1DIR |=   0x01 << led1;   
  led1_off;   
  PINSEL3 &= ~(0x03 << ((led2 % 16)*2));  
  FIO1DIR &= ~(0x01 << led2);  
  FIO1DIR |=   0x01 << led2;   
  led2_off; 
  
  PINSEL5 &= ~(0x03 << ((but1 % 16)*2));  
  PINSEL5 |=   (0x0 << ((but1 % 16)*2));  
  FIO2DIR &= ~(0x01 << but1); 
  
  PINSEL5 &= ~(0x03 << ((but2 % 16)*2));  
  PINSEL5 |=   (0x0 << ((but2 % 16)*2));  
  FIO2DIR &= ~(0x01 << but2); 
}
void led1_reverse(void)
{   
  if ((FIO1SET & (0x01 << led1)) == 0) 
    led1_off;
  else
    led1_on;						
}

void led2_reverse(void)
{   
  if ((FIO1SET & (0x01 << led2)) == 0)
    led2_off;
  else 
    led2_on;
}

__irq __arm void IRQ_Handler (void)
{
void (*interrupt_function)();
unsigned int vector;

  vector = VICADDRESS;     // Get interrupt vector.
  interrupt_function = (void(*)())vector;
  if(interrupt_function != NULL)
  {
    interrupt_function();  // Call vectored interrupt function.
  }
  else
  {
    VICADDRESS = 0;      // Clear interrupt in VIC.
  }
}
void VIC_SetVectoredIRQ(void(*pIRQSub)(), unsigned int Priority,
                        unsigned int VicIntSource)
{
unsigned long volatile *pReg;
  // load base address of vectored address registers
  pReg = &VICVECTADDR0;
  // Set Address of callback function to corresponding Slot
  *(pReg+VicIntSource) = (unsigned long)pIRQSub;
  // load base address of ctrl registers
  pReg = &VICVECTPRIORITY0;
  // Set source channel and enable the slot
  *(pReg+VicIntSource) = Priority;
  // Clear FIQ select bit
  VICINTSELECT &= ~(1<<VicIntSource);
}

volatile u8 DMATCCount = 0;
volatile u8 DMAErrCount = 0;

void DMAHandler (void) 
{
  u8 regVal;
  regVal = DMACINTTCSTATUS;
  if(regVal){
	DMATCCount++;
	DMACINTTCCLEAR |= regVal;
  } 
  regVal = DMACRAWINTERRORSTATUS;
  if ( regVal ){
	DMAErrCount++;
	DMACINTERRCLR |= regVal;
  } 
  VICADDRESS = 0;
}

void DMA_Init( u8 DMAMode )
{
  /* USB RAM is used for test.
  Please note, Ethernet has its own SRAM, but GPDMA can't access
  that. GPDMA can only access USB SRAM and IRAM. Ethernet DMA controller 
  can access both IRAM and Ethernet SRAM. */
  PCONP |= (1 << 29);	/* Enable GPDMA clock */

  /* clear all interrupts on channel 0 */
  DMACINTTCCLEAR = 0x01;
  DMACINTERRCLR = 0x01;
   
  if(DMAMode == M2M){
	/* Ch0 is used for M2M test, for M2P and P2M, go to peripheral directories
	where both DAM and non DMA examples are provided. */
	DMACC0SRCADDR = DMA_SRC;
	DMACC0DESTADDR = DMA_DST;
	/* Terminal Count Int enable */
	DMACC0CONTROL = ((DMA_SIZE/4) & 0x0FFF) | (0x04 << 12) | (0x04 << 15) 
		| (0x02 << 18) | (0x02 << 21) | (1 << 26) | (1 << 27) | 0x80000000;	
  }
  DMACCONFIGURATION = 0x01;	/* Enable DMA channels, little endian */
  while ( !(DMACCONFIGURATION & 0x01) );   
  
  VIC_SetVectoredIRQ(DMAHandler,0,VIC_GP_DMA);
  VICINTENABLE |= 1UL << VIC_GP_DMA;	
  __enable_interrupt();		
}
void dma_test(void)
{
  u16 i;
  u8 *src_addr, *dest_addr;
      
  src_addr = (u8 *)DMA_SRC;
  dest_addr = (u8 *)DMA_DST;
  for ( i = 0; i < DMA_SIZE/4; i++ ){
	*src_addr++ = i;
	*dest_addr++ = 0;
  }
  DMA_Init( M2M );
  DMACC0CONFIGURATION |= 0x08001;
  while ( !DMATCCount );
  /* Verify result */
  src_addr = (u8 *)DMA_SRC;
  dest_addr = (u8 *)DMA_DST;
  for ( i = 0; i < DMA_SIZE/4; i++ ){
	if ( *src_addr++ != *dest_addr++ ){
      led1_on;
	  while ( 1 );
	}
  }
  led2_on;
  while ( 1 );
}
int main(void)
{
  enable_fast_port();
  gpio_init();
  dma_test();
      
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值