garfield

【原创】MCF52233的四通道DMA控制器

0
阅读(2205)

       DMA  DIRECT MEMORY ACCESS,直接存储器访问,简单点儿说就是在处理器不参与或者很少参与(仅提供控制功能)的情况下实现数据在存储器之间或存储器与io设备之间的批量传送。DMA控制器的作用是在大容量存储设备和内存之间传送批量数据。通常I/O外设会通过中断状态位,来告知系统数据是否已准备好或是否有对数据的请求。为了及时地响应这些事件,处理器经常会被中断。在该过程中CPU挂起当前进程,保存设备状态,服务于此事件,清除I/O请求标志,然后返回到被挂起的主进程。为避免每次事件都去中断CPU,ColdFire可使用DMA通道来响应I/O外设请求,实现对请求数据的传送,而不用每次都去中断CPU内核。

    MCF52233的四通道DMA控制器具有以下特点:
1.4个独立的可编程DMA控制通道;
2.源或目的访问的地址自动对齐;
3.双地址传送;
4.每个通道都有外部请求;
5.能进行8、16和32位的数据传送或用16字节缓冲器进行128位的突发数据传送;
6.具有连续传送或周期窃取传送两种模式;源数据或目的数据具有独立的传送带宽;
7.具有独立的源地址和目的地址寄存器;
8.具有源地址和目的地址的模块寻址能力;
9.自动通道链接。


DMA功能模块框图:

 

image

 

寄存器映射:

image

1.源地址寄存器(SARn)和目的地址寄存器(DARn)
       可读/写,包含32位源和目的存储器地址或者输入/输出外设地址。
2.字节计数寄存器(BCRn)
       与DMA状态寄存器共用相同的地址,低24位是字节计数寄存器字段,高8位是DMA状态寄存器。该寄存器用于写入需要传送的字节数。
3.DMA状态寄存器(DSRn)
       DMA状态是8位字段,它在BCR的最高字节中。在DMA通道传送操作中,这个寄存器中的状态位用于表示成功传送或有什么地方出错。
4.DMA控制寄存器(DCRn)
       该DMA控制寄存器可以控制DMA通道的所有操作。
5.DMA请求源
       有10种可能的请求(4个DMA定时器和6个UART),而DMA控制器只有4个通道,每个请求都可以逻辑地连接到4个通道之一。
DMA模块支持内部请求和外部请求,分别由DMA控制寄存器DCR的START和EEXT位控制。
        对于内部请求,设置DCRn的START位,使得DMA通道立即进行总线仲裁,以便于启动所请求的传送。
        对于外部请求,应用软件编程设定后,在开始传送操作之前,DMA通道持续等待,直到片上外设发出请求信号。

DMA启动序列
对于相对简单的任务,设置DMA模块需要以下步骤:
(1)向SARn写入32位源地址。
(2)向DARn写入32位目的地址。
(3)向BCRn写入要传送的字节数量。
(4)通过写DCRn,设置传送过程中的相关属性。

 

前一段时间写的dma与uart配合发送数据的例子,

软件开发环境cw7.0.

 

#include "dma.h"
#include "mcf52235.h"

char receive[64];

void uart0_init(uint16 baudrate)

{
uint32 div,SYS_CLOCK;
SYS_CLOCK=60000000;
MCF_GPIO_PUAPAR=MCF_GPIO_PUAPAR_UTXD0_UTXD0|MCF_GPIO_PUAPAR_URXD0_URXD0;

//Reset Transmitter Receiver Mode Register

MCF_UART0_UCR|=(0 |MCF_UART_UCR_RESET_TX
      |MCF_UART_UCR_RESET_RX
      |MCF_UART_UCR_RESET_MR);

//No parity,8bit data

MCF_UART0_UMR1=(0
     |MCF_UART_UMR_PM_NONE
     |MCF_UART_UMR_BC_8);
//1bit stop

MCF_UART0_UMR2=(0|MCF_UART_UMR_CM_NORMAL|MCF_UART_UMR_SB_STOP_BITS_1);

  //Set Rx and Tx buad by SYSTERM CLOCK

MCF_UART0_UCSR=(0|MCF_UART_UCSR_RCS_SYS_CLK|MCF_UART_UCSR_TCS_SYS_CLK);

//Mask all UART interrupts

MCF_UART0_UIMR=0;

//set buad rate

div=(SYS_CLOCK/32/baudrate);
MCF_UART0_UBG1=(unsigned char)(div>>8);
MCF_UART0_UBG2=(unsigned char)(div&0x00ff);
//Enable Tx/Rx
MCF_UART0_UCR=(0|MCF_UART_UCR_TX_ENABLED|MCF_UART_UCR_RX_ENABLED);
}

