реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> NIOSII и DMA, вроде все дёлаю по книжке, но есть интересные моменты..
Kuzmi4
сообщение May 3 2008, 18:24
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 3 304
Регистрация: 13-02-07
Из: 55°55′5″ 37°52′16″
Пользователь №: 25 329



Здравствуйте.
Счас пытаюсь освоить ДМА для ниоса.
Прочитал описание альтеры для компонента, на ниос-форуме посмотрел примеры и сваял свою реализацию..
В обсчем код выглядит так(звиняйте если большой, но коментарии присутствуют):
Код
//===ISR part===
static void dma_isr ( void * context2, alt_u32 irqnum2 )
{
    asm("nop");
    //set flag
    dmaf=1;
    /* Clear any pending interrupts and the DONE flag */
    IOWR_ALTERA_AVALON_DMA_STATUS (DMA_BASE, 0);
    
}
//===END ISR part===


//---MAIN---
int main (void)
{
    asm ("nop");
    //
    unsigned char i=0;
    // initial values
    cnt_val=0;
    ch=0;
    txf=0;
    dmaf=0;
    //
    for (i=0;i<12;i++)
    {
        inbuffer[i]=0;
        outbuffer[i]=i+1;
    }
    //
    //
    asm("nop");
    //register DMA ISR
    alt_irq_register(DMA_IRQ,(void*)DMA_BASE,dma_isr);
    asm("nop");
    asm("nop");
    //
    //DMA_Init
    /* Clear any pending interrupts and the DONE flag */
    IOWR_ALTERA_AVALON_DMA_STATUS (DMA_BASE, 0);
    asm("nop");
    asm("nop");
    //clear control register
    IOWR_ALTERA_AVALON_DMA_CONTROL (DMA_BASE, 0);
    asm("nop");
    asm("nop");
    /* Halt any current transactions (reset the device) */
    IOWR_ALTERA_AVALON_DMA_CONTROL (DMA_BASE, ALTERA_AVALON_DMA_CONTROL_SOFTWARERESET_MSK);    
    IOWR_ALTERA_AVALON_DMA_CONTROL (DMA_BASE, ALTERA_AVALON_DMA_CONTROL_SOFTWARERESET_MSK);
    asm("nop");
    asm("nop");
    asm("nop");
    //asm("nop");
    //set initial values for tranmit
    //byte orientating transfer
    alt_u32 control=0;
    control |= ALTERA_AVALON_DMA_CONTROL_BYTE_MSK;//byte transfer
    control |= ALTERA_AVALON_DMA_CONTROL_I_EN_MSK;//enable int
    control |= ALTERA_AVALON_DMA_CONTROL_LEEN_MSK;//enable end of transaction by reacing Len 0
    //1st try with mem massives -> no uart
    //control |= ALTERA_AVALON_DMA_CONTROL_RCON_MSK;//read from constant mem - we use uart, so mem == const
    //store control
    IOWR_ALTERA_AVALON_DMA_CONTROL (DMA_BASE, control);
    asm("nop");
    asm("nop");    
    //**
    //DMA_start((int)&inbuffer[0],(int)&outbuffer[0],10);
    //**
    waddr = (int)&inbuffer[0];
    raddr = (int)&outbuffer[0];
    len=10;
    //alt_u32 control;
    control=0;
    //wrire read addr
    IOWR_ALTERA_AVALON_DMA_RADDRESS(DMA_BASE, raddr);
    asm("nop");
    asm("nop");
    //wrire write addr
    IOWR_ALTERA_AVALON_DMA_WADDRESS(DMA_BASE, waddr);
    asm("nop");
    asm("nop");
    //write length
    IOWR_ALTERA_AVALON_DMA_LENGTH(DMA_BASE,len);
    asm("nop");
    asm("nop");
    //start transfer
    control = IORD_ALTERA_AVALON_DMA_CONTROL (DMA_BASE);
    control |= ALTERA_AVALON_DMA_CONTROL_GO_MSK;
    IOWR_ALTERA_AVALON_DMA_CONTROL (DMA_BASE, control);
    //
    dmaf=0;
    asm("nop");
    //**
  while (1)
  {
    /***/
wlabel:
    asm("nop");
    //
    if (dmaf==0) goto wlabel;
    
    asm("nop");
    IOWR_ALTERA_AVALON_PIO_DATA(SEVEN_SEGMENT_PORT_BASE,segments[inbuffer[0]] );        
        asm("nop");
    while (1);
    /***/
  }
  
  return 0;
}


