|
|
  |
Nios + DDR3, Пробую управлять DDR3 HPC из Niosа |
|
|
|
Nov 29 2011, 12:11
|
Местный
  
Группа: Свой
Сообщений: 247
Регистрация: 4-10-10
Из: г. Екатеринбург
Пользователь №: 59 925

|
Собрал в SOPCе набор компонентов, подключил к проекту в Квартусе9.1, а как теперь читать/писать в DDR-ину не знаю. В Инете нашел как это делают с DDR2, но тама зачем-то цепляют DMA, а мне бы хотелось так попробовать, без DMA, и еще в том примере ширина локальной шины интерфейса DDR2 = 32, а у меня 64.
Расскажите, кто как делал, плз.
ПС: постарайтесь без "понтов", пожалуйста, т.к. я в этом Ниосе мало понимаю.
Сообщение отредактировал billidean - Nov 29 2011, 12:11
|
|
|
|
|
Dec 1 2011, 02:43
|
Местный
  
Группа: Свой
Сообщений: 247
Регистрация: 4-10-10
Из: г. Екатеринбург
Пользователь №: 59 925

|
Создал следующий проект: SOPC: пробовал два варианта (из примера для DDR2):
 РЈРСеньшено Р Т‘Р С• 83%
1017 x 444 (35.69 килобайт)
|
и
 РЈРСеньшено Р Т‘Р С• 83%
