Kuzmi4 0 3 мая, 2008 Опубликовано 3 мая, 2008 · Жалоба Здравствуйте. Счас пытаюсь освоить ДМА для ниоса. Прочитал описание альтеры для компонента, на ниос-форуме посмотрел примеры и сваял свою реализацию.. В обсчем код выглядит так(звиняйте если большой, но коментарии присутствуют): //===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: Кто работал с ДМА - подскажите что не так .. Спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kuzmi4 0 7 мая, 2008 Опубликовано 7 мая, 2008 · Жалоба Что ? Никто не работал с ДМА через регистры ?? :( Неохота просто тратить килобайты кода на каналы, что в хале уже есть, если можно просче... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
torik 0 8 мая, 2008 Опубликовано 8 мая, 2008 · Жалоба Надо попробовать для начала без прерываний: while ((IORD_ALTERA_AVALON_DMA_STATUS (DMA_0_BASE) & ALTERA_AVALON_DMA_STATUS_BUSY_MSK)); // ждем пока все не передаст Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kuzmi4 0 8 мая, 2008 Опубликовано 8 мая, 2008 · Жалоба В обсчем попробовал я без прерываний.. Код: // 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 !!! То есть отработка есть а результата нет - как такое может быть ? Специально проверил в дизайне процессора - коннекты есть с сдрамом для записи и чтения: Это вот меня и загоняет в тупик....... :smile3046: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexanderL 0 8 мая, 2008 Опубликовано 8 мая, 2008 · Жалоба попробуй вот так: IOWR_ALTERA_AVALON_DMA_RADDRESS(DMA_BASE, outbuffer); //адрес передатчика IOWR_ALTERA_AVALON_DMA_WADDRESS(DMA_BASE, inbuffer); //адрес приемника Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kuzmi4 0 8 мая, 2008 Опубликовано 8 мая, 2008 · Жалоба 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 Так что это не то.. Кстати до и после транзакции смотрел - правильные адреса в регистрах... Длинна - то же правильная в регистре.. ( Смотрел в дебуге ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vetal 0 8 мая, 2008 Опубликовано 8 мая, 2008 · Жалоба waddr = (alt_u32)&inbuffer[0]; как раз и загружает в waddr адрес inbuffer[0]. Это если без кэша, с кэшем - они там и остаются. Чтобы обойти кэш надо установить 31 бит в адресе переменной или использовать макросы доступа к регистрам. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kuzmi4 0 8 мая, 2008 Опубликовано 8 мая, 2008 · Жалоба NIOSII у меня fast - тобто полной комплектации - есть кеш. Однако по коду просмотрел значения waddr и raddr и те что записывались в регистры ДМА, а потом в мемори тыканулся по этим адресам - всё соответствовало реальности.. Биты DONE и LEN выставляются, регистры адреса меняются, регистр длинны нулевой в конце , а результата - НОЛЬ :crying: Не можете вы объяснить что значит "обойти кеш" и к чему это? :smile3046: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
torik 0 8 мая, 2008 Опубликовано 8 мая, 2008 · Жалоба А вот эти массивы откуда беруться, как объявлены. Проверяли в дебагере - соответствуют ли они тем адресам на которые подключен DMA? inbuffer[i]=0; outbuffer[i]=i+1; Да вообще может я чего-то не понимаю, но как это вы задаете для DMA буфер откуда читать из памяти SDRAM (и то по этому поводу я выше писал), если в системе сопс он подключен к UART. Тогда и подкулючайте порт чтения DMA к той же памяти. Ну и, пожалуй буферы выделяйте через malloc(). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kuzmi4 0 8 мая, 2008 Опубликовано 8 мая, 2008 · Жалоба А вот эти массивы откуда беруться, как объявлены Обявлены до мэйна //---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 подключения - ДМА подключён к уарту и сдрам И что вы имелли ввиду на счёт как это вы задаете для DMA буфер откуда читать из памяти SDRAM Ну и, пожалуй буферы выделяйте через malloc(). Я выставляю в ДМА регистре readaddress откуда читать, в регистре writeaddress - куда писать... И зачем именно malloc() ? Вроде бы уже есть массив volatile alt_u8 ... -- Прицепил весь свой прожект вообсче. Если будет время посмотрите - может что не так... Вот картинки начальных конфигурирования ДМА: data.rar Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vetal 0 8 мая, 2008 Опубликовано 8 мая, 2008 · Жалоба Не можете вы объяснить что значит "обойти кеш" и к чему это? Это значит то, что вы можете писать в память,но данные на самом деле не выйдут за пределы процессора. Также при чтении получите коллизию данных, когда в кэше сидят старые данные, а в памяти новые. Кэш то не знает чего вы там за пределами процессора делаете. При использовании макросов прямого доступа к периферии данные гарантированно выходят за пределы процессора. volatile спасает от оптимизации, но не от кэша! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kuzmi4 0 11 мая, 2008 Опубликовано 11 мая, 2008 · Жалоба 2 vetal - Спасибо. Буду знать. Сегодня пересоздал процессор - дма, цпу, сдрам - результат такой же - дма отрабатывает, а записи в массив нету... Видимо как раз у меня проблема с этим кэшем.. Надо будет пересобрать процессор без кеша на крайний случай... А на счёт макросов обращения к памяти - я ж вроде смотрел в мемори въювере - адреса меняются, всё вроде отрабатывается, только вот в том же въювере не видно изменений в выходном массиве.. То есть запись то в регистры ДМА получается проходит нормально.... Тут есть идея - возможно что когда я повторно считываю данные с массива inbuffer - процюк берёт их с кеша - ведь он уже с ними работал до этого в начале мэйна... А как можно перегрузить данные массива из памяти в кеш ?? :smile3046: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vetal 0 11 мая, 2008 Опубликовано 11 мая, 2008 · Жалоба Работа с кешем: http://altera.com/literature/hb/nios2/n2sw_nii52007.pdf Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RHnd 0 12 мая, 2008 Опубликовано 12 мая, 2008 · Жалоба Работа с кешем: http://altera.com/literature/hb/nios2/n2sw_nii52007.pdf Действительно, попробуйте для эксперимента отключить кеш у проца. Если траблы исчезнкт, то осваивайте работу с кешем. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kuzmi4 0 12 мая, 2008 Опубликовано 12 мая, 2008 · Жалоба Ага! :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 .. Действительно тут немного другой подход... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться