|
AVR32: AP7000: Image Sensor Interface (ISI), Как переключаются буферы видеокадров? |
|
|
|
Jan 12 2008, 13:39
|
Участник

Группа: Новичок
Сообщений: 51
Регистрация: 19-06-07
Из: Республика Беларусь, г.Витебск
Пользователь №: 28 538

|
Пытаюсь подключить к STK1000 цифровую камеру с использованием имеющегося на борту AP7000 Image Sensor Interface (ISI). Не совсем понимаю, как переключать буферы, в которые будут писаться видеокадры. Далее нужно вывести на LCD то, что в этих самых буферах находится с использованием встроенного LCD-контроллера (LCDC).
Может кто-нибудь подскажет, как вообще обрабатывается видеоинформация с использованием нескольких буферов.
Сообщение отредактировал Busel Roman - Jan 12 2008, 13:40
|
|
|
|
|
Jan 14 2008, 07:27
|
Участник

Группа: Новичок
Сообщений: 51
Регистрация: 19-06-07
Из: Республика Беларусь, г.Витебск
Пользователь №: 28 538

|
Цитата(AndyBig @ Jan 13 2008, 00:52)  Скажем, два буфера. Пока в первый пишутся данные с камеры, со второго выводится изображение на ЖКИ. При заполнении камерой первого буфера, она переключается на второй буфер, начиная его заполнять, а на ЖК выводится свежеснятое изображение из первого буфера... И так по циклу туда-сюда  Я себе так все и представлял, но в AP7000 такой прикол: В ISI есть регистр, хранящий адрес ячейки памяти, где находится адрес буфера. То есть, в этом регистре хранится указатель на буфер. При заполнении первого буфера, указатель инкрементируется на 32 бита и указывает уже на адрес второго буфера. Соответственно, адреса всех буферов нужно предварительно записать в соответствующие ячейки памяти. Интересно, что нигде не указывается, сколько всего используется буферов. В LCDC есть только один регистр, в котором сразу указывается адрес единственного буфера.
|
|
|
|
|
Jan 14 2008, 08:30
|

Иногдящий
   
Группа: Свой
Сообщений: 691
Регистрация: 28-02-05
Пользователь №: 2 931

|
Заглянул сейчас в даташит, вроде бы там все расписано под Вашу задачу  . LCD: читаем стр. 735 - 35.9 Double buffer Technique В общих чертах: изначально задаем в DMA-регистре адрес первого буфера, запускаем интерфейс LCD, по прерыванию End Of Frame меняем в DMA-регистрах адрес буфера на второй буфер. Следующий цикл DMA уже пойдет из второго буфера. ISI: читаем стр. 783 - 36.4.4.4 FIFO and DMA Features (Prewiev Patch) В общих чертах: создаем связанный список (linked list) описателей буферов (FBD - Frame Buffer Descriptors) - два, три, сколько угодно, указываем в DMA-регистре адрес первого FBD и запускам ISI. Все, он автоматически будет писать фреймы поочередно во все эти буфера. Цитата При заполнении первого буфера, указатель инкрементируется на 32 бита Нет, он не тупо инкрементируется, он берет адрес следующего буфера из описателя текущего буфера  . Цитата Соответственно, адреса всех буферов нужно предварительно записать в соответствующие ячейки памяти. Естественно, нужно сначала подготовить описатели всех буферов и зарезервировать соответственно память под сами буфера. Цитата Интересно, что нигде не указывается, сколько всего используется буферов Сколько Вашей душе пожелается  . И на сколько хватит памяти, естественно  . Цитата В LCDC есть только один регистр, в котором сразу указывается адрес единственного буфера. Вот его и меняем после каждого кадра по прерыванию... Естественно, что частоту фреймов ISI и LCDC необходимо синхронизировать.
|
|
|
|
|
Jan 14 2008, 09:32
|
Участник

Группа: Новичок
Сообщений: 51
Регистрация: 19-06-07
Из: Республика Беларусь, г.Витебск
Пользователь №: 28 538