1017 x 444 (36.63 килобайт)
|
подключил полученный компонент в проект квартуса, подцепил все внешние ноги. Создал проект в Ниосе, с-код (на основе примера): Код #include "count_binary.h"
static volatile int rx_done = 0;
static void dma_done (void* handle, void* data) { rx_done++; }
static void set_leds(alt_u8 data) { alt_u8 b = data; /* Logic to make the LEDs count from right-to-left, LSB on the right. */ IOWR_ALTERA_AVALON_PIO_DATA( PIO_BASE, ((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16 ); }
int main(void) { alt_u64 w; alt_u64 r;
int rc; int pattern, offset; alt_dma_txchan txchan; alt_dma_rxchan rxchan; void* data_written; void* data_read;
int compare;
/* Get a couple buffers for the test */ data_written = (void*)alt_uncached_malloc(0x1000); data_read = (void*)alt_uncached_malloc(0x1000);
set_leds(0x0f); usleep(100000); set_leds(0xf0); printf("leds ok...\n");
w = 0xf0f0f0f0; IOWR(DMA_WRITE_MASTER_ALTMEMDDR_BASE,0,w); r = IORD(DMA_READ_MASTER_ALTMEMDDR_BASE,0); printf("%x\n",r);
/* Fill write buffer with known values */ for (pattern = 1, offset = 0; offset < 0x1000; pattern++, offset+=4) { IOWR_32DIRECT((int)data_written, offset, pattern); }
/* Create the transmit channel */ if ((txchan = alt_dma_txchan_open("/dev/dma")) == NULL) { printf ("Failed to open transmit channel\n"); exit (1); }
/* Create the receive channel */ if ((rxchan = alt_dma_rxchan_open("/dev/dma")) == NULL) { printf ("Failed to open receive channel\n"); exit (1); }
//-------------------------------------------- /* Use DMA to transfer from write buffer to memory under test */ /* Post the transmit request */ if ((rc = alt_dma_txchan_send(txchan, data_written, 0x1000, NULL, NULL)) < 0) { printf ("Failed to post transmit request, reason = %i\n", rc); exit (1); }
/* Post the receive request */ if ((rc = alt_dma_rxchan_prepare(rxchan, (void*)DMA_WRITE_MASTER_ALTMEMDDR_BASE, 0x1000, dma_done, NULL)) < 0) { printf ("Failed to post read request, reason = %i\n", rc); exit (1); }
/* Wait for transfer to complete */ printf("wait rx_done...\n"); while (!rx_done); printf("rx_done is here\n"); rx_done = 0;
/* Clear the read buffer before we fill it */ memset(data_read, 0, 0x1000);
/* Use DMA to read data back into read buffer from memory under test */ /* Post the transmit request */ if ((rc = alt_dma_txchan_send(txchan, (void*)DMA_READ_MASTER_ALTMEMDDR_BASE, 0x1000, NULL, NULL)) < 0) { printf ("Failed to post transmit request, reason = %i\n", rc); exit (1); }
/* Post the receive request */ if ((rc = alt_dma_rxchan_prepare(rxchan, data_read, 0x1000, dma_done, NULL)) < 0) { printf ("Failed to post read request, reason = %i\n", rc); exit (1); }
/* Wait for transfer to complete */ printf("wait rx_done...\n"); while (!rx_done); printf("rx_done is here\n"); rx_done = 0;
compare = memcmp(data_written, data_read, 0x1000);
printf("compare = %i\n",compare); //--------------------------------------------
alt_uncached_free(data_written); alt_uncached_free(data_read);
return 0; } После запуска проекта на кристалле (StratixIV GX) в консоли печатается следующее: leds ok... (это просто моргание лампочками для визуализации начала работы) ffffffff (это результат выполнения printf("%x\n",r);) wait rx_done... (после выполнения первого alt_dma_rxchan_prepare(...)) - на этом всё заканчивается. Подключил СигналТап и получаю картинку:
 РЈРСеньшено Р Т‘Р С• 84%
1045 x 478 (23.9 килобайт)
|
на которой видно, что адрес=0, local_size почему-то =1(??), а данные тоже = 0. Подскажите, что я делаю не так? Ну и просто можно прокомментировать получившийся проект.
Сообщение отредактировал billidean - Dec 1 2011, 05:38
|
|
|
|
|
Dec 5 2011, 14:57
|
Местный
  
Группа: Свой
Сообщений: 247
Регистрация: 4-10-10
Из: г. Екатеринбург
Пользователь №: 59 925

|
Цитата(vadimuzzz @ Nov 29 2011, 16:33)  можно через указатели, можно через IORD/IOWR как я привел в примере, IORD/IOWR - результата не приносит. после чтения получаю 0xfff... Цитата(vadimuzzz @ Nov 29 2011, 16:33)  это мне ничего нового не сообщило И вообще, я прошу помощи у тех, кто так же пробовал, маялся, и парил Инет в поисках работающего варианта. Если кто не юзал данной связки: "DDR3+NiosII", то и незачем комменты левые оставлять, а если работал, то зажимать ответ стремно
|
|
|
|
|
Dec 6 2011, 03:17
|

Гуру
     
Группа: Свой
Сообщений: 2 291
Регистрация: 21-07-05
Пользователь №: 6 988

|
Цитата(billidean @ Dec 5 2011, 21:57)  как я привел в примере, IORD/IOWR - результата не приносит. после чтения получаю 0xfff... вы привели ерунду. писать/читать надо по адресу в памяти (см. в system.h), а не в мастер-порт контроллера DMA. это первичная проверка. если не работает - нет смысла пробовать DMA. ищите ошибки в назначении пинов или кривых констрейнах Цитата это мне ничего нового не сообщило И вообще, я прошу помощи у тех, кто так же пробовал, маялся, и парил Инет в поисках работающего варианта. Если кто не юзал данной связки: "DDR3+NiosII", то и незачем комменты левые оставлять, а если работал, то зажимать ответ стремно  это вам должно было сообщить, как нужно задавать вопрос, чтобы получить ответ. ваш вопрос звучал так: "я не знаю, что такое ниос и ддр, документацию не читаю, но у меня не работает".
|
|
|
|
|
Dec 7 2011, 03:36
|
Местный
  
Группа: Свой
Сообщений: 247
Регистрация: 4-10-10
Из: г. Екатеринбург
Пользователь №: 59 925

|
Приветствую всех в очередной раз. Доработал свою систему до следующего состояния: SOPC:
 РЈРСеньшено Р Т‘Р С• 68%
992 x 505 (41.55 килобайт)
|
NiosII: Код static volatile int rx_done = 0;
static void dma_done (void* handle, void* data) { rx_done = 1; }
int main(void) { int rc; int pattern, offset; alt_dma_txchan txchan; alt_dma_rxchan rxchan; void* data_written; void* data_read;
int i;
//выделяю памяти [32 байт] = [8*64-битных слова] data_written = (void*)alt_remap_uncached(DMA_WRITE_MASTER_ALTMEMDDR_BASE,0x20); data_read = (void*)alt_remap_uncached(DMA_READ_MASTER_ALTMEMDDR_BASE,0x20);
if( data_written == NULL ) printf("data_written is NULL\n"); if( data_read == NULL ) printf("data_read is NULL\n");
// дергаю лампочками для визуализации начала работы set_leds(0x0f); usleep(100000); set_leds(0xf0); printf("leds ok...\n");
//----------------------------------- // эта часть кода бессмысленна!!, т.к. никакой записи не происходит!! for (pattern = 0x0000000f, offset = 0; offset < 0x20; offset+=8) { IOWR((int)data_written, offset, (alt_u64)pattern); } printf("data_written MEM inited by:\n"); for (i=0;i<0x20;i+=8) { printf("[DDR3]addr %d:\tdata: 0x%2x\n",i,IORD((int)data_written,i)); } //-----------------------------------
if ((txchan = alt_dma_txchan_open("/dev/dma")) == NULL) { printf ("Failed to open transmit channel\n"); exit (1); } if ((rxchan = alt_dma_rxchan_open("/dev/dma")) == NULL) { printf ("Failed to open receive channel\n"); exit (1); }
if(alt_dma_txchan_ioctl(txchan, ALT_DMA_SET_MODE_64, NULL)<0) printf("NO (txchan, ALT_DMA_SET_MODE_64)\n"); else printf("OK (txchan, ALT_DMA_SET_MODE_64)\n");
if(alt_dma_rxchan_ioctl(rxchan,ALT_DMA_SET_MODE_64,NULL)<0) printf("NO (rxchan,ALT_DMA_SET_MODE_64)\n"); else printf("OK (rxchan,ALT_DMA_SET_MODE_64)\n");
if(alt_dma_txchan_ioctl(txchan,ALT_DMA_TX_ONLY_ON,data_written)<0) printf("NO (txchan,ALT_DMA_TX_ONLY_ON)\n"); else printf("OK (txchan,ALT_DMA_TX_ONLY_ON)\n");
if ((rc = alt_dma_txchan_send(txchan, data_written, 0x20, NULL, NULL)) < 0) { printf ("Failed to post transmit request, reason = %i\n", rc); exit (1); } if(alt_dma_txchan_ioctl(txchan,ALT_DMA_TX_ONLY_OFF,NULL)<0) printf("NO (txchan,ALT_DMA_TX_ONLY_OFF)\n"); else printf("OK (txchan,ALT_DMA_TX_ONLY_OFF)\n");
if(alt_dma_rxchan_ioctl(rxchan,ALT_DMA_RX_ONLY_ON,data_read)<0) printf("NO (rxchan,ALT_DMA_RX_ONLY_ON)\n"); else printf("OK (rxchan,ALT_DMA_RX_ONLY_ON)\n");
if ((rc = alt_dma_rxchan_prepare(rxchan, data_read, 0x20, dma_done, NULL)) < 0) { printf ("Failed to post read request, reason = %i\n", rc); exit (1); } if(alt_dma_rxchan_ioctl(rxchan,ALT_DMA_RX_ONLY_OFF,NULL)<0) printf("NO (rxchan,ALT_DMA_RX_ONLY_OFF)\n"); else printf("OK (rxchan,ALT_DMA_RX_ONLY_OFF)\n");
/* Wait for transfer to complete */ printf("wait rx_done...\n"); while (!rx_done); printf("rx_done is here\n"); rx_done = 0;
printf("data_read MEM:\n"); for (i=0;i<0x20;i+=8) { printf("addr %d:\tdata: 0x%2x\n",i,IORD((int)data_read,i)); }
alt_uncached_free(data_written); alt_uncached_free(data_read);
return 0; } Все это я нарыл на разных форумах. В "system.h" у меня есть только DMA_WRITE_MASTER_ALTMEMDDR_BASE адрес, он равен адресу DMA_READ_MASTER_ALTMEMDDR_BASE, но нет адреса ALTMEMDDR_BASE, поэтому я пытаюсь писать только по этому адресу. при этом получаю такую катрину на SignalTap'e:
 РЈРСеньшено Р Т‘Р С• 79%
1502 x 271 (24.19 килобайт)
|
Получается, что вычитывается из DDR-ины, то затем и записывается. Подскажите, пожалуйста: 1. почему на диаграмме получается так, что сначала начинается процесс чтения, а затем уже процесс записи данных? 2. почему при попытке убрать из кода одну из функций alt_dma_txchan_send или alt_dma_rxchan_prepare не происходит послыки запросов в DDR3-контроллер ни на запись ни на чтение? 3. как записать какие-то конкретные данные в область памяти DDR-ины??? p.s.: я работал с DDR3, но только в Квартусе, на VHDL, но не используя Ниос, поэтому я знаю как должна выглядеть нормальная циклограмма запросов на DDR3-контроллер, но как все это сделать на Ниосе и с применением DMA, для меня ново.
Сообщение отредактировал billidean - Dec 7 2011, 03:47
|
|
|
|
|
Dec 7 2011, 06:25
|

Гуру
     
Группа: Свой
Сообщений: 2 291
Регистрация: 21-07-05
Пользователь №: 6 988

|
Цитата В "system.h" у меня есть только DMA_WRITE_MASTER_ALTMEMDDR_BASE адрес, он равен адресу DMA_READ_MASTER_ALTMEMDDR_BASE, но нет адреса ALTMEMDDR_BASE, поэтому я пытаюсь писать только по этому адресу. его (ALTMEMDDR_BASE) там нет, т.к. вы не подключили память к мастер портам процессора. первые 2 адреса - это адреса мастер-портов, в них нельзя писать, они сами пишут/читают. зачем вы все в одну кучу свалили? DMA не имеет никакого отношения к DDR, это один из способов разгрузить процессор при обмене с памятью. я уже вам писал - проверьте с IOWR/IORD. когда увидите нормальные транзакции (в сигналтапе, например), тогда уже и решайте - надо вам DMA (SGDMA) или нет. если надо - читаете Software Developer's Handbook, Section 14 (HAL API) описание функций alt_dma*. попутно посмотрите в ug_embedded.pdf что из себя представляют контроллеры DMA. ну и попутно - как устроена шина Avalon
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|