Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Nios -> DMA
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Системы на ПЛИС - System on a Programmable Chip (SoPC)
torik
Вот и опять я....)

Ранее был разговор о том, как загружать данные из 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. Вот тут-то и возникли проблемы sad.gif, прошу помочь найти ошибку.
Как используем 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.
Помогите разобраться что не так...
torik
Что, никто не пишет программы по ниос? Та же фигня и с флеш памятью. Все работает только через IOWR-ы. В чем дело?
id_gene
Да методы отладки остались все те же:
1. чтение документации;
2. моделирование верилога;
3. пошаговая отладка в железе;
4. монитор памяти в отладчике;
5. сигналтап.

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

Потому и спрашиваю, что наверняка кто-либо уже с этим сталкивался и ошибка весьма примитивна...
Postoroniy_V
Цитата(torik @ Feb 13 2008, 02:30) *
Да можно и так, но опыта у меня мало, потому все это займет у меня много времени, а не хотелось бы. Кроме того - дизассемблирование вообще, на мой взгляд - чушь порядочная. Ты когда на visual С++ по windows пишешь и ошибка появляется, тоже "дизассемблируешь"?

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

Обычно если что то не получается так как у вас например, я использую совет id_gene
3. пошаговая отладка в железе;
посмотрите что происходит при вызове
alt_dma_txchan_open и что в ней например есть вызов alt_find_dev ну и так далее...
страно что сразу так не сделать было....много вопросов отпало сразу же biggrin.gif
id_gene
Цитата(torik @ Feb 12 2008, 20:30) *
Да можно и так, но опыта у меня мало, потому все это займет у меня много времени, а не хотелось бы. Кроме того - дизассемблирование вообще, на мой взгляд - чушь порядочная. Ты когда на visual С++ по windows пишешь и ошибка появляется, тоже "дизассемблируешь"?
Ну, ваш вопрос висит уже 4 дня, и никто еще не ответил, похоже, что никто не сталкивался с такой проблемой, поэтому не лез в исходники С-файлов. Я, честно говоря, ДМА не использовал, но просто поиском в файлах описания указанной функции не нашел. sad.gif

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

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

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

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

Кроме того, id_gene прав на счет пары часов...
torik
Продолжу здесь, дабы не захламлять эфир еще одной темой...

Дошел до того, что хочу подключить библиотеку к проекту в ниосе. Добавляю в проект elca_fat.h и elca_fat.a (сама библиотека) и... при компиляции IDE делает вид что не видит эту библиотеку. Я уже и в свойствах проекта ее указал - почему не видит?
AlexanderL
Доброго времени суток!
По поводу ДМА:
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); // ждем пока все не передаст smile.gif

САМИ МАКРОСЫ

#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 из проекта и создать новые, вроде помогало
(правой кнопкой мыша и создать новую библиотеку, должно втянуть то что ты написал)
torik
Вот спасибо!
RYury
Вот еще код при работе с дма, шина данных 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;
}
torik
Вариант работы через IOWR-ы впорядке, все работает нормально...
Последний вариант, к сожалению не работает. Я тоже самое взял из примера memtest (вроде).

Код
txchan = alt_dma_txchan_open("/dev/dma")

когда дело доходит до этой функции - он не воспринимает имя "/dev/dma", и я пока отложил в сторону эту проблему...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.