Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: AXI VDMA & VideoInToAXI4-Stream
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Системы на ПЛИС - System on a Programmable Chip (SoPC)
AntLip
Доброго времени суток, Уважаемые форумчане!
Помогите разобраться с некоторыми вопросами:
1. Нужно ли настраивать (инициализировать) ядро Video In To AXI4-Stream или оно само передает информацию без предварительных настроек.
2. Как лучше (основной критерий простота, наверное) инициализировать VDMA (при помощи описанной Programming Sequence в документации или брать код в examples API-функций)
3. Я пробовал вставить примеры, а именно функцию
Код
int run_triple_frame_buffer(XAxiVdma* InstancePtr, int DeviceId, int hsize,int vsize, int buf_base_addr, int number_frame_count,int enable_frm_cnt_intr);

для инициализации, но данные в память не идут (смотрю по вкладке Memory в режиме Debug)
инициализация по документации
Код
void InitializeVDMA(){
    u32        RegVal;
    //reset AXI DMA
    RegVal    = 0x04;
    Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0x30, RegVal);
        //wait reset
    while(RegVal & (1 << 2))
    {
        RegVal    = Xil_In32(XPAR_AXI_VDMA_0_BASEADDR + 0x30);
    }
        //Инициализируем AXI DMA
    RegVal    = Xil_In32(XPAR_AXI_VDMA_0_BASEADDR + 0x30);
    RegVal    = RegVal | 0x1001;
    Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0x30, RegVal);
    RegVal    = Xil_In32(XPAR_AXI_VDMA_0_BASEADDR + 0x30);
        xil_printf("AXI DMA control register value: %x\n\r", RegVal);
    RegVal    = Xil_In32(XPAR_AXI_VDMA_0_BASEADDR + 0x34);
        xil_printf("AXI DMA status register value: %x\n\r", RegVal);
        //Set start  address
    RegVal    = 0x000000;
    Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0xAC, RegVal);
        //Set Frame Delay ???????
    RegVal    = 0x0000000;
    Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0xA8, RegVal);
        //Set Horizontal Size 640
    RegVal    = 0x280;
    Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0xA4, RegVal);
        //Set Vertical Size 480
    RegVal    = 0x1e0;
    Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0xA0, RegVal);
}

Документацию читал, но пока плохо её понимаю.
Буду рад пояснениям, ссылкам, направлениям на цель
Пример инициализации и работы брал из Adam Taylor's chronicles(part 119)
ilyaprok
Если еще актуально
1) не нужно, главное правильно для вашей камеры определить настройки ядра, и подключить сигналы шины vid_io_in согласно документации на это ядро и документации на камеру. Также не забыть притянуть сигналы vid_io_in_ce, aclken, axis_enable к "1".
2) я напрямую с регистрами работал:
Код
    //Сбрасываем ядро AXI VDMA
    RegVal    = 0x04;
    Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0x30, RegVal);
    RegVal    = 0;
    //Дожидаемся окончания сброса ядра
    while(RegVal & (1 << 2))
    {
        RegVal    = Xil_In32(XPAR_AXI_VDMA_0_BASEADDR + 0x30);
    }
    //Сбрасываем флаг прерывания
    RegVal            = Xil_In32(XPAR_AXI_VDMA_0_BASEADDR + 0x34);
    RegVal            = RegVal | 0x1000;
    Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0x34, RegVal);

    //Инициализируем AXI VDMA
    RegVal    = Xil_In32(XPAR_AXI_VDMA_3_BASEADDR + 0x30);
    RegVal    = RegVal | 0x108B;
    Xil_Out32(XPAR_AXI_VDMA_3_BASEADDR + 0x30, RegVal);

    // VDMA Interrupt Init
    status = XScuGic_Connect(IntrC, XPAR_FABRIC_AXI_VDMA_0_S2MM_INTROUT_INTR, (Xil_InterruptHandler)DMA_TransferEnd_Handler, NULL);
    if (status != XST_SUCCESS)
    {
        return XST_FAILURE;
    }
    XScuGic_SetPriorityTriggerType(IntrC, XPAR_FABRIC_AXI_VDMA_0_S2MM_INTROUT_INTR, 0, 3);
    XScuGic_Enable(IntrC, XPAR_FABRIC_AXI_VDMA_0_S2MM_INTROUT_INTR);

        //адрес первого кадра
    Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0xAC, ptrBufFrame);
        //адрес второго кадра
    Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0xAC+4, ptrBufFrame+752*480);
        //адрес третьего кадра
    Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0xAC+8, ptrBufFrame+2*752*480);
        //параметры кадра
    Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0xA8, 752);
    Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0xA4, 752);
    Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0xA0, 480);

