- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I've been searching the forums for a few examples on how to stream ADC data to DDR2 for awhile now and finally think i've built a system that correctly does this. Im just looking for some validation of my design:
1) I've made my ADC interface into an Avalon-ST interface. The ADC is 14bits wide and samples at a rate of 125MSPS. 2) Avalon Clock is set to 125MSPS. 3) ADC, Avalon-ST gets sent to an SGDMA. 4) For now I have the SGDMA sending the samples into onboard ram, eventually I'd make that the DDR2 stick that comes with my board. Anway, SOPC/NIOS is totally new to me at this level. I've done simple things but nothing this complex. Does this sound like a legit way of doing things? It should be pretty simple to just read off the on-board ram that is holding the samples. Previously, when I would interact through the PIO interface, it was easy via: IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE,0x00000011); But using the SGDMA, im a little confused on how to use descriptors, etc. Also, what happens when the onboard ram is full? Is there a write_full signal or should a stick a fifo somewhere? ThanksLink Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You should read the datasheet of sgdma core first. No, there's no full signal as You can transfer only up to 65.5kb of data per descriptor, so You can do the math how many descriptors You'll need to fill the memory. Also remember, that 125MHz Nios system won't be able to work with all the data, as some of Your commands will take more than one cpu instruction.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for the info Socrates. I've come a long way in the past few days using some example code that you or BadOmen posted. Im still a little hazy on my SOPC/ADC driver design though. Attached is a Jpeg and the driver VHDL code.
Lastly, like I mentioned above, I modified the C code that you or BadOmen posted in another thread to read off the onboard ram once it is filled by the ADC and print to the screen via stdout. Unfortunately, it is only printing addresses even though I am de-referencing the memory address pointer. If you could, can you take a look at the following and attached code? Im not sure what I am doing wrong, but I think I'm pretty close. Thanks Matt#include "io.h"# include "stdio.h"# include "stdlib.h"# include "system.h"# include "alt_types.h"# include "altera_avalon_sgdma.h"# include "altera_avalon_sgdma_regs.h"# include <sys/alt_cache.h># include <sys/stdio.h># include <math.h>
# define NUMBER_OF_BUFFERS 10 /* each direction so double this for the total */# define MINIMUM_BUFFER_LENGTH 50# define MAXIMUM_BUFFER_LENGTH 1500 /* set this to the same value as the min for a fixed size, also don't exceed 65535 */
volatile alt_u8 rx_done = 0;
alt_sgdma_dev *DEVICE;
alt_sgdma_descriptor *dma_descriptors, *dma_descriptors_copy;
void dma_interrupt(void * context) {
rx_done=1; /* main will be polling for this value being 1 */
}
alt_u8 allocate_descriptors(alt_sgdma_descriptor **dma_descriptors,
alt_sgdma_descriptor **dma_descriptors_copy,
alt_u32 num_buffers)
{
void *temp_pointer;
temp_pointer = malloc((num_buffers + 2) * ALTERA_AVALON_SGDMA_DESCRIPTOR_SIZE);
if(temp_pointer==NULL) return 1;
*dma_descriptors_copy = (alt_sgdma_descriptor *)temp_pointer;
while((((alt_u32)temp_pointer) % ALTERA_AVALON_SGDMA_DESCRIPTOR_SIZE) != 0) temp_pointer++; // Limit size @ 32 bytes
*dma_descriptors = (alt_sgdma_descriptor *)temp_pointer;
dma_descriptors->control = 0; // Set IE_ERROR=0 bit in control register
return 0;
}
alt_u8 allocate_dma_buffers(alt_sgdma_descriptor *dma_descriptors, alt_u32 num_buffers) {
alt_u32 i, length = 0;
alt_u32 *data_pointer;
for(i=0; i<num_buffers; i++){
length = MINIMUM_BUFFER_LENGTH;
data_pointer = (alt_u32 *)malloc(length);
if(data_pointer == NULL) return 1;
alt_avalon_sgdma_construct_stream_to_mem_desc(&dma_descriptors, // descriptor
&dma_descriptors, // next descriptor
data_pointer, // write buffer location
MINIMUM_BUFFER_LENGTH, //(alt_u16)length, // I will wait for End Of Packet instead of fixed length
0); // writes are not to a fixed location
}
alt_dcache_flush_all();
return 0;
}
/* Making sure that there will be enough space for code (maximum of 1.5MB) */
int main(){
alt_putstr("Here");
alt_u8 returned = 0;
DEVICE = alt_avalon_sgdma_open("/dev/sgdma_0");
if(DEVICE == NULL)
{
alt_putstr("Could Not Find SGDMA Device");
return 1;
}
else
{
alt_putstr("Found SGDMA Device");
}
IOWR_ALTERA_AVALON_SGDMA_CONTROL(DEVICE->base,ALTERA_AVALON_SGDMA_CONTROL_SOFTWARERESET_MSK); // Reset SGDMA
IOWR_ALTERA_AVALON_SGDMA_CONTROL(DEVICE->base,0x0);
IOWR_ALTERA_AVALON_SGDMA_CONTROL(DEVICE->base, ALTERA_AVALON_SGDMA_CONTROL_PARK_MSK); // change park
returned = allocate_descriptors(&dma_descriptors, &dma_descriptors_copy, NUMBER_OF_BUFFERS);
if(returned) alt_putstr("### ERROR: Failed to allocate memory for descriptors!\n");
returned = allocate_dma_buffers(dma_descriptors,NUMBER_OF_BUFFERS); // Allocate data buffers and construct descriptors
if(returned) alt_putstr("### ERROR: Failed to allocate memory for data receive!\n");
alt_avalon_sgdma_register_callback(DEVICE, &dma_interrupt,
(ALTERA_AVALON_SGDMA_CONTROL_IE_GLOBAL_MSK | ALTERA_AVALON_SGDMA_CONTROL_IE_CHAIN_COMPLETED_MSK),
NULL);
//printf("%d", sizeof(alt_sgdma_descriptor));
// last descriptor needs to point to the first
dma_descriptors.next = (alt_sgdma_descriptor *)dma_descriptors;
printf("descriptor address: %d \n", dma_descriptors);
printf("final descriptor next: %d \n", dma_descriptors.next);
if(alt_avalon_sgdma_do_async_transfer(DEVICE, &dma_descriptors) != 0)
alt_putstr("FAIL! (Writing the head of the descriptor list to the DMA failed)\n");
int i = 0;
int j = 0;
for( i = 0; i < 10; i++)
{
if(alt_avalon_sgdma_do_async_transfer(DEVICE, &dma_descriptors) != 0)
alt_putstr("FAIL! (Writing the head of the descriptor list to the DMA failed)\n");
usleep(5000);
int k = 0;
/// problem area
for(j = 0; j < NUMBER_OF_BUFFERS; j++)
{
printf("%d ", IORD_32DIRECT((&dma_descriptors.write_addr),0));
//alt_putstr(&dma_descriptors.write_addr);
dma_descriptors.control = dma_descriptors.control | ALTERA_AVALON_SGDMA_DESCRIPTOR_CONTROL_OWNED_BY_HW_MSK;
}
// int k = 0;
// for(k = 0; k < NUMBER_OF_BUFFERS; k ++)
// {
// dma_descriptors.control = dma_descriptors.control | 0b10000001;
// }
}
//
// alt_putstr(">>> Starting SGDMA transfers... \n");
//
// if(alt_avalon_sgdma_do_async_transfer(DEVICE, &dma_descriptors) != 0)
// alt_putstr("FAIL! (Writing the head of the descriptor list to the DMA failed)\n");
//
//// while(rx_done == 0) {
//// alt_putstr("Something\n");
//// usleep(5000);
//// }
//
//
// usleep(500000);
//
// //alt_putstr(">>> The SGDMA transfer has completed, Done = %u\n",(unsigned int)rx_done);
//
//
//
//
//
// alt_avalon_sgdma_stop(DEVICE);
// //free(dma_descriptors_copy);
// //free(dma_descriptors);
//
// // do stuff to transfer the data off
//
// alt_putstr(" dumping data ");
// alt_u32 *data_pointer;
// int i = 0;
// for(i = 0; i < NUMBER_OF_BUFFERS; i++)
// {
// data_pointer = dma_descriptors.write_addr;
// alt_putstr(&data_pointer);
// }
//free(dma_descriptors_copy);
//free(dma_descriptors);
//alt_putstr("Working...\n");
return 0;
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, mwb500 :
Now the same issue confused me. How about your ADC avalon interface ?- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Do a proper debug.
Are You sure data is written to the memory? I see that You use malloc(), so it places data to .heap. I'd offer to change address to particular place in on-chip ram, so You can use in-system memory content editor and check what data has been copied. I'd also offer to do debug inside dma_interrupt(), so You'll be sure it has occoured.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page