- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I'm playing with a design in order to test the highest throughput from the FPGA to the SDRAM. Here you can have my design explained: http://www.alteraforum.com/forum/showthread.php?t=45290 Basically: 1. I've set the F2S SDRAM Bridge data to 64 bits WIDTH and write only, avalon-mm 2. I've added a SPAN EXTENDER, then i set the DATA PATH WIDTH to 64 bits and the ADDRESS WIDTH of the master to 32 bits (4 giga) and a default subwindow of 512kb 3. I've added an ALTERA DMA Controller and the WIDTH of the DMA LENGTH REGISTER is set to 32 bits 4. I've connected the DMA write master to the windowed slave on the SPAN EXTENDER 5. I've connected the expanded master to F2H_DATA The question is how to properly configure the DMA in Linux. I've already read Documentation/DMA-API.txt and Documentation/DMA-API-HOWTO.txt, but it is not clear how to use those set of functions. I've made a Concept test device driver that allocate a buffer with this command: vbuffer = dma_alloc_coherent(acq.dev, BUFFER_SIZE, &pbuffer, GFP_ATOMIC | GFP_DMA); Then I write the paddr to the DMA (actualy to the address_span_extender and the DMA ip), and send the GO command to the dma. When the interrupt from the DMA arrive, I clear the DMA IRQ and do a dma_sync_single_for_cpu(acq.dev, pbuffer, BUFFER_SIZE, DMA_FROM_DEVICE); After that, i release the read fop; Is this the correct use of the DMA api for this case??? It seems to work (MAGIC_STRING is being transferred). But I'm afraid I'm missing something. Bellow there is a piece of code used for this test: static irqreturn_t dma_isr (int irq, void *dev_id) { acq.dma_ready = 1; writel(CLEAR_DMA_IRQ, acq.dma + DMA_STATUS); dma_sync_single_for_cpu(acq.dev, pbuffer, BUFFER_SIZE, DMA_FROM_DEVICE); wake_up_interruptible(&dma_irq_wait); return IRQ_HANDLED; } static ssize_t acq_read(struct file *filp, char __user *buff, size_t count, loff_t *offp) { int num_reads; u64 jiffies_before, jiffies_after; char str[100]; int len; writel(pbuffer, acq.span_extender + ADDR_SPAN_EXT_BASE); jiffies_before = jiffies; for (num_reads = 0; num_reads < 100000; num_reads++) { acq.dma_ready = 0; writel(0, acq.dma + DMA_DEST_ADDR); writel(0, acq.dma + DMA_SOURCE_ADDR); writel(BUFFER_SIZE, acq.dma + DMA_LENGTH); writel(DMA_GO_CMD, acq.dma + DMA_CONTROL); if (wait_event_interruptible(dma_irq_wait, acq.dma_ready)) { return -ERESTARTSYS; } } jiffies_after = jiffies; len = sprintf(str, "jiffies / HZ = %lld / %d VBUFFER_MAGIG_STRING:%s\n", jiffies_after - jiffies_before, HZ,vbuffer); return simple_read_from_buffer(buff, count, offp, str, len); } Thank you, regards. BTW I'm using Linux 3.9 and quartus 13.1Link Copied
0 Replies
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page