Код
#define BUF_NUMBER_FRAME   3
uint8_t ptrBufFrame[752*480*BUF_NUMBER_FRAME]__attribute__((aligned(32)));
void DMA_TransferEnd_Handler(void)
{
    u32        RegValue;
    //Сбрасываем флаг прерывания
    RegValue            = Xil_In32(XPAR_AXI_VDMA_0_BASEADDR + 0x34);
    RegValue            = RegValue | 0x1000;
    Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0x34, RegValue);

       Xil_DCacheFlushRange(((uint32_t)ptrBufFrame + cntFrame*360960), 752*480);
       cntFrame = (cntFrame + 1)%BUF_NUMBER_FRAME;
       //делаем с кадром что-то
    cntIntrDMA++;

}

3) попробуйте в Vivado вставить debug ядро и посмотреть что есть на шинах данных между Video In To AXI4-Stream и VDMA.
Похожую тему можно посмотреть тут:
https://electronix.ru/forum/index.php?showtopic=144296
Но не знаю как делают люди, но у меня проблема с доступом к памяти кадра, так как после получения свежего кадра, процессор читая память на самом деле прочитает данные из кэша, в котором будет мусор либо старые данные, чтобы освежить кэш, нужно использовать функции Xil_DCacheFlushRange либо Xil_DCacheInvalidateRange. В чем разница кстати не понял. однако это занимает время, поэтому свежий кадр можно получить спустя некоторое время (у меня для области 360960 байт - 11 мс). Либо использовать массив для записи в некешируемой области памяти, но тогда с частым обращением к массиву могут быть ощутимы задержки.
Короче я так и не понял как решить вопрос с кешем и DMA, как правильно с ними работать, может знатоки ответят?
ilyaprok
Вообщем если интересно, то проблема с чтением процем памяти, куда кладется инфа с DMA уже давно известна. Тут предлагается несколько путей решения:
1) отключить кэш полностью, тогда будут проблемы с быстродействием всей программы
2) пометить область памяти, куда кладется буфер кадров - некешируемым, тогда пострадает только быстродействие доступа к этому кадру
3) вручную очищать кэш при поступлении новых данных от DMA, перед чтением. (Тут лучше вместо VDMA юзать DMA, тогда при поступлении новой строки, очищаем кеш именно этой строки и таким образом когда последняя строчка будет получена - весь кадр будет закешериван с минимальной задержкой. Однако возрастает нагрузка на проц, так как придется обрабатывать каждую новую строку кадра. Либо юзать VDMA - тогда при получении всего кадра нужно ждать продолжительное время пока не обновится кэш всего кадра )
4) Использовать ACP порт, вместо HP. Тогда кэш будет обновляться сам. Но тут надо смотреть за требуемой скоростью передачи, так как ACP медленyее чем HP.
Вот ссылка на форум:
форум
форум2
а также тесты по скорости HP и ACP портов в прикрепленном файле (взял с того же форума, не помню ссылку)
AntLip
2 ilyaprok
Да, все еще актуально. ,
Спасибо большое за информацию!!!
Вашу тему я читал, но как-то там не понял что и как.
Буду пробовать. Еще раз спасибо!
AntLip
Доброго дня!
Подскажите пожалуйста, правильно ли я понял.


После того как я задал значение VSIZE начинается передача, при условии правильной инициализации и подачи всех сигналов?
И как понять легло ли в память, во вкладке memory я смотрю что лежит по адресам - а там какая-то ерунда.

А вот с ila я пока воюю, не могу нормально наловчиться с ним работать, получается через раз. Может кто-нибудь скинь ссыль, как с ним, ila, работать.
Буду признателен за помощь.
ilyaprok
Цитата
После того как я задал значение VSIZE начинается передача, при условии правильной инициализации и подачи всех сигналов?

Да правильно
Цитата
И как понять легло ли в память, во вкладке memory я смотрю что лежит по адресам - а там какая-то ерунда.

Вы завели прерывание от VDMA? Еще нужно очистить кеш по адресу принятого кадра и подождать милисекунд 100, чтобы наверняка, дальше можно читать память как вы делали.
А вообще для начала надо понять - приходит ли вообще что-нибудь в VDMA, дальше смотреть, работает ли сам VDMA, а потом только смотреть в память. То есть проследить всю цепочку от источника до пункта назначения.
Как я делал:
У меня были проблемы на хардварном уровне, на параллельном интерфейсе камеры - сигнал PIXCLK имел резкие фронты, которые порождали высокие гармоники, из-за чего было воспринято большее кол-во фронтов, чем ожидалось. (лечилось индуктивностью на этом сигнале, зарезались высокие гармоники), то есть желательно смотреть осциллографом все сигналы с камеры. Не должно быть сильно заваленных фронтов или сильных колебаний на фронтах.
Дальше в Vivado посмотреть с ila сигналы приходящие в само ядро Video In To AXI4-Stream, проверить соответсвуют ли сигналы документам на камеру (длительности, кол-во тактов), желательно проследить несколько раз,в разных местах кадра. Если на этом этапе все хорошо, значит первое звено цепочки можно вычеркивать.
Проверить как подключены сигналы из камеры к ядру, мне пришлось лепить несколько логических функция (И, НЕ) для сигналов active video и hblank, vblank, так как камера выдавала инвертированные сигналы.
Дальше посмотреть какой Stream генерит ядро, тоже с помощью ila, сигналы TLAST, TUSER, TVALID, TREADY.
Дальше посмотреть что генерит VDMA, там достаточно наличие хоть какой то деятельности.
Проверить всю настройки VDMA, софтварную и хардварную.
Проверить прогу, чтобы кеш успевал обновляться.
Цитата
А вот с ila я пока воюю, не могу нормально наловчиться с ним работать, получается через раз. Может кто-нибудь скинь ссыль, как с ним, ila, работать.
Буду признателен за помощь.