|
Спасибо тебе, добрый человек! Когда первый раз читал datasheet на LCDC пару месяцев назад, как-то упустил из виду этот пункт - наверное, подумал, что это относится к "2D Memory Addressing". Теперь стало еще понятнее.
А как думаете, зачем проверять регистр DMAFRMPTх на наличие достаточного количества времени на изменение DMA Base Address Register, ведь можно просто изменять его по приходу прерывания End Of Frame?
|
|
|
|
|
Jan 16 2008, 07:34
|
Участник

Группа: Новичок
Сообщений: 51
Регистрация: 19-06-07
Из: Республика Беларусь, г.Витебск
Пользователь №: 28 538

|
Еще вот такой вопрос:
Как в С получить численное значение адреса, хранящегося в указателе. Дело в том, что в регистр ISI PPFBD (поле PREV_FBD_ADDR) необходимо записать фактический адрес первого дескриптора кадрового буфера в формате integer.
Как я понимаю, значение одного указателя можно присвоить другому указателю, если указатель-приемник указывает на тот же тип данных, что и указатель-источник.
Сообщение отредактировал Busel Roman - Jan 16 2008, 07:35
|
|
|
|
|
Jan 16 2008, 08:01
|
Участник

Группа: Участник
Сообщений: 17
Регистрация: 13-11-05
Пользователь №: 10 786

|
char *buf; // указатель int adr=(unsigned int)buf; // получаем значение указателя
int *pInt=(int*)buf; // приводим указатель к типу int*
Сообщение отредактировал dimitryl - Jan 16 2008, 08:14
|
|
|
|
|
Jan 16 2008, 09:52
|
Участник

Группа: Новичок
Сообщений: 51
Регистрация: 19-06-07
Из: Республика Беларусь, г.Витебск
Пользователь №: 28 538

|
А как можно установить определенный диапазон адресов для значений указателя? То есть, чтобы определенный указатель мог указывать только на память, например, с адреса 0х10000000 по 0х20000000.
|
|
|
|
|
Jan 16 2008, 11:35
|
Участник

Группа: Участник
Сообщений: 17
Регистрация: 13-11-05
Пользователь №: 10 786

|
Указатель это просто переменная, если нужно чтоб он не выходил за определенные границы - его надо контролировать.
|
|
|
|
|
Jan 16 2008, 13:27
|
Участник

Группа: Новичок
Сообщений: 51
Регистрация: 19-06-07
Из: Республика Беларусь, г.Витебск
Пользователь №: 28 538

|
Цитата(dimitryl @ Jan 16 2008, 13:35)  Указатель это просто переменная, если нужно чтоб он не выходил за определенные границы - его надо контролировать. Я и спрашиваю, как сказать указателю, чтобы он адресовал только определенный участок памяти? Например, я хочу, чтобы кадровые буферы у меня находились во внешней SDRAM, а остальные переменные хранились во внутренней SRAM. Не буду же я каждый раз создавать новый указатель, если только что созданный указатель адресует не ту область оперативной памяти. И так до тех пор, пока не будет создан "правильный" указатель.
|
|
|
|
|
Jan 16 2008, 14:19
|
Участник

Группа: Участник
Сообщений: 17
Регистрация: 13-11-05
Пользователь №: 10 786