void DMA_init(void)

{

char *decadd=receive;
char i;
for(i=0;i<64;i++)
{
  receive[i]=0;
}
MCF_SCM_DMAREQC=MCF_SCM_DMAREQC_DMAC0(0x8);//UART0 receive
//source address register
MCF_DMA0_SAR= 0x4000020C;
  //destination address register
MCF_DMA_DAR(0)=(uint32)decadd;
//byte count
MCF_DMA0_BCR=64;
MCF_DMA0_DCR=MCF_DMA_DCR_INT //interrupt enable
    |MCF_DMA_DCR_EEXT //enable external request
    |MCF_DMA_DCR_CS //force a single read/write transfer per request
    |MCF_DMA_DCR_SSIZE(MCF_DMA_DCR_SSIZE_BYTE)
    |MCF_DMA_DCR_DINC
    |MCF_DMA_DCR_DSIZE(MCF_DMA_DCR_DSIZE_BYTE);

//UART0 read
MCF_SCM_PACR2=MCF_SCM_PACR_ACCESS_CTRL1(5);

//read/write
MCF_SCM_GPACR0=MCF_SCM_GPACR_ACCESS_CTRL(6);

//interrupt enable
MCF_INTC0_IMRL&=~MCF_INTC_IMRL_MASKALL;
MCF_INTC0_IMRL&=~MCF_INTC_IMRL_INT_MASK9;

//channel 0
MCF_INTC0_ICR09=MCF_INTC_ICR_IP(3)+MCF_INTC_ICR_IL(2);

}

void uart0_putchar(char c)

{

//Wait until space is available in the FIFO
while (!(MCF_UART0_USR&MCF_UART_USR_TXRDY)) { ; }

//Send the character
MCF_UART0_UTB = (unsigned char)c;

}

unsigned char uart0_getchar()

{

//Wait until character has been received
while (!(MCF_UART0_USR & MCF_UART_USR_RXRDY))
  { };

return MCF_UART0_URB;

}

void uart0_putstr(char *str)

{

while(*str!=0) { uart0_putchar(*str++); }

}

__declspec(interrupt:0) void DMA0_handler(void)//source 9

{

uint8 int_status = MCF_DMA0_DSR;

if(int_status & MCF_DMA_DSR_DONE)

{

  if(int_status & MCF_DMA_DSR_CE) { uart0_putstr("configuration error\n"); }

  else if(int_status & MCF_DMA_DSR_BED) { uart0_putstr("destination bus error\n"); }

  else if(int_status & MCF_DMA_DSR_BES) { uart0_putstr("source bus error\n"); }

  else {

    uart0_putstr("dma0 transfer done\n");

    uart0_putstr(receive);

    }

  //clear DMA0 interrupt

  MCF_DMA0_DCR&=~MCF_DMA_DCR_EEXT;

  MCF_DMA0_DSR |= MCF_DMA_DSR_DONE;

  MCF_DMA_DAR(0)=(uint32)receive;

  MCF_DMA0_BCR=64;

  MCF_DMA0_DCR|=MCF_DMA_DCR_EEXT;

  }

if(int_status & MCF_DMA_DSR_BSY) { uart0_putstr("busy\n"); }

if(int_status & MCF_DMA_DSR_REQ) { uart0_putstr("transfer remaining but channel not selected\n");}

}


dma_uart_4928.rar