По-началу тоже были проблемы. Я делал так, перед тем как поменять, удалить какие то сигналы из дебага, я очищал файл констрейтов, где прописаны все дебажные сигналы и ядра ila. дальше в схеме синтеза заново отмечал, создавал ядро ila, синтезировал.
Вот мне добрый человек подсказал, из-за этого тоже могут быть проблемы:
https://electronix.ru/forum/index.php?s=&am...t&p=1530631
AntLip
Цитата
У меня были проблемы на хардварном уровне, на параллельном интерфейсе камеры - сигнал PIXCLK имел резкие фронты, которые порождали высокие гармоники, из-за чего было воспринято большее кол-во фронтов, чем ожидалось. (лечилось индуктивностью на этом сигнале, зарезались высокие гармоники), то есть желательно смотреть осциллографом все сигналы с камеры. Не должно быть сильно заваленных фронтов или сильных колебаний на фронтах.
Дальше в Vivado посмотреть с ila сигналы приходящие в само ядро Video In To AXI4-Stream, проверить соответсвуют ли сигналы документам на камеру (длительности, кол-во тактов), желательно проследить несколько раз,в разных местах кадра. Если на этом этапе все хорошо, значит первое звено цепочки можно вычеркивать.

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

По ila спасибо, буду почитать и пробовать. И еще хотел бы спросить по таймингу, убегают времянки, как с этим бороться, какие причины могут быть?
ilyaprok
Цитата(AntLip @ Mar 12 2018, 13:06) *
У меня не подключена камера, я имитирую камеру. снизу прикреплю скрин структуры. Возможно , что-то неправильно подключил.

Тут не подскажу, но возможно для ядра сигнал active_video требуется нисходящие и восходящие фронты для работы внутренней логики, а не просто константное значение.
документ "AXI4-Stream Video IP and System Design Guide" UG934, там прописаны какие сигналы подавать на ядро. для видео - либо hblank vblank, либо vsync hsync. В моем случае были ~hblank ~vblank, поэтому vsync hsync я просто заземлил. Сигнал active_video должен быть в любом случае.
во картинка из того документа (она есть в моей теме)


Цитата
По ila спасибо, буду почитать и пробовать. И еще хотел бы спросить по таймингу, убегают времянки, как с этим бороться, какие причины могут быть?

Я железо дебажу немного по-другому
вот как тут:
видеоурок
AntLip
Я смотрел это видео, я только не понял как он работал с XMD console, это он симулировал работу SDK? Напрямую писал и читал из памяти?
ilyaprok
Цитата(AntLip @ Mar 14 2018, 12:22) *
Я смотрел это видео, я только не понял как он работал с XMD console, это он симулировал работу SDK? Напрямую писал и читал из памяти?

Напрямую, в нынешней версии SDK нет XMD консоли, щас там что то другое, не помню абривеатуру (что то типа XSCT). немножко другой синтаксис.
команда чтения памяти и запись в файл выглядит так, как пример (0x01000000 360960 - это адрес и кол-во байт соответственно)
mrd -bin -file "D:/Programming/ZYNQ/logs/mem22.raw" 0x01000000 360960
AntLip
Спасибо за ответы.
Я наконец разобрался с ila (по крайней мере, мне удалось увидеть то, что я хотел). Я заметил ошибку и исправил ее, вы были правы, я не выдал там необходимые сигналы.
Теперь информация доходит до vdma. Однако, я хотел бы поинтересоваться
Цитата
, дальше смотреть, работает ли сам VDMA,
как это проверить, посмотреть данные на выходе S2MM?
ilyaprok
Цитата(AntLip @ Mar 16 2018, 15:55) *
Теперь информация доходит до vdma. Однако, я хотел бы поинтересоваться как это проверить, посмотреть данные на выходе S2MM?

