mini2440裸机试炼之——DMA直接存取 实现Uart(串口)通信
这个仅仅能作为自己初步了解MDA的开门篇
实现功能:
将字符串数据通过DMA0通道传递给UTXH0,然后在终端
显示。传输数据完后。DMA0产生中断,beep声, LED亮。
DMA基本知识
计算机系统中各种经常使用的数据输入/输出方法有查询方式(包含无条件及条件传送方式)和中断方式,这些方式适用于CPU与慢速及中速外设之间的数据交换。但当高速外设要与系统内存或者要在系统内存的不同区域之间进行大量数据的高速传送时。就在一定程度上限制了数据传送的速率。直接存储器存取(DMA)就是为解决问题提出的,採用DMA方式,在一定时间段内,由DMA控制器代替CPU。获得总线控制权,来实现内存与外设或者内存的不同区域之间大量数据的高速传送。
DMA的概述:
SC2440支持位于系统总线与外围总线之间的四通道DMA控制。每一通道的DMA都能够处理一下四种情况:
1.源和目的器件均能够在系统总线
2.源器件在系统总线而目的器件在外围总线
3.源器件在外围总线而目的器件在系统总线
4.源和目的器件均能够在外围总线
DMA最大的有点就是能够在没有CPU干涉的情况下进行数据的传送。能够通过软件控制DMA启动,或者通过内部请求或者外部请求引脚启动。
DMA控制
DMA使用三态的有限状态机FSM (Finite State Machine)。有限状态机制)对其进行控制,下面用三步进行描写叙述:
状态1:
在初始状态,DMA等待DMA请求。当DMA请求到达时。进入状态2。在这 阶段DMA ACK和INT REQ均为0。
状态2:
在这个阶段,DMA ACK变成1以及计数器CURR_TC从DCON[19:0]寄存器载入数据。
(注意:DMA ACK保持1直到对其清零)
状态3:
在这个阶段,DMA对进行原子操作(atomic operation)的子有限状态机(sub-FSM)进行初始化。
sub-FSM从源地址读取数据以后并写进目的地址。在这个操作前。数据的大小和传输的大小均应给予考虑。在总体模式(Whole service mode)下的计数器(CURR_TC)为0之前。传输数据的操作将会继续。
当sub-FSM完毕原子操作后,主FSM进行倒计。另外,在计数器CRRR_TC为0以及中断设置DCON[29]寄存器被置1时,主FSM发出INT REQ信号。除此之外。同一时候清除DMA
ACK。
DMA寄存器配置
rDISRC0=(U32)SendBuffer; //数据地址
rDISRCC0 |=((0<<1)|(0<<0)); //[1]系统总线,[0]地址将依据单次和突发模式中每次传输后其数据大小而添加
rDIDST0=(U32)UTXH0; //传输目标地址UTXH0 {2440addr.h文件里定义 #define UTXH0 (0x50000020) }
rDIDSTC0 |=((0<<2)|(1<<1)|(1<<0)); //[2]在TC到达0时发生中断, [1] APB(外设总线上) , [0]传输后地址总线不变
//对上述寄存器说明。rDISRC0、rDIDST0分别配置为数据地址(DMA内部)、传输目标地址(uart是属于外设设备),再对应的配置rDISRCC0、rDIDSTC0 rDCON0 |=((U32)1<<31)|(0<<30)|(1<<29)|(0<<28)|(0<<27)|(1<<24)|(1<<23)|(1<<22)|(0<<20)|(15);
//[31] 握手模式; [30]同步PCLK=50M(APB时钟< 外设 >); [29]当全部传输完毕产生中断请求(即CURR_TC变为0);[28]运行一个单元传输;
//[27]选择每次原子传输(单次或突发4)后DMA停止和等待其他DMA请求的单服务模式; [24]UART0; [23]选择DMA源触发DMA操作;
//[22]当传输计数的当前值变为0时DMA通道(DMA REQ)关闭; [20]字节(每次一个字节传输);[19:0]初始传输计数15,15=SendBuffer字符数组长度; rDMASKTRIG0=(0<<2)|(1<<1)|(0<<0); //[1]打开DMA通道而且处理此通道DMA请求
总结
源地址: 字符串SendBuffer的地址
目的地址: uart0的地址
MDA仅仅是实现传输数据的一种机制,桥梁搭建的作用
这里并没实现MDA字符串SendBuffer赋值,而是CPU完毕的,MDA仅仅是实现直接从内存(字符串已经被CPU存放于内存)传输到uart0, 字符串Hello mini2440!,长15,每次输出一个字节,要输出十五次。tc就是存放输出的次数每输出一次tc减1,为0时, DMA停止和等待其他DMA请求的单服务模式,假设设置中断则产生MDA中断。所以说tc也就是节拍。
代码区
Main.c
#define GLOBAL_CLK 1 #include "def.h"
#include "option.h"
#include "2440addr.h"
#include "2440lib.h" //函数声明
#include "2440slib.h"
#include "mmu.h"
#include "profile.h" //函数声明处
extern void DMA_UART(void); void Main(void)
{
U32 mpll_val = 0,consoleNum;
Port_Init(); mpll_val = (92<<12)|(1<<4)|(1); //init FCLK=400M,
ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3);
ChangeClockDivider(14, 12); //the result of rCLKDIVN [0:1:0:1] 3-0 bit
cal_cpu_bus_clk(); //HCLK=100M PCLK=50M consoleNum = 0; // Uart 1 select for debug.
Uart_Init( 0,115200 );
Uart_Select( consoleNum ); MMU_Init();//中断映射地址初始化
Beep(2000, 100); DMA_UART(); //DMA方式实现Uart(串口)通信 }
DMA_uart.c
//====================================================================
// 实现功能:
// DMA直接存取 实现Uart(串口)通信,
// 将字符串数据通过DMA0通道传递给UTXH0,然后在终端
// 显示。传输数据完后,DMA0产生中断,beep声, LED亮。
// by:梁惠涌
//==================================================================== #include "2440addr.h"
#include "2440lib.h" //beep函数 char *SendBuffer = "Hello mini2440!" ; //source data /**************************************************************
DMA初始化
**************************************************************/
void Dma_init()
{
rDISRC0=(U32)SendBuffer; //数据地址
rDISRCC0 |=((0<<1)|(0<<0)); //[1]系统总线,[0]地址将依据单次和突发模式中每次传输后其数据大小而添加
rDIDST0=(U32)UTXH0; //传输目标地址UTXH0 {2440addr.h文件里定义 #define UTXH0 (0x50000020) }
rDIDSTC0 |=((0<<2)|(1<<1)|(1<<0)); //[2]在TC到达0时发生中断, [1] APB(外设总线上) , [0]传输后地址总线不变
//对上述寄存器说明。rDISRC0、rDIDST0分别配置为数据地址(DMA内部)、传输目标地址(uart是属于外设设备),再对应的配置rDISRCC0、rDIDSTC0 rDCON0 |=((U32)1<<31)|(0<<30)|(1<<29)|(0<<28)|(0<<27)|(1<<24)|(1<<23)|(1<<22)|(0<<20)|(15);
//[31] 握手模式; [30]同步PCLK=50M(APB时钟< 外设 >); [29]当全部传输完毕产生中断请求(即CURR_TC变为0);[28]运行一个单元传输;
//[27]选择每次原子传输(单次或突发4)后DMA停止和等待其他DMA请求的单服务模式; [24]UART0; [23]选择DMA源触发DMA操作;
//[22]当传输计数的当前值变为0时DMA通道(DMA REQ)关闭; [20]字节(每次一个字节传输);[19:0]初始传输计数15,15=SendBuffer字符数组长度; rDMASKTRIG0=(0<<2)|(1<<1)|(0<<0); //[1]打开DMA通道而且处理此通道DMA请求
} /**************************************************************
DMA中断
**************************************************************/
void __irq Dma0_isr(){
rSRCPND|=0x1<<17; //清除中断挂起状态
rINTPND|=0x1<<17;
Uart_Printf("\n ***DMA TO Uart finished***\n");
Beep(2000,100);
rGPBCON=0x015400;
rGPBDAT=0x6<<5;
} /**************************************************************
| DMA子函数
| 需设置2440lib.c里 rUCON0 |=((1<<0) | (1<<3) | (2<<10) );
**************************************************************/
void DMA_UART(){
Uart_Printf("\n ***HELLO DMA TO Uart ***\n");
Delay(1000); Dma_init();//DMA初始化
rINTMSK &=~(1<<17); //开 dma0 中断
pISR_DMA0=(U32)Dma0_isr; while(1){
}
}
截图
完整项目下载地址
mini2440裸机试炼之——DMA直接存取 实现Uart(串口)通信的更多相关文章
- mini2440裸机试炼之—RTC闹钟中断,节拍中断
版权声明:博客地址:http://blog.csdn.net/muyang_ren.源代码能够在我的github上找看看 https://blog.csdn.net/muyang_ren/articl ...
- mini2440裸机试炼之——看门狗中断和复位操作
看门狗的工作原理: 设本系统程序完整执行一周期的时间是Tp,看门狗的定时周期为Ti,Ti>Tp,在程序正常执行时,定时器就不会溢出,若因为干扰等原因使系统不能在Tp时刻改动定时器的记数值,定时器 ...
- mini2440裸机试炼之——Uart与pc端实现文件、字符传输
1. 波特率(Baud rate)即调制速率,1波特即指每秒传输1个符号. 2. 非FIFO模式,即数据传输不利用FIFO缓存,一个字节一个字节地传输. 3. 位能够用来推断发送缓存器中是否为空 ...
- 【ARM】2410裸机系列-uart串口通信
开发环境 (1)硬件平台:FS2410 (2)主机:Ubuntu 12.04 FS2410串口的原理图 串口UART寄存器配置 配置TXD0与RXD0(GPH2.GPH3) 设置波特率(UBRDI ...
- 八、mini2440裸机程序之UART(1)简单介绍【转】
转自:http://blog.csdn.net/shengnan_wu/article/details/8298869 一.概述 S3C2440通用异步接收和发送(UART)提供了三 ...
- (三)stm32之串口通信DMA传输完成中断
一.DMA功能简介 首先唠叨一下DMA的基本概念,DMA的出现大大减轻了CPU的工作量.在硬件系统中,主要由CPU(内核).外设.内存(SRAM).总线等结构组成,数据经常要在内存和外设之间,外设和外 ...
- 串口通信DMA中断
这是以前学32的时候写的,那时候学了32之后感觉32真是太强大了,比51强的没影.关于dma网上有许多的资料,亲们搜搜,这里只贴代码了,其实我也想详详细细地叙述一番,但是自己本身打字就慢,还有好多事情 ...
- mini2440裸机音乐播放器(非常久曾经的笔记)
[这是好久曾经写的.有点乱,没时间整理.当做记录用的.] 图片粘贴失效.没上传图,想要的直接下载文档吧. 项目目的:通过IIS,触摸屏,LCD模块实现音乐播放器功能(button上一首.下一首.播放. ...
- DMA 内存存取原理
DMA直接内存存取原理 DMADMA直接内存存取原理是指外部设备不通过CPU而直接与系统内存交换数据的接口技术. 要把外设的数据读入内存或把内存的数据传送到外设,一般都要通过CPU控制完成,如CPU程 ...
随机推荐
- linux系统自动执行任务(转)
开机启动 开机启动应该是我们很经常的需求了,我们常需要在开机时就自动执行某些命令来开启服务,进程等,有了它我们不必再在每次开机时输入同一堆命令. chkconfig命令 使用chkconfig命令可以 ...
- jquery之checkbox
//checkbox 数据回显 var publishRange=rowData.publishRange.split(","); for(var i = 0;i < pub ...
- gulp前端自动化构建工具新手入门篇
很久没有更新博文了. 经过了一次年前吐血的赶项目,终于在年后回血了.趁着有空,新学到了一个前端自动化构建工具-gulp. 现在我们通过这3个问题来学习一下: 1.什么是gulp? 2.为什么要用gul ...
- 在同个类中non-const插入const来减少重复
class A { private: std::string a; public: A(std::string b) :a(b){} const char& operator[](int b) ...
- swt
http://blog.sina.com.cn/s/blog_557ebb4c0101mgtc.html http://blog.csdn.net/kagoy/article/details/1746 ...
- JqueryUI插件网络连接
operamasks_UI官网 http://ui.operamasks.org/website/homepage.html EasyUI官网 http://www.jeasyui.com/index ...
- 转载:[Java]读取文件方法大全
转载网址:http://www.cnblogs.com/lovebread/archive/2009/11/23/1609122.html 1.按字节读取文件内容 2.按字符读取文件内容 3.按行读取 ...
- CentOS 5上Apache配置虚拟主机范例
昨天实践了下在CentOS 5上通过Apache直接配置虚拟主机,服务器没有安装面板软件,所以只能通过SSH远程连接操作了.Apache安装在/etc/httpd目录下,这个即是Apache的根目录, ...
- PHP数据过滤
1.php提交数据过滤的基本原则 1)提交变量进数据库时,我们必须使用addslashes()进行过滤,像我们的注入问题,一个addslashes()也就搞定了.其实在涉及到变量取值时,intval ...
- 深入浅出scanf、getcha、gets、cin函数
转:问题描述一:(分析scanf()和getchar()读取字符) scanf(), getchar()等都是标准输入函数,一般人都会觉得这几个函数非常简单,没什么特殊的.但是有时候却就是因为使用这些 ...