Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: AVR32: AP7000: Image Sensor Interface (ISI)
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Все остальные микроконтроллеры > AVR32
Busel Roman
Пытаюсь подключить к STK1000 цифровую камеру с использованием имеющегося на борту AP7000 Image Sensor Interface (ISI). Не совсем понимаю, как переключать буферы, в которые будут писаться видеокадры.
Далее нужно вывести на LCD то, что в этих самых буферах находится с использованием встроенного LCD-контроллера (LCDC).

Может кто-нибудь подскажет, как вообще обрабатывается видеоинформация с использованием нескольких буферов.
AndyBig
Цитата
Может кто-нибудь подскажет, как вообще обрабатывается видеоинформация с использованием нескольких буферов.

Скажем, два буфера. Пока в первый пишутся данные с камеры, со второго выводится изображение на ЖКИ. При заполнении камерой первого буфера, она переключается на второй буфер, начиная его заполнять, а на ЖК выводится свежеснятое изображение из первого буфера... И так по циклу туда-сюда smile.gif
Правда про AVR32 подсказать не могу - реализовано там это аппаратно или надо самому следить за переключением буферов...
Busel Roman
Цитата(AndyBig @ Jan 13 2008, 00:52) *
Скажем, два буфера. Пока в первый пишутся данные с камеры, со второго выводится изображение на ЖКИ. При заполнении камерой первого буфера, она переключается на второй буфер, начиная его заполнять, а на ЖК выводится свежеснятое изображение из первого буфера... И так по циклу туда-сюда smile.gif
Я себе так все и представлял, но в AP7000 такой прикол:

В ISI есть регистр, хранящий адрес ячейки памяти, где находится адрес буфера. То есть, в этом регистре хранится указатель на буфер. При заполнении первого буфера, указатель инкрементируется на 32 бита и указывает уже на адрес второго буфера. Соответственно, адреса всех буферов нужно предварительно записать в соответствующие ячейки памяти. Интересно, что нигде не указывается, сколько всего используется буферов.

В LCDC есть только один регистр, в котором сразу указывается адрес единственного буфера.
AndyBig
Заглянул сейчас в даташит, вроде бы там все расписано под Вашу задачу smile.gif.
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 бита

Нет, он не тупо инкрементируется, он берет адрес следующего буфера из описателя текущего буфера smile.gif.
Цитата
Соответственно, адреса всех буферов нужно предварительно записать в соответствующие ячейки памяти.

Естественно, нужно сначала подготовить описатели всех буферов и зарезервировать соответственно память под сами буфера.
Цитата
Интересно, что нигде не указывается, сколько всего используется буферов

Сколько Вашей душе пожелается smile.gif. И на сколько хватит памяти, естественно smile.gif.

Цитата
В LCDC есть только один регистр, в котором сразу указывается адрес единственного буфера.

Вот его и меняем после каждого кадра по прерыванию...
Естественно, что частоту фреймов ISI и LCDC необходимо синхронизировать.
Busel Roman
Спасибо тебе, добрый человек!
Когда первый раз читал datasheet на LCDC пару месяцев назад, как-то упустил из виду этот пункт - наверное, подумал, что это относится к "2D Memory Addressing". Теперь стало еще понятнее.

А как думаете, зачем проверять регистр DMAFRMPTх на наличие достаточного количества времени на изменение DMA Base Address Register, ведь можно просто изменять его по приходу прерывания End Of Frame?
AndyBig
Цитата
А как думаете, зачем проверять регистр DMAFRMPTх на наличие достаточного количества времени на изменение DMA Base Address Register, ведь можно просто изменять его по приходу прерывания End Of Frame?

Там просто описано два варианта: один без прерывания, проверяя достаточно ли времени для апдейта регистра, второй с использованием прерывания. И это в основном относится к панелям с двойным сканированием (Dual Scan Panels), когда надо апдейтить оба указателя буферов одновременно smile.gif
Busel Roman
Еще вот такой вопрос:

Как в С получить численное значение адреса, хранящегося в указателе. Дело в том, что в регистр ISI PPFBD (поле PREV_FBD_ADDR) необходимо записать фактический адрес первого дескриптора кадрового буфера в формате integer.