У VDMA все стандартно в плане подключения сигналов, поэтому ошибки могут быть на стороне софта (то есть настройки в регистрах). Сами сигналы приходящие на VDMA желательно проверить, должен быть импульс в начале кадра TUSER, импульсы TLAST - в конце строк, так же TVALID и TREADY согласно документам на AXI-STREAM. Есть еще моменты в настройки самих ядер в Vivado, размеры буферов FIFO, ширина шин и т.д. Их нужно устанавливать исходя из скорости потока камеры и размера кадра, я бы ставил по максимуму буферы первое время, но тут я не уверен, надо поиграться.
Дальше можно просто посмотреть что происходит на S2MM, главное чтобы что то было. Используйте тот код, что я кидал, только адаптируйте под параметры вашего кадра, там ошибка была в
Код
    //Инициализируем AXI VDMA
    RegVal    = Xil_In32(XPAR_AXI_VDMA_3_BASEADDR + 0x30);
    RegVal    = RegVal | 0x108B;
    Xil_Out32(XPAR_AXI_VDMA_3_BASEADDR + 0x30, RegVal);
надо вместо XPAR_AXI_VDMA_3_BASEADDR юзать XPAR_AXI_VDMA_0_BASEADDR.
прочитайте кусок памяти командой чтения из предыдущего сообщения
AntLip
Цитата
надо вместо XPAR_AXI_VDMA_3_BASEADDR юзать XPAR_AXI_VDMA_0_BASEADDR.
прочитайте кусок памяти командой чтения из предыдущего сообщения

Я это сразу поправил, спасибо.
А по сигналам... я сейчас решил посмотреть до конца, как и что формируется Спасибо за информацию.
т.е. после инициализации должна начаться передача данных, правильно я понимаю?

Посмотрел. Не формируются на выходе tlast и tuser нету, а tvalid и tready всегда в единице.
AntLip
Посидел я над документацией ядер, над vivado, ila и прочими штуками.
Понял что ничего не понял. Так как информация, данные, через Video In to AXI4-Stream проходят, а сигналы TLAST и TUSER - нет, почему? Не понимаю!
Вот так выглядит времянка на выходе вышеупомянутого ядра ну и design_1_i/axi_vdma_0_M_AXI_S2MM_WDATA[31:0] затесался

Вот так сигналы синхронизации заходят в Video In to AXI4-Stream

Вот так выглядит тестбенч на приблуду, которая иммитирует камеру

Ну,собственно, проект (сигналы на vblank и hblank поданы тут единожды, в других вариациях они вообще не подключены, разницы я не заметил)

А понять кто виноват и что делать не могу, то ли сигналы неправильно подобраны, то ли чего-то не хватает. Может я смотрю в ila и вижу то, что плохой ученик в книге
Подскажите пожалуйста как это довести до ума!
ilyaprok
Цитата(AntLip @ Mar 21 2018, 20:02) *
Ну,собственно, проект (сигналы на vblank и hblank поданы тут единожды, в других вариациях они вообще не подключены, разницы я не заметил)

вот это место я не понял:

Вы не можете просто инвертировать сигнал vsync, посмотрите еще раз вот эту диаграмму, которую я приводил ранее:

считайте, что этот двухмерный прямоугольник в виде кадра с камеры, ядро пересылает построчно слева направо, сверху вниз.
я это вижу примерно так, может ошибся где, но суть в том, что active video - это не инверсия от vsync, как у вас
AntLip
А, до меня, кажется, дошло. Спасибо
AntLip
Вот, у меня получилось.


Данные преодолели vdma, только теперь надо разобраться как они правильно должны лечь в память. Спасибо Большое ilyaprok за помощь.
AntLip
Что-то я не пойму в чем ошибся дальше.
1. На выходе vdma я вижу только 256 пикселей

Код
Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0xA4, 640*16);

в настройках vdma я поменял значение HSIZE( прочитал что может необходимо в битах, хотя есть большие сомнения), после этого стало 256, а ранее на выходе было только 16 пикселей.
Как это исправить, где я накосячил, подскажите пожалуйста?
2. Еще есть вопрос о том, возможно ли передать с помощью vdma по WDATA передать не так как у меня получается (дублируется один и тот же пиксель, видно на изображении, 01000100 ), а так, что бы или бит на транзакцию, а лучше два бита на транзакцию?
3. Про память,я так понимаю, вести речь пока не стоит, ведь там тоже твориться неладное.

Значение HSIZE умножил на 40, тогда получилось что передает все 640 пикселов
AntLip
А с памятью все ровно творится что-то неладное, запись в память при помощи vdma. Почему-то записывает в десять ячеек памяти вместо одной

Может знает кто как это исправить?
AntLip
Я нашел ошибку, дело было в неправильных синхросигналах
AntLip
Может кто-нибудь может подсказать как правильно выбрать частоту работы дизайна если известна частота работы камеры?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.