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

Здравствуйте.

Счас пытаюсь освоить ДМА для ниоса.

Прочитал описание альтеры для компонента, на ниос-форуме посмотрел примеры и сваял свою реализацию..

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

//===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:

Кто работал с ДМА - подскажите что не так ..

:help:

Спасибо.

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


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

Что ? Никто не работал с ДМА через регистры ?? :(

:help:

Неохота просто тратить килобайты кода на каналы, что в хале уже есть, если можно просче...

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


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

Надо попробовать для начала без прерываний:

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

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


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

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

 

Код:

//
    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:

Специально проверил в дизайне процессора - коннекты есть с сдрамом для записи и чтения:

post-25329-1210236259_thumb.jpg

 

Это вот меня и загоняет в тупик....... :smile3046:

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


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

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

 

IOWR_ALTERA_AVALON_DMA_RADDRESS(DMA_BASE, outbuffer); //адрес передатчика

IOWR_ALTERA_AVALON_DMA_WADDRESS(DMA_BASE, inbuffer); //адрес приемника

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


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

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

 

Так что это не то..

Кстати до и после транзакции смотрел - правильные адреса в регистрах...

Длинна - то же правильная в регистре..

( Смотрел в дебуге )

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


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

waddr = (alt_u32)&inbuffer[0];

как раз и загружает в waddr адрес inbuffer[0].

Это если без кэша, с кэшем - они там и остаются. Чтобы обойти кэш надо установить 31 бит в адресе переменной или использовать макросы доступа к регистрам.

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


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

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

 

Однако по коду просмотрел значения waddr и raddr и те что записывались в регистры ДМА, а потом в мемори тыканулся по этим адресам - всё соответствовало реальности..

Биты DONE и LEN выставляются, регистры адреса меняются, регистр длинны нулевой в конце , а результата - НОЛЬ :crying:

:help:

 

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

:smile3046:

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


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

А вот эти массивы откуда беруться, как объявлены. Проверяли в дебагере - соответствуют ли они тем адресам на которые подключен DMA?

        inbuffer[i]=0;
        outbuffer[i]=i+1;

 

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

Ну и, пожалуй буферы выделяйте через malloc().

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


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

А вот эти массивы откуда беруться, как объявлены

Обявлены до мэйна

//---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 подключения - ДМА подключён к уарту и сдрам

post-25329-1210255420_thumb.jpg

 

И что вы имелли ввиду на счёт

как это вы задаете для DMA буфер откуда читать из памяти SDRAM

Ну и, пожалуй буферы выделяйте через malloc().

Я выставляю в ДМА регистре readaddress откуда читать, в регистре writeaddress - куда писать...

И зачем именно malloc() ? Вроде бы уже есть массив volatile alt_u8 ...

 

--

Прицепил весь свой прожект вообсче.

Если будет время посмотрите - может что не так...

Вот картинки начальных конфигурирования ДМА:

post-25329-1210258486_thumb.jpg

post-25329-1210258496_thumb.jpg

data.rar

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


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

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

Это значит то, что вы можете писать в память,но данные на самом деле не выйдут за пределы процессора. Также при чтении получите коллизию данных, когда в кэше сидят старые данные, а в памяти новые. Кэш то не знает чего вы там за пределами процессора делаете.

При использовании макросов прямого доступа к периферии данные гарантированно выходят за пределы процессора. volatile спасает от оптимизации, но не от кэша!

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


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

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

 

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

Видимо как раз у меня проблема с этим кэшем..

Надо будет пересобрать процессор без кеша на крайний случай...

 

А на счёт макросов обращения к памяти - я ж вроде смотрел в мемори въювере - адреса меняются, всё вроде отрабатывается, только вот в том же въювере не видно изменений в выходном массиве.. То есть запись то в регистры ДМА получается проходит нормально....

:wacko:

Тут есть идея - возможно что когда я повторно считываю данные с массива inbuffer - процюк берёт их с кеша - ведь он уже с ними работал до этого в начале мэйна... А как можно перегрузить данные массива из памяти в кеш ?? :smile3046:

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


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

Действительно, попробуйте для эксперимента отключить кеш у проца. Если траблы исчезнкт, то осваивайте работу с кешем.

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


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

Ага! :08:

Пока суть до дела, я отправил запрос в саппорт - типа хелп, не работает...

В обсчем получил ответ с саппорта - догадка оказалась правльной - действительно кеш бякой оказался:

...

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:

...

Кстати читая "n2sw_nii52007.pdf" наткнулся на место:

The volatile keyword ONLY prevents the compiler from optimizing out accesses using the pointer.

Как раз то , о чём говорил vetal ..

Действительно тут немного другой подход...

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


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

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

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

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

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

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

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

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

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

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