Как я понимаю, значение одного указателя можно присвоить другому указателю, если указатель-приемник указывает на тот же тип данных, что и указатель-источник.
dimitryl
char *buf; // указатель
int adr=(unsigned int)buf; // получаем значение указателя

int *pInt=(int*)buf; // приводим указатель к типу int*
Busel Roman
А как можно установить определенный диапазон адресов для значений указателя? То есть, чтобы определенный указатель мог указывать только на память, например, с адреса 0х10000000 по 0х20000000.
dimitryl
Указатель это просто переменная, если нужно чтоб он не выходил за определенные границы - его надо контролировать.
Busel Roman
Цитата(dimitryl @ Jan 16 2008, 13:35) *
Указатель это просто переменная, если нужно чтоб он не выходил за определенные границы - его надо контролировать.
Я и спрашиваю, как сказать указателю, чтобы он адресовал только определенный участок памяти? Например, я хочу, чтобы кадровые буферы у меня находились во внешней SDRAM, а остальные переменные хранились во внутренней SRAM.

Не буду же я каждый раз создавать новый указатель, если только что созданный указатель адресует не ту область оперативной памяти. И так до тех пор, пока не будет создан "правильный" указатель.
dimitryl
Самый простой способ - статически выделить память под эти буфера.

в случае динамического выделения памяти из кучи (как у вас, если я правильно понял) нужно будет переписывать фукции работающие с памятью (malloc/calloc/new....).

Установить какие-либо определенные границы для указателя нельзя(.
Busel Roman
Цитата(dimitryl @ Jan 16 2008, 16:19) *
Самый простой способ - статически выделить память под эти буфера.
Если не трудно - кусок кода приведите, в общих чертах.

А вообще, как в С организовать доступ к требуемому типу памяти - SRAM, SDRAM, FLASH, если они имеют каждая свой диапазон адресов? Например, как записать конкретное целое число в конкретную ячейку SDRAM?
AndyBig
У каждого типа памяти свое заранее известное адресное пространство.
Во-первых, Вы можете указать статической переменной (тому же буферу) абсолютный адрес, по которому она должна располагаться оператором @. Например:
Код
__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" smile.gif
Busel Roman
Программирую в среде AVR32Studio. Она использует GCC.

Кто знает, направьте, куда смотреть, какие файлы содержат описание "Controling data placement in memory"?

А также, где найти какие и как в GCC применяются директивы (может дополнительные знаки, типа @) при управлении распределением памяти.
singlskv
Цитата(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,...
Busel Roman
Цитата(singlskv @ Jan 16 2008, 23:21) *
ну и линкеру не забываем указать где находятся эти Ваши секции mysect1,mysect2,...
Я прошу прощения за глупые вопросы, но как это указать линкеру?

Может для AP7000 где-то в файлах GCC уже указаны все возможные адресные пространства (согласно datasheet на этот микроконтроллер). Я всего-лишь хочу создать кадровый буфер во внешней SDRAM, подключенной аппаратно в моем STK1000.
singlskv
Цитата(Busel Roman @ Jan 17 2008, 11:01) *
Я прошу прощения за глупые вопросы, но как это указать линкеру?

-Wl,--section-start=mysect=0x10000000
ну или другой нужный адрес подставить
Цитата
Может для AP7000 где-то в файлах GCC уже указаны все возможные адресные пространства

В хидерах на AP7000 ищите такие дефайны:
AVR32_EBI1_ADDRESS
Busel Roman
Цитата(singlskv @ Jan 17 2008, 10:49) *
В хидерах на AP7000 ищите такие дефайны:
AVR32_EBI1_ADDRESS

Спасибо, нашел - то что требовалось. Файл "ap7000.h"

Только вот что-то все-равно не так. Где бы почитать про аттрибуты GCC?
singlskv
Цитата(Busel Roman @ Jan 17 2008, 12:54) *
Только вот что-то все-равно не так. Где бы почитать про аттрибуты GCC?
А что не так ?
Посмотрите в файле gcc.info
ну или погуглите по словам __attribute__ section

P.S. А Вы SDRAM инициализируете ?
Busel Roman
Цитата(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);
Собственно, я про это и спрашивал.

Всем СПАСИБО за помощь!
singlskv
Цитата(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, тем быстрее потом будете
осваивать написание вышеперечисленных "нужно"....
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.