标签:des c style class blog code
AXI HP接口的DMA+GIC编程(参照博客)
参照文档:UG873,博客文档
Vivado 接线图:
地址分配:
standalone代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348 |
#include <stdio.h> //#include "platform.h" #include "xaxicdma.h" #include "xdebug.h" #include "xil_exception.h" #include "xil_cache.h" #include "xparameters.h" #include "xscugic.h" //包含头文件,不必多言 #define NUMBER_OF_TRANSFERS 2 /* 做两次传输 */ #define DMA_CTRL_DEVICE_ID XPAR_AXICDMA_0_DEVICE_ID //DMA控制设备ID号= #define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID //GIC控制设备ID号= #define DMA_CTRL_IRPT_INTR XPAR_FABRIC_AXI_CDMA_0_CDMA_INTROUT_INTR //中断号 volatile
static int Done = 0; /* Dma transfer is done */ volatile
static int Error = 0; /* Dma Bus Error occurs */ static
u32 SourceAddr = 0x10000000; // =0x10000000 static
u32 DestAddr = 0x18000000; // = 0x18000000 static
XAxiCdma AxiCdmaInstance; /* XAxiCdma 控制对象*/ static
XScuGic IntcController; /* Interrupt Controller 控制对象*/ static
int Array_3[32][16]; //阵列 static
int Array_4[32][16]; static
int Array_1[32][16]; static
int Array_2[32][16]; int
const input[16] = {0xb504f33, 0xabeb4a0, 0xa267994, 0x987fbfc, 0x8e39d9c, 0x839c3cc, 0x78ad74c, 0x6d743f4, 0x61f78a8, 0x563e6a8, 0x4a5018c, 0x3e33f2c, 0x31f1704, 0x259020c, 0x1917a64, 0xc8fb2c}; /* Length of the buffers for DMA transfer */ static
u32 BUFFER_BYTESIZE = (XPAR_AXI_CDMA_0_M_AXI_DATA_WIDTH * XPAR_AXI_CDMA_0_M_AXI_MAX_BURST_LEN); //大小为1024*256/8=32KB,起始就是我们在XPS中设置好的 static
int CDMATransfer(XAxiCdma *InstancePtr, int
Length, int
Retries); //执行传输 static
void DisableIntrSystem(XScuGic *IntcInstancePtr , u32 IntrId) //禁止中断 { XScuGic_Disable(IntcInstancePtr ,IntrId ); XScuGic_Disconnect(IntcInstancePtr ,IntrId ); } //Multiply and Shift int
MUL_SHIFT_30( int
x, int
y) //实现x*y,但又怕溢出,所以右移30位,除以2^30~1e9 { return
(( int ) ((( long
long ) (x) * (y)) >> 30)); } void
MULT_SHIFT_LOOP( int
Value ) //生成源数据的函数 { int
i, j; for
(i = 0; i < 32; i++) { for
(j = 0; j < 16; j++) { Array_3[i][j] = ( int )((MUL_SHIFT_30(input[j],Array_1[j][i])) + Value); Array_4[i][j] = ( int )((MUL_SHIFT_30(input[j],Array_2[j][i])) + Value); } } } void
TestPattern_Initialization( void ) //生成原始数据 { int
i, j; for
(i = 0; i < 32; i++) { for
(j = 0; j < 16; j++) { Array_1[i][j] = ( int
) ((0xA5A5A5A5 >> 1) * i ); Array_2[i][j] = ( int
) ((0xA5A5A5A5 << 1) * i ); } } } //下面是中断服务函数 static
void Cdma_CallBack( void
*CallBackRef, u32 IrqMask, int
*IgnorePtr) { if
(IrqMask & XAXICDMA_XR_IRQ_ERROR_MASK) { Error = TRUE; printf ( "\r\n--- Transfer Error --- \r\n" ); //传输出错 } if
(IrqMask & XAXICDMA_XR_IRQ_IOC_MASK) { printf ( "\r\n--- Transfer Done --- \r\n" ); Done = TRUE; //传输成功 } } //设置中断系统,初始化中断控制器 static
int SetupIntrSystem(XScuGic *IntcInstancePtr, XAxiCdma *InstancePtr, u32 IntrId) { int
Status; /* * Initialize the interrupt controller driver */ XScuGic_Config *IntcConfig; /* * Initialize the interrupt controller driver so that it is ready to * use. */ IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID); if
(NULL == IntcConfig) { return
XST_FAILURE; } Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig, IntcConfig->CpuBaseAddress); if
(Status != XST_SUCCESS) { return
XST_FAILURE; } XScuGic_SetPriorityTriggerType(IntcInstancePtr, IntrId, 0xA0, 0x3); /* * Connect the device driver handler that will be called when an * interrupt for the device occurs, the handler defined above performs * the specific interrupt processing for the device. */ Status = XScuGic_Connect(IntcInstancePtr, IntrId, (Xil_InterruptHandler)XAxiCdma_IntrHandler, InstancePtr); if
(Status != XST_SUCCESS) { return
Status; } /* * Enable the interrupt for the DMA device. */ XScuGic_Enable(IntcInstancePtr, IntrId); Xil_ExceptionInit(); /* * Connect the interrupt controller interrupt handler to the hardware * interrupt handling logic in the processor. */ Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, IntcInstancePtr); /* * Enable interrupts in the Processor. */ Xil_ExceptionEnable(); return
XST_SUCCESS; } int
XAxiCdma_Interrupt(XScuGic *IntcInstancePtr, XAxiCdma *InstancePtr, u16 DeviceId, u32 IntrId) { { XAxiCdma_Config *CfgPtr; int
Status; int
SubmitTries = 1; /* Retry to submit */ int
Tries = NUMBER_OF_TRANSFERS; int
Index; /* Initialize the XAxiCdma device. */ CfgPtr = XAxiCdma_LookupConfig(DeviceId); if
(!CfgPtr) { return
XST_FAILURE; } Status = XAxiCdma_CfgInitialize(InstancePtr, CfgPtr, CfgPtr->BaseAddress); if
(Status != XST_SUCCESS) { return
XST_FAILURE; } /* Setup the interrupt system */ Status = SetupIntrSystem(IntcInstancePtr, InstancePtr, IntrId); if
(Status != XST_SUCCESS) { return
XST_FAILURE; } /* Enable all (completion/error/delay) interrupts */ XAxiCdma_IntrEnable(InstancePtr, XAXICDMA_XR_IRQ_ALL_MASK); for
(Index = 0; Index < Tries; Index++) { Status = CDMATransfer(InstancePtr, BUFFER_BYTESIZE, SubmitTries); if (Status != XST_SUCCESS) { DisableIntrSystem(IntcInstancePtr, IntrId); return
XST_FAILURE; } } /* Test finishes successfully, clean up and return */ DisableIntrSystem(IntcInstancePtr, IntrId); return
XST_SUCCESS; } } /*****************************************************************************/ /* * * This function does CDMA transfer * * @param InstancePtr is a pointer to the XAxiCdma instance * @param Length is the transfer length * @param Retries is how many times to retry on submission * * @return * - XST_SUCCESS if transfer is successful * - XST_FAILURE if either the transfer fails or the data has * error * * @note None * ******************************************************************************/ static
int CDMATransfer(XAxiCdma *InstancePtr, int
Length, int
Retries) { int
Status; Done = 0; Error = 0; printf ( "Start Transfer \n\r" ); /* Try to start the DMA transfer */ Done = 0; Error = 0; /* Flush the SrcBuffer before the DMA transfer, in case the Data Cache * is enabled */ Xil_DCacheFlushRange((u32)SourceAddr, Length); Status = XAxiCdma_SimpleTransfer(InstancePtr, (u32)(u8 *) (SourceAddr ), (u32)(DestAddr), Length, Cdma_CallBack, ( void
*)InstancePtr); if
(Status == XST_FAILURE) { printf ( "Error in Transfer \n\r" ); return
1; } /* Wait until the DMA transfer is done */ while
(!Done && !Error) { /* Wait */ } if
(Error) { return
XST_FAILURE; return
1; } /* Invalidate the DestBuffer before receiving the data, in case the * Data Cache is enabled */ Xil_DCacheInvalidateRange((u32)DestAddr, Length); return
XST_SUCCESS; } int
main() { int
Status; u32 *SrcPtr; u32 *DestPtr; u32 Index; int
i, j; printf ( "\r\n--- Entering main() --- \r\n" ); /********************************************************************************* Step : 1 : Intialization of the SOurce Memory with the Specified test pattern Clear Destination memory **********************************************************************************/ TestPattern_Initialization(); /* Initialize the source buffer bytes with a pattern and the * the destination buffer bytes to zero */ SrcPtr = (u32*)SourceAddr; DestPtr = (u32 *)DestAddr; for
(Index = 0; Index < (BUFFER_BYTESIZE/1024); Index++) { MULT_SHIFT_LOOP((Index*100)); for
(i = 0; i < 32; i++) { for
(j = 0; j < 16; j++) { SrcPtr[((i+j))*(Index+1)] = Array_3[i][j]; SrcPtr[((i+j)*(Index+1)) + 1] = Array_4[i][j]; DestPtr[(i+j)*(Index+1)] = 0; DestPtr[((i+j)*(Index+1)) + 1] = 0; } } } /********************************************************************************* Step : 2 : AXI CDMA Intialization Association of the CDMA ISR with the Interrupt Enable the CDMA Interrupt Provide Source and destination location to CDMA Specified Number of byte to be transfer to CDMA register Start the CDMA Wait for the Interrupt and return the status **********************************************************************************/ Status = XAxiCdma_Interrupt( &IntcController, &AxiCdmaInstance, DMA_CTRL_DEVICE_ID, DMA_CTRL_IRPT_INTR ); if
(Status != XST_SUCCESS) { printf ( "XAxiCdma_Interrupt: Failed\r\n" ); return
XST_FAILURE; } xil_printf( "XAxiCdma_Interrupt: Passed\r\n" ); /********************************************************************************* Step : 3 : Compare Source memory with Destination memory Return the Status **********************************************************************************/ for
(Index = 0; Index < (BUFFER_BYTESIZE/4); Index++) { if
( DestPtr[Index] != SrcPtr[Index]) { printf ( "Error in Comparison : Index : %x \n\r" , Index); return
XST_FAILURE; } } printf ( "DMA Transfer is Successful \n\r" ); return
XST_SUCCESS; return
0; } |
驱动程序代码(未完成,有错误待修改):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289 |
#include <linux/module.h> #include <linux/version.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/delay.h> #include <linux/spinlock.h> #include <linux/device.h> #include <linux/types.h> #include <linux/ioctl.h> #include <asm/io.h> #include <asm/uaccess.h> #include <asm/atomic.h> #include <linux/wait.h> #include <linux/cdev.h> #include <linux/interrupt.h> #include <asm/signal.h> #include <linux/gpio.h> #include <linux/irq.h> #include <linux/mm.h> #include <asm/page.h> #include <asm/dma.h> #define DEVICE_NAME "dma_dev" #define IRQ_MASK 0x00007000 #define IRQ_DEVICE_ID 0 #define NUMBER_OF_TRANSFERS 2 #define DMA_CTRL_DEVICE_ID 0 #define INTC_DEVICE_ID 0 #define DMA_CTRL_IRPT_INTR 91 #define MEMORY_BASE 0x01000000 #define CDMA_BASEADDR 0x80200000 #define XAXICDMA_BTT_OFFSET 0x00000028 #define XAXICDMA_SRCADDR_OFFSET 0x00000018 #define XAXICDMA_DSTADDR_OFFSET 0x00000020 #define HP0_BASEADDR 0x10000000 #define HP2_BASEADDR 0x18000000 #define XPAR_AXI_CDMA_0_M_AXI_DATA_WIDTH 64 #define XPAR_AXI_CDMA_0_M_AXI_MAX_BURST_LEN 256 static
u32 SourceAddr = HP0_BASEADDR; // =0x10000000 static
u32 DestAddr = HP2_BASEADDR; // = 0x18000000 static
int Array_3[32][16]; //阵列 static
int Array_4[32][16]; static
int Array_1[32][16]; static
int Array_2[32][16]; int
const input[16] = {0xb504f33, 0xabeb4a0, 0xa267994, 0x987fbfc, 0x8e39d9c, 0x839c3cc, 0x78ad74c, 0x6d743f4, 0x61f78a8, 0x563e6a8, 0x4a5018c, 0x3e33f2c, 0x31f1704, 0x259020c, 0x1917a64, 0xc8fb2c}; /* Length of the buffers for DMA transfer */ static
u32 BUFFER_BYTESIZE = (XPAR_AXI_CDMA_0_M_AXI_DATA_WIDTH * XPAR_AXI_CDMA_0_M_AXI_MAX_BURST_LEN); //大小为64*256/8=2KB,起始就是我们在XPS中设置好的 static
unsigned long
dma_addr = 0; static
unsigned long
src_addr = 0; static
unsigned long
dest_addr = 0; static
unsigned long
mem_addr = 0; static
struct class * dma_class = NULL; static
struct device* dma_device = NULL; static
int dma_major = 0; typedef
struct { dev_t dev_no; u32 IsReady; int
InterruptPresent; u32 BaseAddress; // spinlock_t lock; atomic_t lock; } KEY_DEV; static
KEY_DEV keydev; /************** start data generation func **************/ //Multiply and Shift int
MUL_SHIFT_30( int
x, int
y) //实现x*y,但又怕溢出,所以右移30位,除以2^30~1e9 { return
(( int ) ((( long
long ) (x) * (y)) >> 30)); } void
MULT_SHIFT_LOOP( int
Value ) //生成源数据的函数 { int
i, j; for
(i = 0; i < 32; i++) { for
(j = 0; j < 16; j++) { Array_3[i][j] = ( int )((MUL_SHIFT_30(input[j],Array_1[j][i])) + Value); Array_4[i][j] = ( int )((MUL_SHIFT_30(input[j],Array_2[j][i])) + Value); } } } void
TestPattern_Initialization( void ) //生成原始数据 { printk( "begin testPattern\n" ); int
i, j; for
(i = 0; i < 32; i++) { for
(j = 0; j < 16; j++) { Array_1[i][j] = ( int
) ((0xA5A5A5A5 >> 1) * i ); Array_2[i][j] = ( int
) ((0xA5A5A5A5 << 1) * i ); } } printk( "finish testPattern\n" ); } /********finish test data generation func ************/ static
void InterruptClear() { u32 val; val = ioread32(dma_addr); iowrite32(val & IRQ_MASK,dma_addr); printk( "int cleared" ); } static
irqreturn_t dma_interrupt( int
irq, void
*dev_id, struct
pt_regs *regs) { u32 IrqMask = 0x0; u32 status = 0xff; status = ioread32(dma_addr+0x00000004); printk( "irq status = 0x%x\n" ,status); IrqMask = status & 0x00007000; if
(IrqMask & 0x00004000) { printk( "\r\n--- Transfer Error --- \r\n" ); //传输出错 } if
(IrqMask & 0x00001000) { printk( "\r\n--- Transfer Done --- \r\n" ); //传输成功 } InterruptClear(); return
0; } static
void InterruptEnable() { printk( "in InterruptEnable" ); u32 val; val = ioread32(dma_addr); iowrite32(val | IRQ_MASK,dma_addr); } static
int transfer() { printk( "start transfer" ); iowrite32(SourceAddr,dma_addr+XAXICDMA_SRCADDR_OFFSET); iowrite32(DestAddr,dma_addr+XAXICDMA_DSTADDR_OFFSET); iowrite32(Length,dma_addr+XAXICDMA_BTT_OFFSET); } static
int dma_open( struct
inode *inode, struct
file *filp) { int
ret; int
Status; u32 *SrcPtr; u32 *DestPtr; u32 Index; int
i, j; printk( "open! just standalone‘s main\n" ); /**************************************************** Step : 1 : Intialization of the SOurce Memory with the Specified test pattern Clear Destination memory *****************************************************/ TestPattern_Initialization(); SrcPtr = (u32*)SourceAddr; DestPtr = (u32 *)DestAddr; for
(Index = 0; Index < (BUFFER_BYTESIZE/1024); Index++) { MULT_SHIFT_LOOP((Index*100)); for
(i = 0; i < 32; i++) { for
(j = 0; j < 16; j++) { iowrite32(Array_3[i][j],src_addr+((i+j)*(Index+1))* sizeof ( int )); iowrite32(Array_4[i][j],src_addr+(((i+j)*(Index+1))+1)* sizeof ( int )); iowrite32(0,dest_addr+((i+j)*(Index+1))* sizeof ( int )); iowrite32(0,dest_addr+(((i+j)*(Index+1))+1)* sizeof ( int )); } } } printk( "step1 finished!\n" ); /************************************************************************** Step : 2 : AXI CDMA Intialization Association of the CDMA ISR with the Interrupt Enable the CDMA Interrupt Provide Source and destination location to CDMA transfer() Specified Number of byte to be transfer to CDMA register transfer() Start the CDMA transfer() Wait for the Interrupt and return the status ***************************************************************************/ InterruptEnable(); printk( "interrupt Enabled!\n" ); ret = request_irq(DMA_CTRL_IRPT_INTR, dma_interrupt,IRQF_TRIGGER_RISING, DEVICE_NAME, &keydev); if (ret) { printk( "could not register interrupt!" ); return
ret; } printk( "register interrupt success!\n" ); //start data transfer transfer(BUFFER_BYTESIZE); printk( "start transfer!\n" ); return
0; } static
struct file_operations dma_fops = { .owner = THIS_MODULE, .open = dma_open, }; static
int __init cdma_init( void ) { int
ret; ret = register_chrdev(0,DEVICE_NAME, &dma_fops); if (ret < 0) { printk( "gpio: can‘t get major number\n" ); return
ret; } dma_major = ret; dma_class = class_create(THIS_MODULE, "dma_class" ); if (IS_ERR(dma_class)) { printk( "dma: failed in creating class\n" ); unregister_chrdev(dma_major, DEVICE_NAME); return
-1; } dma_device = device_create(dma_class,NULL,MKDEV(dma_major,0),NULL,DEVICE_NAME); if (IS_ERR(dma_device)) { printk( "dma: failed in creating device!\n" ); unregister_chrdev(dma_major, DEVICE_NAME); class_unregister(dma_class); class_destroy(dma_class); return
-1; } dma_addr = (unsigned long ) ioremap(CDMA_BASEADDR, sizeof (u32)); //mem_addr = (unsigned long) ioremap(MEMORY_BASE, sizeof(u32)); dest_addr = (unsigned long )bus_to_virt(HP2_BASEADDR); src_addr = (unsigned long )bus_to_virt(HP0_BASEADDR); //src_addr = (unsigned long) ioremap(HP0_BASEADDR, sizeof(u32)); //dest_addr = (unsigned long) ioremap(HP2_BASEADDR, sizeof(u32)); printk( "dma_addr=%lx,src_addr=%lx,dest_addr=%lx\n" ,dma_addr,src_addr/dest_addr); printk( "dma installed successfully!\n" ); return
0; } static
void __exit cdma_exit( void ) { /* iowrite32(0x00,led_addr); mdelay(100); iowrite32(0xff,led_addr); */ device_destroy(dma_class,MKDEV(dma_major, 0)); class_unregister(dma_class); class_destroy(dma_class); unregister_chrdev(dma_major,DEVICE_NAME); printk( "dma module exit!" ); } module_init(cdma_init); module_exit(cdma_exit); MODULE_AUTHOR( "seg" ); MODULE_LICENSE( "GPL" ); |
finish
标签:des c style class blog code
原文地址:http://www.cnblogs.com/shenerguang/p/3760012.html