В обсчем, компилируется всё нормально, код вроде выглядить при дебуге нормально,
однако есть непонятные моменты...
Если поставить точек прерываний по коду в ключевых местах - регистрация прерывания, запись контрола ДМА, старт ДМА - то всё отрабатывается нормально, если только на старте ДМА - то интерупт генерится а действия никакого..
Если вообсче не ставить точек прерывания - то ничего не отрабатывается - интерупта нет.. ничего нет...
Дебаг юнит в НИОСЕ - 2-й, 3-й - без разницы.
Read и Write каналы соединены с уартом и сдрам, программа находтся в сдрам, переменные - тоже.
В принципе такое поведение наталкивает на мысль , что не хватает задержек (только не пойму зачем, вроде в описании к ДМА не было про них...) , потому и наставил нопов - однако с ними и без них - работает одинаково...
smile3046.gif
Кто работал с ДМА - подскажите что не так ..
help.gif
Спасибо.
Go to the top of the page
 
+Quote Post
Kuzmi4
сообщение May 7 2008, 13:49
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 3 304
Регистрация: 13-02-07
Из: 55°55′5″ 37°52′16″
Пользователь №: 25 329



Что ? Никто не работал с ДМА через регистры ?? sad.gif
help.gif
Неохота просто тратить килобайты кода на каналы, что в хале уже есть, если можно просче...
Go to the top of the page
 
+Quote Post
torik
сообщение May 8 2008, 05:06
Сообщение #3


Гуру
******

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



Надо попробовать для начала без прерываний:
Код
    while ((IORD_ALTERA_AVALON_DMA_STATUS (DMA_0_BASE) & ALTERA_AVALON_DMA_STATUS_BUSY_MSK)); // ждем пока все не передаст


--------------------
Быть. torizin-liteha@yandex.ru
Go to the top of the page
 
+Quote Post
Kuzmi4
сообщение May 8 2008, 08:45
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 3 304
Регистрация: 13-02-07
Из: 55°55′5″ 37°52′16″
Пользователь №: 25 329



В обсчем попробовал я без прерываний..

Код:
Код
//
    unsigned char i=0;
    for (i=0;i<16;i++)
    {
        inbuffer[i]=0;
        outbuffer[i]=i+1;
    }
    //
    waddr = (alt_u32)&inbuffer[0];
    raddr = (alt_u32)&outbuffer[0];
    buff_length = 8;
    //
    IOWR_ALTERA_AVALON_DMA_STATUS(DMA_BASE, 0); //очистка статуса
    IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_BASE,0); //очистка регистра управления
    //
    IOWR_ALTERA_AVALON_DMA_RADDRESS(DMA_BASE, raddr); //адрес передатчика
    IOWR_ALTERA_AVALON_DMA_WADDRESS(DMA_BASE, waddr); //адрес приемника
    //
    IOWR_ALTERA_AVALON_DMA_LENGTH(DMA_BASE, buff_length); //длина в байтах
    dma_length=IORD_ALTERA_AVALON_DMA_LENGTH(DMA_BASE);
    //
    IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_BASE,
    ALTERA_AVALON_DMA_CONTROL_BYTE_MSK|
    ALTERA_AVALON_DMA_CONTROL_GO_MSK|
    ALTERA_AVALON_DMA_CONTROL_LEEN_MSK);
    
    while ( IORD_ALTERA_AVALON_DMA_STATUS(DMA_BASE) & (ALTERA_AVALON_DMA_STATUS_BUSY_MSK))
    { // ждем пока все не передаст
        asm volatile ("nop");
    }
    //отображение
    printf("!!!");
    printf("inbuffer= ");
    for (i=0; i<buff_length; i++)
    {
        printf("%i ", inbuffer[i]);
        asm volatile ("nop");
    }
    printf("!!!");
    printf("outbuffer= ");
    for (i=0; i<buff_length; i++)
    {
        printf("%i ", outbuffer[i]);
        asm volatile ("nop");
    }
    printf("!!!");
    while (1);


Вот что выдало:

!!!inbuffer= 0 0 0 0 0 0 0 0 !!!outbuffer= 1 2 3 4 5 6 7 8 !!!

То есть отработка есть а результата нет - как такое может быть ? wacko.gif
Специально проверил в дизайне процессора - коннекты есть с сдрамом для записи и чтения:
Прикрепленное изображение


Это вот меня и загоняет в тупик....... smile3046.gif
Go to the top of the page
 
