第7课:DMA
DMA利用了有限状态机来分析。它分成3个状态。
状态1等待REQ,一切状态为0
状态2这个状态已经接受到了REQ,这个时候把CNT中的值导入到DMA中的CURR—TC中,然后ACK就变成了1
状态3这个时候分为2个有限状态机,子机用来作数据传输,从源地址取数据,再写到目标地址。而主机负责计数,以及计数到0的中断等。。。
其实 有限状态机FSM这种分析方法简单来说就是把过程的变化无视掉,转而只看状态稳定后的结果。
以下来介绍在传输中的3种基本分类。
第一类 是 单元式 和 突发式 unit and brust
unit 发送1个Byte,而brust发送4个。
第2类 服务类 单一服务 和 连续服务 single and whole
单一服务本质上来讲就是做一个原子操作 必须再从状态1到状态3再走一遍,也就是说 需要等待REQ的这比有请求。而连续服务则在CURR_TC中的计数到0才停止。但是需要注意的一点:虽然是连续的,但是它也要短暂的释放数据总线,来给“饥渴”的CPU控制。
第3类 请求式和握手式 demand and shake
请求式就是当ACK结束整个一次传输后,恢复到0,发现REQ仍然是1的话,继续进行传输。
而shake mode 指的是 ,ACK完成一次传输后,一定要等到REQ 变成0,来确认才能继续进行。不然会一直等待。
请求式单服务,握手式单服务,握手式全服务,请求式全服务。一般如果是外设对外设的话,推荐使用请求全服务。
而从速度上来讲,连续服务的确比单服务快一点。
简单说下需要设置的寄存器。
因为我们有4组DMA,每组要设置的寄存器是9个,所以总共算术36个。
在9个中,前4个设置源地址,源地址的控制,目标地址,目标地址的控制等选项。
第5个是DMA控制寄存器,它要可以设置DMA的模式等具体的内容。
第6,7个是看源地址和目标地址在现在的数值。
而第8个是看CT内部计数器中,递减到了几。
第9个是控制DMA启动和停止的寄存器。例如在单一模式下,传完一次 on/off位会自动置0,需要再次置1才能再次传输
以下来进行举例:
写一个程序 利用分别利用DMA传输1M数据,另外一个正常拷贝,利用定时器PWM来计时 并输出到UART串口中。基本上除了中断,前2次用到的设备这次都利用到了。
#include"s3c2440.h"
#define UART_CLK 50000000
#define UART_BAUD_RATE 115200
#define UART_BRD (int)(UART_CLK/(UART_BAUD_RATE *16))-1
int n=0; //定义外部变量
void init_uart()
{
rGPHCON |=0xa0;
rGPHUP = 0x0c;
rULCON0 = 0x3;
rUCON0 = 0x5;
rUFCON0 = 0;
rUMCON0 = 0;
rUBRdiv0 = UART_BRD;
}
void init_timer0() //初始化pwm,0.5秒计65535次数
{
rTCFG0 = 0x63;
rTCFG1 = 0x1;
rTCNTB0 = 0xFFFF;
rTCON = 0xa;
rTCON = 0x9;
}
void init_irq()
{
rINTMOD = 0;
rINTMSK = ~(1<10);//计时到0进入ISR,其中进行计数的累加,和小灯亮暗处理,小灯亮暗 为了说明进入了中断
}
void uart_write(char *data)
{
while (*data != \0) {
while (!(rUTRSTAT0 & 0x4));
rUTXH0 = *data;
data++;
}
}
void init_dma()
{
rDISRC0 = 0x31000000;//初始化源地址
rDISRCC0 = 0x0;
rDIDST0 = 0x32000000;
rDIDSTC0 = 0x4;
rDCON0 = 0xb820ffff; //设置为模式
}
void long2char(long n)// 65535 is half second 把计数的值变成2进制,输出到uart中。
{
int c=32;
while(c!=0){
if(n&(0x1<31))
uart_write("1");
else
uart_write("0");
c--;
n=n<1;
}
}
void init_led()
{
rGPECON = GPE12_out|GPE13_out;
}
int main()
{
init_uart();
init_led();
init_irq();
init_timer0();
long t,t1,t2,num;
char *src = (char *)0x31000000;
char *obj = (char *)0x32000000;
num = 1024*1024;
n=0;
t1= (long)rTCNTO0;//t1第一次计数
uart_write("This is the time of normal memory copy :");
while(num>0){
*obj++ = *src++;//正常的拷贝
num--;
}
t2= (long)rTCNTO0;//t2第2次
t = (t1-t2)+65535*n;//计算时间差
long2char(t);
uart_write("\r\n");
init_dma();
n = 0;
t1 = rTCNTO0;
rDMASKTRIG0 = 3; //set the reg and then DMA will operate
while(rDSTAT0 & 0x1<20);
t2 = rTCNTO0;
t= (t1-t2)+65535*n;
uart_write("This is the time of DMA :");
long2char(t);
uart_write("\r\n");
}
这个是中断是ISR
#include"s3c2440.h"
void ISR_Handle()
{
extern int n;//外部变量的声明
n++;
rGPEDAT ^= (3<12);
rSRCPND = 1<10;
rINTPND = 1<10;
}
DM 相关文章:
- Linux嵌入式系统开发平台选型探讨(11-09)
- 达芬奇数字媒体片上系统的架构和Linux启动过程(06-02)
- 基于TMS320DM642的农药喷洒系统(04-22)
- CDMA2000基带信号发生器的FPGA+DSP实现(05-29)
- 基于DSP的视频采集驱动程序的实现(07-21)
- DSP中DMA操作的无阻塞请求实现(06-18)