访问DMA设备的API在sys/alt_dma.h中定义。DMA设备操作物理存储器的内容,因此, 当读和写数据时,用户必须考虑缓存的交互。 DMA发送通道
DMA发送请求使用DMA发送句柄进行排队。要获得一个句柄, 使用函数 alt_dma_txchan_open()函数。该函数需要一个变量,要使用的设备名字,在system.h中定义。 下面的代码展示的是怎样获得DMA发送设备dma_0的句柄。 例:获得DMA设备的文件句柄
#include
#include “sys/alt_dma.h” int main (void) {
alt_dma_txchan tx;
tx = alt_dma_txchan_open (“/dev/dma_0”);
if (tx == NULL) {
/* Error */ } else {
/* Success */ }
return 0; }
用户可以使用该句柄通过函数alt_dma_txchan_send()来递交一个发送请求。该函数原型 为:
typedef void (alt_txchan_done)(void* handle); int alt_dma_txchan_send (alt_dma_txchan dma, const void* from, alt_u32 length,
alt_txchan_done* done, void* handle);
调用alt_dma_txchan_send()向通道dma递交发送请求。变量length指定要发送的字节数, 变量from 指定源地址。函数在整个DMA传输结束之前返回。返回值指示请求是否成功,并排入队列。负的返回值表示请求失败。当传输结束,函数done被调用,提供通 知。两个附加的函数用来操控DMA发送通道:alt_dma_txchan_space()和 alt_dma_txchan_ioctl()。alt_dma_txchan_space()函数返回还有多少个发送请求可以加入到发 送队列中去。
alt_dma_txchan_ioctl()函数执行发送设备中与设备相关的操控。 如果使用Altera Avalon DMA设备发送到硬件设备(不是存储器到存储器的传输),调用 alt_dma_txchan_ioctl()函数,请求变量设成ALT_DMA_TX_ONLY_ON。 DMA接收通道
DMA 接收通道的工作方式同DMA发送通道相似。软件使用alt_dma_rxchan_open()函数可以获得DMA接收通道的句柄。 用户然后可以使用alt_dma_rxchan_prepare()函数来递交接收请求。alt_dma_rxchan_prepare()函数原型为:
typedef void (alt_rxchan_done)(void* handle, void* data); int alt_dma_rxchan_prepare (alt_dma_rxchan dma, void* data,
alt_u32 length,
alt_rxchan_done* done, void* handle);
void* handle);
调用该函数向dma通道递交一个接收请求, 长度为length比特的数据要被放到data指向的 地址。该函数在DMA传输结束前返回。返回值指示请求是否被排入队列。一个负的返回值 表示请求失败。当传输结束,用户指定的函数
done被调用,变量handle提供通知和接收数据 的指针。两个附加的函数被提供来操控DMA接收通道:alt_dma_rxchan_depth()和 alt_dma_rxchan_ioctl()。 如果用户使用Altera Avalon DMA设备来从硬件(非存储器之间的传输)接收数据,调 用alt_dma_rxchan_ioctl()函数,请求变量设成
ALT_DMA_RX_ONLY_ON。具体使用细节参 看Nios II Software Developer’s Handbook的HAL API 部分的alt_dma_rxchan_ioctl()章节。 alt_dma_rxchan_depth()返回设备可允许的最大的接收请求数。
alt_dma_rxchan_ioctl()执行接 收设备中设备相关的操纵。详细信息参考HAL API章节。 下面的代码演示的一个完整的是递交DMA接收请求以及main()中的直到传输完成的程 序例子。
例子:接收通道的DMA传输 #include
#include “sys/alt_dma.h” #include “alt_types.h”
/* flag used to indicate the transaction is complete */ volatile int dma_complete = 0;
/* function that is called when the transaction completes */ void dma_done (void* handle, void* data) {
dma_complete = 1; }
int main (void) {
alt_u8 buffer[1024]; alt_dma_rxchan rx;
/* Obtain a handle for the device */
if ((rx = alt_dma_rxchan_open (“/dev/dma_0”)) == NULL) {
printf (“Error: failed to open device\\n”); exit (1); } else {
/* Post the receive request */
if (alt_dma_rxchan_prepare (rx, buffer, 1024, dma_done, NULL) < 0) {
printf (“Error: failed to post receive request\\n”); exit (1);
}
/* Wait for the transaction to complete */ while (!dma_complete);
printf (“Transaction complete\\n”); alt_dma_rxchan_close (rx); }
return 0; }
存储器到存储器的DMA传输
从一个存储器缓冲器拷贝数据到另一个缓冲器,同时包括接收和发送DMA驱动程序。下面的代码演示的是请求队列中,一个接收请求后面跟着一个发送请求的过程。
例:存储器之间拷贝数据 #include
#include \#include \
static volatile int rx_done = 0; /*
* Callback function that obtains notification that the data has * been received. */
static void done (void* handle, void* data) {
rx_done++; } /* * */
int main (int argc, char* argv[], char* envp[]) {
int rc;
alt_dma_txchan txchan; alt_dma_rxchan rxchan;
void* tx_data = (void*) 0x901000; /* pointer to data to send */ void* rx_buffer = (void*) 0x902000; /* pointer to rx buffer */ /* Create the transmit channel */
if ((txchan = alt_dma_txchan_open(\{
printf (\exit (1); }
/* Create the receive channel */
if ((rxchan = alt_dma_rxchan_open(\{
printf (\exit (1); }
/* Post the transmit request */
if ((rc = alt_dma_txchan_send (txchan, tx_data, 128, NULL,
NULL)) < 0) {
printf (\exit (1); }
/* Post the receive request */
if ((rc = alt_dma_rxchan_prepare (rxchan, rx_buffer, 128, done,
NULL)) < 0) {
printf (\exit (1); }
/* wait for transfer to complete */ while (!rx_done);
printf (\return 0; }
6.5.11 启动顺序和入口点
通常用户程序的入口点就是main( )函数。这里还另有一个入口点alt_main( ),用户可以使用它来获得对启动顺序的更大的控制。程序的入口地址是main( )还是alt_main( )的区别就是托管(hosted)的应用和独立
(free-standing)的应用之间的区别。ANSI C标准定义托管应用是调用main( )函数来开始执行的应用,在main( )开始时,一个托管的应用运行环境和系统服务都已准备就绪。在HAL环境中就是这样的,如果是Nios II开发的新手,HAL的托管环境会帮助用户很容易地快速上手,因为用户不必考虑系统中包含什么样的设备以及怎样取初始化它们。HAL户初始化整个系统。 ANSI C标准也提供了一个可选的程序入口,可以避免自动的初始化,而由Nios II 程序 员手动初始化要使用的硬件。alt_main( )提供了一个独立的环境,使用户获得对系统初始