|
Самый простой способ - статически выделить память под эти буфера.
в случае динамического выделения памяти из кучи (как у вас, если я правильно понял) нужно будет переписывать фукции работающие с памятью (malloc/calloc/new....).
Установить какие-либо определенные границы для указателя нельзя(.
|
|
|
|
|
Jan 16 2008, 14:42
|
Участник

Группа: Новичок
Сообщений: 51
Регистрация: 19-06-07
Из: Республика Беларусь, г.Витебск
Пользователь №: 28 538

|
Цитата(dimitryl @ Jan 16 2008, 16:19)  Самый простой способ - статически выделить память под эти буфера. Если не трудно - кусок кода приведите, в общих чертах. А вообще, как в С организовать доступ к требуемому типу памяти - SRAM, SDRAM, FLASH, если они имеют каждая свой диапазон адресов? Например, как записать конкретное целое число в конкретную ячейку SDRAM?
|
|
|
|
|
Jan 16 2008, 15:22
|

Иногдящий
   
Группа: Свой
Сообщений: 691
Регистрация: 28-02-05
Пользователь №: 2 931

|
У каждого типа памяти свое заранее известное адресное пространство. Во-первых, Вы можете указать статической переменной (тому же буферу) абсолютный адрес, по которому она должна располагаться оператором @. Например: Код __no_init unsigned int LCD_BUFFER1[1024] @ 0x20000000 __no_init unsigned int LCD_BUFFER2[1024] @ 0x20000400 Этот примр создаст две статических переменных - массивы по 1024 беззнаковых интовых значений. А во-вторых можете указать не конкретный адрес, а только сегмент, внутри которого линкер уже сам выберет место размещения: Код __no_init unsigned int LCD_BUFFER1[1024] @ "SDRAM_SEGMENT" __no_init unsigned int LCD_BUFFER2[1024] @ "SDRAM_SEGMENT" Это создаст две статические переменные - буфера - в сегменте SDRAM_SEGMENT по адресу, выбранному линкером. Для ограничения адресного пространства Вы можете просто определить свой сегмент с заданными адресными границами и при создании переменных указывать его. Это все справедливо для IAR ARM, но нечто подобное должно быть и в других средах. Смотрите хелп на компилятор, раздел наподобие "Controling data placement in memory"
|
|
|
|
|
Jan 16 2008, 16:05
|
Участник

Группа: Новичок
Сообщений: 51
Регистрация: 19-06-07
Из: Республика Беларусь, г.Витебск
Пользователь №: 28 538

|
Программирую в среде AVR32Studio. Она использует GCC.
Кто знает, направьте, куда смотреть, какие файлы содержат описание "Controling data placement in memory"?
А также, где найти какие и как в GCC применяются директивы (может дополнительные знаки, типа @) при управлении распределением памяти.
|
|
|
|
|
Jan 16 2008, 21:21
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(Busel Roman @ Jan 16 2008, 19:05)  Программирую в среде AVR32Studio. Она использует GCC. Кто знает, направьте, куда смотреть, какие файлы содержат описание "Controling data placement in memory"? А также, где найти какие и как в GCC применяются директивы (может дополнительные знаки, типа @) при управлении распределением памяти. В gcc пишут так int myvar __attribute__((section("mysect1"))); char myarr[256] __attribute__((section("mysect2"))); ну и линкеру не забываем указать где находятся эти Ваши секции mysect1,mysect2,...
|
|
|
|
|
Jan 17 2008, 08:01
|
Участник

Группа: Новичок
Сообщений: 51
Регистрация: 19-06-07
Из: Республика Беларусь, г.Витебск
Пользователь №: 28 538

|
Цитата(singlskv @ Jan 16 2008, 23:21)  ну и линкеру не забываем указать где находятся эти Ваши секции mysect1,mysect2,... Я прошу прощения за глупые вопросы, но как это указать линкеру? Может для AP7000 где-то в файлах GCC уже указаны все возможные адресные пространства (согласно datasheet на этот микроконтроллер). Я всего-лишь хочу создать кадровый буфер во внешней SDRAM, подключенной аппаратно в моем STK1000.
Сообщение отредактировал Busel Roman - Jan 17 2008, 08:02
|
|
|
|
|
Jan 17 2008, 08:49
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(Busel Roman @ Jan 17 2008, 11:01)  Я прошу прощения за глупые вопросы, но как это указать линкеру? -Wl,--section-start=mysect=0x10000000 ну или другой нужный адрес подставить Цитата Может для AP7000 где-то в файлах GCC уже указаны все возможные адресные пространства В хидерах на AP7000 ищите такие дефайны: AVR32_EBI1_ADDRESS
|
|
|
|
|
Jan 17 2008, 09:54
|
Участник

Группа: Новичок
Сообщений: 51
Регистрация: 19-06-07
Из: Республика Беларусь, г.Витебск
Пользователь №: 28 538

|
Цитата(singlskv @ Jan 17 2008, 10:49)  В хидерах на AP7000 ищите такие дефайны: AVR32_EBI1_ADDRESS Спасибо, нашел - то что требовалось. Файл "ap7000.h" Только вот что-то все-равно не так. Где бы почитать про аттрибуты GCC?
|
|
|
|
|
Jan 17 2008, 10:50
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(Busel Roman @ Jan 17 2008, 12:54)  Только вот что-то все-равно не так. Где бы почитать про аттрибуты GCC? А что не так ? Посмотрите в файле gcc.info ну или погуглите по словам __attribute__ section P.S. А Вы SDRAM инициализируете ?
|
|
|
|
|
Jan 17 2008, 13:33
|
Участник

Группа: Новичок
Сообщений: 51
Регистрация: 19-06-07
Из: Республика Беларусь, г.Витебск
Пользователь №: 28 538

|
Цитата(singlskv @ Jan 17 2008, 12:50)  А что не так ? Посмотрите в файле gcc.info ну или погуглите по словам __attribute__ section
P.S. А Вы SDRAM инициализируете ? Из gcc.info: Код `section ("SECTION-NAME")' Normally, the compiler places the code it generates in the `text' section. Sometimes, however, you need additional sections, or you need certain particular functions to appear in special sections. The `section' attribute specifies that a function lives in a particular section. For example, the declaration:
extern void foobar (void) __attribute__ ((section ("bar")));
puts the function `foobar' in the `bar' section.
Some file formats do not support arbitrary sections so the `section' attribute is not available on all platforms. If you need to map the entire contents of a module to a particular section, consider using the facilities of the linker instead. Все верно, но не так явно указывается, как мне хотелось бы. SDRAM, конечно, инициализирую. Я взял AppNote для LCDC. На базе его делаю свою программу для вывода видеоизображения с ISI на LCD. При более детальном рассмотрении данного AppNote, нашел как они присваивают указателю определенное значение: Код unsigned char * framePtr = (unsigned char *) (lcdc_conf->dmabaddr1 | 0xA0000000); Собственно, я про это и спрашивал. Всем СПАСИБО за помощь!
|
|
|
|
|
Jan 17 2008, 16:12
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(Busel Roman @ Jan 17 2008, 16:33)  Из gcc.info: ...................... SDRAM, конечно, инициализирую. Я взял AppNote для LCDC. На базе его делаю свою программу для вывода видеоизображения с ISI на LCD. При более детальном рассмотрении данного AppNote, нашел как они присваивают указателю определенное значение: Код unsigned char * framePtr = (unsigned char *) (lcdc_conf->dmabaddr1 | 0xA0000000); Собственно, я про это и спрашивал. Это конечно работает, в качестве аппноута, только все равно когда программа начнет разрастаться, Вам придеться разбираться с section. На этом проце SRAM не такая уж и большая и предполагается что в ней должны жить всякие очень быстродоступные вещи типа обработчиков прерываний, важных для общей производительности переменных(например семафоры, мьютексы,....) , и т.д. Все остальное должно храниться в SDRAM(в том числе и обычные переменные и особенно массивы). И вот здесь, без подробного разбирательства с sections не обойтись. Вам нужно написать инициализацию SDRAM в определенной секции .initX , нужно написать процедуру копирования инициализированных данных из флеш в SDRAM, нужно написать процедуру обнуления всех неинициализированных переменных, нужно написать процедуру переноса "быстрого" кода в SRAM и "медленного" в SDRAM, и т.д. Так что чем раньше Вы начнете разбираться с sections, тем быстрее потом будете осваивать написание вышеперечисленных "нужно"....
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|