Перейти к содержанию
    

Nios + DDR3

Собрал в SOPCе набор компонентов, подключил к проекту в Квартусе9.1, а как теперь читать/писать в DDR-ину не знаю.

В Инете нашел как это делают с DDR2, но тама зачем-то цепляют DMA, а мне бы хотелось так попробовать, без DMA, и еще в том примере ширина локальной шины интерфейса DDR2 = 32, а у меня 64.

 

Расскажите, кто как делал, плз.

 

ПС: постарайтесь без "понтов", пожалуйста, т.к. я в этом Ниосе мало понимаю.

Изменено пользователем billidean

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а как теперь читать/писать в DDR-ину не знаю.

можно через указатели, можно через IORD/IOWR

я в этом Ниосе мало понимаю.

http://electronix.ru/forum/index.php?showtopic=78032

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Создал следующий проект:

SOPC: пробовал два варианта (из примера для DDR2):

post-59925-1322706607_thumb.png

и

post-59925-1322706632_thumb.png

подключил полученный компонент в проект квартуса, подцепил все внешние ноги.

Создал проект в Ниосе, с-код (на основе примера):

#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(...)) - на этом всё заканчивается.

 

Подключил СигналТап и получаю картинку:

post-59925-1322717668_thumb.png

на которой видно, что адрес=0, local_size почему-то =1(??), а данные тоже = 0.

 

Подскажите, что я делаю не так? Ну и просто можно прокомментировать получившийся проект.

Изменено пользователем billidean

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

можно через указатели, можно через IORD/IOWR

как я привел в примере, IORD/IOWR - результата не приносит. после чтения получаю 0xfff...

 

это мне ничего нового не сообщило

 

И вообще, я прошу помощи у тех, кто так же пробовал, маялся, и парил Инет в поисках работающего варианта.

 

Если кто не юзал данной связки: "DDR3+NiosII", то и незачем комменты левые оставлять, а если работал, то зажимать ответ стремно :mad:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

как я привел в примере, IORD/IOWR - результата не приносит. после чтения получаю 0xfff...

вы привели ерунду. писать/читать надо по адресу в памяти (см. в system.h), а не в мастер-порт контроллера DMA. это первичная проверка. если не работает - нет смысла пробовать DMA. ищите ошибки в назначении пинов или кривых констрейнах

это мне ничего нового не сообщило

И вообще, я прошу помощи у тех, кто так же пробовал, маялся, и парил Инет в поисках работающего варианта.

Если кто не юзал данной связки: "DDR3+NiosII", то и незачем комменты левые оставлять, а если работал, то зажимать ответ стремно :mad:

это вам должно было сообщить, как нужно задавать вопрос, чтобы получить ответ. ваш вопрос звучал так: "я не знаю, что такое ниос и ддр, документацию не читаю, но у меня не работает".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую всех в очередной раз.

Доработал свою систему до следующего состояния:

SOPC:

post-59925-1323228510_thumb.png

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:

post-59925-1323228517_thumb.png

 

Получается, что вычитывается из DDR-ины, то затем и записывается.

 

Подскажите, пожалуйста:

1. почему на диаграмме получается так, что сначала начинается процесс чтения, а затем уже процесс записи данных?

2. почему при попытке убрать из кода одну из функций alt_dma_txchan_send или alt_dma_rxchan_prepare

не происходит послыки запросов в DDR3-контроллер ни на запись ни на чтение?

3. как записать какие-то конкретные данные в область памяти DDR-ины???

 

p.s.: я работал с DDR3, но только в Квартусе, на VHDL, но не используя Ниос, поэтому я знаю как должна выглядеть нормальная циклограмма запросов на DDR3-контроллер, но как все это сделать на Ниосе и с применением DMA, для меня ново.

Изменено пользователем billidean

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В "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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо за подсказки и советы.

Я уже нашел на сайте alterawiki похожую конструкцию, и немного описания по данной теме.

Да, кстати, вы правы, что сначала нужно было добиться рабочих транзакций при использовании IOWR/IORD, а затем уже поднимать вопрос о необходимости DMA.

Да и не обязательно пользоваться макросами IOWR/IORD, можно просто работать с выделенной памятью как с массивом.

 

А проблема моя была в настройках системы в SOPC'е. Пока у меня немного кривые пакеты ходят от/к DDR, но изменяя параметры, я кое-чего добился уже.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да и не обязательно пользоваться макросами IOWR/IORD, можно просто работать с выделенной памятью как с массивом.

разумеется, можно. надо только учитывать кэш данных (если он есть в cpu)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...