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

Nios -> DMA

Вот и опять я....)

 

Ранее был разговор о том, как загружать данные из CFI_FLASH в SDRAM. Была проблема в том что глючно происходила запись. Как выяснилось из документации - виноват кэш. И проблема, соответсвенно решилась использованием макросов IOWR/IORD.

 

Код перекачки одного кадра изображения из флеша в сдрам получился такой:

    for (i = 0; i < 614400; i++) {
       dst_src = IORD_8DIRECT(CFI_FLASH_0_BASE+f_offset, i);
       IOWR_8DIRECT(SDRAM_0_BASE+d_offset, i, dst_src);
    }

 

Как вы понимаете - этот метод уже не устраивает, т.к. процессор загружен. Иными словами, я решил разобраться с прямым доступом к памяти DMA. Вот тут-то и возникли проблемы :(, прошу помочь найти ошибку.

Как используем DMA:

   alt_dma_txchan txchan;
    alt_dma_rxchan rxchan;
    int rc, rc1;
    if ((txchan = alt_dma_txchan_open("/dev/dma_0")) == NULL) {rc1 = 2;};
    if ((rxchan = alt_dma_rxchan_open("/dev/dma_0")) == NULL) {rc1 = 3;};
    
    if ((rc = alt_dma_txchan_send (txchan, (void*)(CFI_FLASH_0_BASE+f_offset), 614400, NULL, NULL)) < 0)
    {
        rc1 = 4;
    }
    if ((rc = alt_dma_rxchan_prepare (rxchan, (void*)(SDRAM_0_BASE+d_offset), 614400, dma_done, NULL)) < 0)
    {
        rc1 = 5;
    }
    while (!rx_done);  //инкремент в функции dma_done
    rx_done = 0;

 

Эта последовательность действий получена на основе примера memtest. Результат плачевный - в дебагере видно, что даже результат первых строчек NULL. Почему не открывается канал?

CFI_FLASH_0_BASE+f_offset = адрес картинки во влеше, источник

SDRAM_0_BASE+d_offset = куда копировать, адрес в ОЗУ

 

Прилагаю также картинки SOPC и настроек DMA.

Помогите разобраться что не так...

post-10359-1202468468_thumb.jpg

post-10359-1202468492_thumb.jpg

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


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

Что, никто не пишет программы по ниос? Та же фигня и с флеш памятью. Все работает только через IOWR-ы. В чем дело?

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


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

Да методы отладки остались все те же:

1. чтение документации;

2. моделирование верилога;

3. пошаговая отладка в железе;

4. монитор памяти в отладчике;

5. сигналтап.

 

Расковыряйте в исходниках, что делает функция alt_dma_txchan_open, дизассемблируйте код, посмотрите регистры процессора в режиме step debug.

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


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

Да можно и так, но опыта у меня мало, потому все это займет у меня много времени, а не хотелось бы. Кроме того - дизассемблирование вообще, на мой взгляд - чушь порядочная. Ты когда на visual С++ по windows пишешь и ошибка появляется, тоже "дизассемблируешь"?

 

Потому и спрашиваю, что наверняка кто-либо уже с этим сталкивался и ошибка весьма примитивна...

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


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

Да можно и так, но опыта у меня мало, потому все это займет у меня много времени, а не хотелось бы. Кроме того - дизассемблирование вообще, на мой взгляд - чушь порядочная. Ты когда на visual С++ по windows пишешь и ошибка появляется, тоже "дизассемблируешь"?

 

Потому и спрашиваю, что наверняка кто-либо уже с этим сталкивался и ошибка весьма примитивна...

Обычно если что то не получается так как у вас например, я использую совет id_gene

3. пошаговая отладка в железе;

посмотрите что происходит при вызове

alt_dma_txchan_open и что в ней например есть вызов alt_find_dev ну и так далее...

страно что сразу так не сделать было....много вопросов отпало сразу же :biggrin:

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


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

Да можно и так, но опыта у меня мало, потому все это займет у меня много времени, а не хотелось бы. Кроме того - дизассемблирование вообще, на мой взгляд - чушь порядочная. Ты когда на visual С++ по windows пишешь и ошибка появляется, тоже "дизассемблируешь"?
Ну, ваш вопрос висит уже 4 дня, и никто еще не ответил, похоже, что никто не сталкивался с такой проблемой, поэтому не лез в исходники С-файлов. Я, честно говоря, ДМА не использовал, но просто поиском в файлах описания указанной функции не нашел. :(

 

А отладка займет не так уж много времени, как вам кажется. Главное - найти в исходниках функцию и понять, что она делает. И тут не С++, программа не такая уж сложная. Дизассемблируйте с ключом -S, будет понятнее. Если ключ gcc -O0 (не оптимизировать), то результат будет очень близок к исходнику.

 

Первый шаг: в отладчике ставите точку останова перед вызовом функции, дожидаетесь останова, далее переключаетесь в режим "instruction stepping mode" и шагаете по коду. Исходники там, кажется, тоже откроются.

Проблема тут в том, что альтера многие свои функции объявляет _inline_ , так что они не всегда у вас "всплывут" при обычной отладке, вы перешагнете через них и не заметите.

 

Лучше два часа потерять сейчас на простом примере, зато в следующий раз такие проблемы решатся гораздо быстрее. Если вы собираетесь дальше работать с ниосом, применять этот метод вам рано или поздно придется все равно (когда вы начнете писать сложные приложения и драйверы под свои модули).

Удачи

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


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

Раз так все говорят, значит это, вероятно, правда :)

Приду на работу - пошагово отлажу.

 

За ответ спасибо!

 

Кроме того, id_gene прав на счет пары часов...

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


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

Продолжу здесь, дабы не захламлять эфир еще одной темой...

 

Дошел до того, что хочу подключить библиотеку к проекту в ниосе. Добавляю в проект elca_fat.h и elca_fat.a (сама библиотека) и... при компиляции IDE делает вид что не видит эту библиотеку. Я уже и в свойствах проекта ее указал - почему не видит?

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


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

Доброго времени суток!

По поводу ДМА:

dma_clear_status();

dma_clear_control();

dma_wr_source_address(source_addr);

dma_wr_dest_address(dest_addr);

dma_wr_length(length); //длинна в байтах

 

dma_wr_control(ALTERA_AVALON_DMA_CONTROL_DWORD_MSK|

ALTERA_AVALON_DMA_CONTROL_LEEN_MSK|

ALTERA_AVALON_DMA_CONTROL_RCON_MSK|

ALTERA_AVALON_DMA_CONTROL_GO_MSK); // все эти биты есть в описании

while (IORD_ALTERA_AVALON_DMA_STATUS (DMA_0_BASE) & ALTERA_AVALON_DMA_STATUS_BUSY_MSK); // ждем пока все не передаст :)

 

САМИ МАКРОСЫ

 

#include <altera_avalon_dma_regs.h>

 

 

 

#define dma_clear_status() IOWR_ALTERA_AVALON_DMA_STATUS(DMA_0_BASE, 0)

#define dma_clear_control() IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_0_BASE,0)

 

#define dma_wr_source_address(address) IOWR_ALTERA_AVALON_DMA_RADDRESS(DMA_0_BASE, address)

#define dma_wr_dest_address(address) IOWR_ALTERA_AVALON_DMA_WADDRESS(DMA_0_BASE, address)

#define dma_wr_length(length) IOWR_ALTERA_AVALON_DMA_LENGTH(DMA_0_BASE, length)

#define dma_wr_control(control) IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_0_BASE, control)

 

 

по поводу библиотек, попробуй грохнуть старые sislib из проекта и создать новые, вроде помогало

(правой кнопкой мыша и создать новую библиотеку, должно втянуть то что ты написал)

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


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

Вот еще код при работе с дма, шина данных 8 бит.

 

 

#include <stdio.h>

#include "altera_avalon_dma.h"

#include "sys/alt_dma.h"

 

char txbuf[512];

char rxbuf[512];

 

static volatile int rx_done = 0;

static void dma_done (void* handle, void* data)

{

rx_done++;

}

 

int main()

{

int dma_ok, rc, i;

 

alt_dma_txchan txchan;

alt_dma_rxchan rxchan;

 

if ((txchan = alt_dma_txchan_open("/dev/dma")) == NULL) printf("alt_dma_txchan_open error\n");

if ((rxchan = alt_dma_rxchan_open("/dev/dma")) == NULL) printf("alt_dma_rxchan_open error\n");

 

alt_dma_txchan_ioctl(txchan, ALT_DMA_SET_MODE_8, NULL);//SDRAM MT48LC8M8A2->WIDTH_DATA=8

alt_dma_rxchan_ioctl(rxchan, ALT_DMA_SET_MODE_8, NULL);//SDRAM MT48LC8M8A2->WIDTH_DATA=8

 

while(1)

{

printf("test dma \n");

 

for(i=0; i<512; i++) {txbuf=i; rxbuf=0; }

 

if ((rc = alt_avalon_dma_send(txchan, txbuf, 512, NULL, NULL)) < 0)

{

printf("alt_dma_txchan_send : error = %d\n", rc);

}

if ((rc = alt_avalon_dma_prepare(rxchan, rxbuf, 512, dma_done, NULL)) < 0)

{

printf("alt_dma_rxchan_send : error = %d\n", rc);

}

while (!rx_done); //инкремент в функции dma_done

rx_done = 0;

 

dma_ok = 1;

for(i=0; i<512; i++)

{

if(rxbuf != txbuf)

{

dma_ok = 0;

printf("error : txbuf[%d] = %x rxbuf[%d] = %x\n", i, txbuf, i, rxbuf);

}

}

if(dma_ok) printf("dma_ok\n");

}

 

return 0;

}

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


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

Вариант работы через IOWR-ы впорядке, все работает нормально...

Последний вариант, к сожалению не работает. Я тоже самое взял из примера memtest (вроде).

 

txchan = alt_dma_txchan_open("/dev/dma")

когда дело доходит до этой функции - он не воспринимает имя "/dev/dma", и я пока отложил в сторону эту проблему...

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


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

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

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

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

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

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

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

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

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

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