+Quote Post
AlexanderL
сообщение May 8 2008, 12:56
Сообщение #5





Группа: Участник
Сообщений: 10
Регистрация: 22-03-07
Пользователь №: 26 400



попробуй вот так:

IOWR_ALTERA_AVALON_DMA_RADDRESS(DMA_BASE, outbuffer); //адрес передатчика
IOWR_ALTERA_AVALON_DMA_WADDRESS(DMA_BASE, inbuffer); //адрес приемника
Go to the top of the page
 
+Quote Post
Kuzmi4
сообщение May 8 2008, 13:23
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 3 304
Регистрация: 13-02-07
Из: 55°55′5″ 37°52′16″
Пользователь №: 25 329



2 AlexanderL -

Понимаете -
конструкция вида
waddr = (alt_u32)&inbuffer[0];
как раз и загружает в waddr адрес inbuffer[0].

А ваше предложение вызывает такие варнинги:
../count_binary.c: In function `main':
../count_binary.c:50: warning: passing arg 2 of `__builtin_stwio' makes integer from pointer without a cast
../count_binary.c:51: warning: passing arg 2 of `__builtin_stwio' makes integer from pointer without a cast

Так что это не то..
Кстати до и после транзакции смотрел - правильные адреса в регистрах...
Длинна - то же правильная в регистре..
( Смотрел в дебуге )
Go to the top of the page
 
+Quote Post
vetal
сообщение May 8 2008, 13:43
Сообщение #7


Гуру
******

Группа: Модераторы
Сообщений: 2 095
Регистрация: 27-08-04
Из: Россия, СПб
Пользователь №: 553



Цитата
waddr = (alt_u32)&inbuffer[0];
как раз и загружает в waddr адрес inbuffer[0].

Это если без кэша, с кэшем - они там и остаются. Чтобы обойти кэш надо установить 31 бит в адресе переменной или использовать макросы доступа к регистрам.
Go to the top of the page
 
+Quote Post
Kuzmi4
сообщение May 8 2008, 13:50
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 3 304
Регистрация: 13-02-07
Из: 55°55′5″ 37°52′16″
Пользователь №: 25 329



NIOSII у меня fast - тобто полной комплектации - есть кеш.

Однако по коду просмотрел значения waddr и raddr и те что записывались в регистры ДМА, а потом в мемори тыканулся по этим адресам - всё соответствовало реальности..
Биты DONE и LEN выставляются, регистры адреса меняются, регистр длинны нулевой в конце , а результата - НОЛЬ crying.gif
help.gif

Не можете вы объяснить что значит "обойти кеш" и к чему это?
smile3046.gif
Go to the top of the page
 
+Quote Post
torik
сообщение May 8 2008, 13:58
Сообщение #9


Гуру
******

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



А вот эти массивы откуда беруться, как объявлены. Проверяли в дебагере - соответствуют ли они тем адресам на которые подключен DMA?
Код
        inbuffer[i]=0;
        outbuffer[i]=i+1;


Да вообще может я чего-то не понимаю, но как это вы задаете для DMA буфер откуда читать из памяти SDRAM (и то по этому поводу я выше писал), если в системе сопс он подключен к UART. Тогда и подкулючайте порт чтения DMA к той же памяти.
Ну и, пожалуй буферы выделяйте через malloc().


--------------------
Быть. torizin-liteha@yandex.ru
Go to the top of the page
 
+Quote Post
Kuzmi4
сообщение May 8 2008, 14:58
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 3 304
Регистрация: 13-02-07
Из: 55°55′5″ 37°52′16″
Пользователь №: 25 329



Цитата(torik @ May 8 2008, 16:58) *
А вот эти массивы откуда беруться, как объявлены

Обявлены до мэйна
Код
//---DATA Declaration    
    volatile alt_u8 inbuffer[16];
    volatile alt_u8 outbuffer[16];
    volatile alt_u32 waddr=0;
    volatile alt_u32 raddr=0;
    volatile alt_u32 buff_length=0;
    volatile alt_u32 dma_length=0;
//---END DATA Declaration
//

//---MAIN---
int main (void)
{
....

В дебуге проверял - выше писал..Перед записью GO_MASK для старта делал останов и проверял регистры - readaddress и writeaddress соответствовали действительным адресам в раме(тыкался по мемори,смотрел..), длинна тоже была правильной...

Вот рисунок с SoPC - там можете увидеть - синеньком подсвечены read и write подключения - ДМА подключён к уарту и сдрам
Прикрепленное изображение


И что вы имелли ввиду на счёт
Цитата(torik @ May 8 2008, 16:58) *
как это вы задаете для DMA буфер откуда читать из памяти SDRAM
Ну и, пожалуй буферы выделяйте через malloc().

Я выставляю в ДМА регистре readaddress откуда читать, в регистре writeaddress - куда писать...
И зачем именно malloc() ? Вроде бы уже есть массив volatile alt_u8 ...

--
Прицепил весь свой прожект вообсче.
Если будет время посмотрите - может что не так...
Вот картинки начальных конфигурирования ДМА:
Прикрепленное изображение

Прикрепленное изображение

Прикрепленные файлы
Прикрепленный файл  data.rar ( 545.99 килобайт ) Кол-во скачиваний: 43
 
Go to the top of the page
 
+Quote Post
vetal
сообщение May 8 2008, 15:39
Сообщение #11


Гуру
******

Группа: Модераторы
Сообщений: 2 095
Регистрация: 27-08-04
Из: Россия, СПб
Пользователь №: 553



Цитата
Не можете вы объяснить что значит "обойти кеш" и к чему это?

Это значит то, что вы можете писать в память,но данные на самом деле не выйдут за пределы процессора. Также при чтении получите коллизию данных, когда в кэше сидят старые данные, а в памяти новые. Кэш то не знает чего вы там за пределами процессора делаете.
При использовании макросов прямого доступа к периферии данные гарантированно выходят за пределы процессора. volatile спасает от оптимизации, но не от кэша!
Go to the top of the page
 
+Quote Post
Kuzmi4
сообщение May 11 2008, 14:37
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 3 304
Регистрация: 13-02-07
Из: 55°55′5″ 37°52′16″
Пользователь №: 25 329



2 vetal - Спасибо. Буду знать.

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

А на счёт макросов обращения к памяти - я ж вроде смотрел в мемори въювере - адреса меняются, всё вроде отрабатывается, только вот в том же въювере не видно изменений в выходном массиве.. То есть запись то в регистры ДМА получается проходит нормально....
wacko.gif
Тут есть идея - возможно что когда я повторно считываю данные с массива inbuffer - процюк берёт их с кеша - ведь он уже с ними работал до этого в начале мэйна... А как можно перегрузить данные массива из памяти в кеш ?? smile3046.gif
Go to the top of the page
 
+Quote Post
vetal
сообщение May 11 2008, 17:12
Сообщение #13


Гуру
******

Группа: Модераторы
Сообщений: 2 095
Регистрация: 27-08-04
Из: Россия, СПб
Пользователь №: 553



Работа с кешем:
http://altera.com/literature/hb/nios2/n2sw_nii52007.pdf
Go to the top of the page
 
+Quote Post
RHnd
сообщение May 12 2008, 05:52
Сообщение #14


Знающий
****

Группа: Свой
Сообщений: 518
Регистрация: 12-04-07
Из: Санкт-Петербург
Пользователь №: 26 997



Цитата(vetal @ May 11 2008, 21:12) *

Действительно, попробуйте для эксперимента отключить кеш у проца. Если траблы исчезнкт, то осваивайте работу с кешем.
Go to the top of the page
 
+Quote Post
Kuzmi4
сообщение May 12 2008, 09:18
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 3 304
Регистрация: 13-02-07
Из: 55°55′5″ 37°52′16″
Пользователь №: 25 329



Ага! 08.gif
Пока суть до дела, я отправил запрос в саппорт - типа хелп, не работает...
В обсчем получил ответ с саппорта - догадка оказалась правльной - действительно кеш бякой оказался:
Цитата
...
Since the CPU you used has data cache, I am afraid that the data displaying after the DMA operation is the dirty data.

Please call alt_dcache_flush_all (); after the DMA finishes. The alt_dcache_flush_all() function flushes, i.e., writes back dirty data and then invalidates, the entire contents of the data cache.
...

Сегодня как дойдут руки - обязательно попробую , а то уже столько времени уже убил блин на одном месте....
smile3046.gif
...
Кстати читая "n2sw_nii52007.pdf" наткнулся на место:
Цитата
The volatile keyword ONLY prevents the compiler from optimizing out accesses using the pointer.

Как раз то , о чём говорил vetal ..
Действительно тут немного другой подход...
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 20:02
Рейтинг@Mail.ru


Страница сгенерированна за 0.0155 секунд с 7
ELECTRONIX ©2004-2016