|
Nios -> DMA, как правильно пользоваться |
|
|
|
Feb 8 2008, 11:01
|

Гуру
     
Группа: Свой
Сообщений: 2 113
Регистрация: 1-11-05
Пользователь №: 10 359

|
Вот и опять я....) Ранее был разговор о том, как загружать данные из 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. Помогите разобраться что не так...
Эскизы прикрепленных изображений
--------------------
Быть. torizin-liteha@yandex.ru
|
|
|
|
|
 |
Ответов
(1 - 11)
|
Feb 13 2008, 02:22
|

МедвеД Инженер I
   
Группа: Свой
Сообщений: 816
Регистрация: 21-10-04
Пользователь №: 951

|
Цитата(torik @ Feb 13 2008, 02:30)  Да можно и так, но опыта у меня мало, потому все это займет у меня много времени, а не хотелось бы. Кроме того - дизассемблирование вообще, на мой взгляд - чушь порядочная. Ты когда на visual С++ по windows пишешь и ошибка появляется, тоже "дизассемблируешь"?
Потому и спрашиваю, что наверняка кто-либо уже с этим сталкивался и ошибка весьма примитивна... Обычно если что то не получается так как у вас например, я использую совет id_gene3. пошаговая отладка в железе; посмотрите что происходит при вызове alt_dma_txchan_open и что в ней например есть вызов alt_find_dev ну и так далее... страно что сразу так не сделать было....много вопросов отпало сразу же
--------------------
Cogito ergo sum
|
|
|
|
|
Feb 13 2008, 08:40
|
carpe manana
  
Группа: Свой
Сообщений: 321
Регистрация: 2-06-05
Пользователь №: 5 659

|
Цитата(torik @ Feb 12 2008, 20:30)  Да можно и так, но опыта у меня мало, потому все это займет у меня много времени, а не хотелось бы. Кроме того - дизассемблирование вообще, на мой взгляд - чушь порядочная. Ты когда на visual С++ по windows пишешь и ошибка появляется, тоже "дизассемблируешь"? Ну, ваш вопрос висит уже 4 дня, и никто еще не ответил, похоже, что никто не сталкивался с такой проблемой, поэтому не лез в исходники С-файлов. Я, честно говоря, ДМА не использовал, но просто поиском в файлах описания указанной функции не нашел.  А отладка займет не так уж много времени, как вам кажется. Главное - найти в исходниках функцию и понять, что она делает. И тут не С++, программа не такая уж сложная. Дизассемблируйте с ключом -S, будет понятнее. Если ключ gcc -O0 (не оптимизировать), то результат будет очень близок к исходнику. Первый шаг: в отладчике ставите точку останова перед вызовом функции, дожидаетесь останова, далее переключаетесь в режим "instruction stepping mode" и шагаете по коду. Исходники там, кажется, тоже откроются. Проблема тут в том, что альтера многие свои функции объявляет _inline_ , так что они не всегда у вас "всплывут" при обычной отладке, вы перешагнете через них и не заметите. Лучше два часа потерять сейчас на простом примере, зато в следующий раз такие проблемы решатся гораздо быстрее. Если вы собираетесь дальше работать с ниосом, применять этот метод вам рано или поздно придется все равно (когда вы начнете писать сложные приложения и драйверы под свои модули). Удачи
|
|
|
|
|
Feb 15 2008, 18:14
|
Группа: Участник
Сообщений: 10
Регистрация: 22-03-07
Пользователь №: 26 400

|
Доброго времени суток! По поводу ДМА: 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 из проекта и создать новые, вроде помогало (правой кнопкой мыша и создать новую библиотеку, должно втянуть то что ты написал)
|
|
|
|
|
Feb 19 2008, 11:04
|

Участник

Группа: Свой
Сообщений: 70
Регистрация: 4-12-06
Из: Окно Петра в Европу
Пользователь №: 23 119

|
Вот еще код при работе с дма, шина данных 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]=i; rxbuf[i]=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[i] != txbuf[i]) { dma_ok = 0; printf("error : txbuf[%d] = %x rxbuf[%d] = %x\n", i, txbuf[i], i, rxbuf[i]); } } if(dma_ok) printf("dma_ok\n"); }
return 0; }
|
|
|
|
|
Feb 19 2008, 19:52
|

Гуру
     
Группа: Свой
Сообщений: 2 113
Регистрация: 1-11-05
Пользователь №: 10 359

|
Вариант работы через IOWR-ы впорядке, все работает нормально... Последний вариант, к сожалению не работает. Я тоже самое взял из примера memtest (вроде). Код txchan = alt_dma_txchan_open("/dev/dma") когда дело доходит до этой функции - он не воспринимает имя "/dev/dma", и я пока отложил в сторону эту проблему...
--------------------
Быть. torizin-liteha@yandex.ru
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|