Easyelectronics.ru

Электроника для всех
Текущее время: 19 окт 2019, 00:04

Часовой пояс: UTC + 5 часов



JLCPCB – Прототипы печатных плат за $2/10pcs (Любой цвет!)
Крупнейший производитель печатных плат и прототипов. Более 600000 клиентов и свыше 10000 заказов в день!
Получите скидку на почтовую отправку при первом заказе в JLCPCB!

Начать новую тему Ответить на тему  [ Сообщений: 20 ] 
Автор Сообщение
 Заголовок сообщения: IAR. Медленное заполнение двумерного массива.
СообщениеДобавлено: 17 авг 2017, 06:47 
Старожил

Зарегистрирован: 18 июл 2016, 21:17
Сообщения: 746
F4 работает на 16 МГц. Имеется байтовый массив 480*272 точки. Если последовательно перебором строк и столбцов записывать какое то значение, то заполнение всего массива занимает 0.5 с. А если использовать функцию memset, то 0.005 с.
Почему возникает такая разница по времени и как от нее избавиться? (Ну т.е. не чтобы memset работала медленнее, а чтобы запись в массив в любую точку ускорилась :) )


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: IAR. Медленное заполнение двумерного массива.
СообщениеДобавлено: 17 авг 2017, 09:26 
Старожил
Аватара пользователя

Зарегистрирован: 22 июл 2017, 11:48
Сообщения: 3646
На 16 МГц работать с таким дисплеем - эт конечно очень смелое решение :))
Во-вторых, включите оптимизацию повыше уровнем. Или работайте по указателям: *ptr_array++ = var
В-третьих, memset - встроенная функция, которая всегда медленнее прямой реализации, но благодаря указателям, работает быстрее, чем по индексации массива.
Ускорить запись по произвольному индексу элемента? Включение оптимизации и не применение встроенных функций. Однако, одиночные записи всегда будут медленнее, чем запись непрерывного блока.

Вот вам наглядное сравнение (без оптимизации!) длинны цикла при работе с индексами массива и при работе с memset:


Вложения:
Без-имени-1.png
Без-имени-1.png [ 105.77 Кб | Просмотров: 2015 ]
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: IAR. Медленное заполнение двумерного массива.
СообщениеДобавлено: 18 авг 2017, 03:30 
Старожил

Зарегистрирован: 18 июл 2016, 21:17
Сообщения: 746
Если использовать указатель и поставить макс оптимтзацию, то скорость увеличивается раз в 10, но все еще раз в 10 медленнее,чем memset.
Возможно, я что то изначально не так делаю? Мне надо будет, например, закрашивать большие фигуры сложной формы, но даже при увеличении частоты до максимальной, получается,что fps будет слишком маленьким...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: IAR. Медленное заполнение двумерного массива.
СообщениеДобавлено: 18 авг 2017, 03:35 
Старожил
Аватара пользователя

Зарегистрирован: 23 янв 2012, 00:31
Сообщения: 1797
Откуда: Новокузнецк
Тут код смотреть нужно

_________________
elisey.su


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: IAR. Медленное заполнение двумерного массива.
СообщениеДобавлено: 18 авг 2017, 07:56 
Старожил
Аватара пользователя

Зарегистрирован: 18 май 2013, 20:43
Сообщения: 4340
Откуда: Кемеровская область, Киселевск
dma надо подключать и заранее еще можно в озу или флеш чтото построить а потом через дма гнать. через проц всегда медленно.

_________________
RADIOWOLF.RU


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: IAR. Медленное заполнение двумерного массива.
СообщениеДобавлено: 18 авг 2017, 08:02 
Старожил
Аватара пользователя

Зарегистрирован: 22 июл 2017, 11:48
Сообщения: 3646
Почему memset работает быстрее - я ж уже показал - в его цикле гораздо меньше инструкций.

А по поводу заливки прямоугольников - ну у вас же F4xx, а у него есть DMA2D, или по-другому, Chrom-Art - видеоакселератор, предназначенный как раз для таких групповых операций. Его возможности вполне хороши, позволяют даже смешивать слои с преобразованием цветовых моделей.

Кстати говоря.. Если у вас размер дисплея 480*272, и вы используете не 8-битный цвет, а 16- или 24-битный, то у вас размера встроенной оперативки не хватит, и вам придется либо готовить картинку по частям, либо размещать бидеобуфер в SDRAM.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: IAR. Медленное заполнение двумерного массива.
СообщениеДобавлено: 18 авг 2017, 08:13 
Старожил
Аватара пользователя

Зарегистрирован: 18 май 2013, 20:43
Сообщения: 4340
Откуда: Кемеровская область, Киселевск
научиться, если захочет )))

_________________
RADIOWOLF.RU


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: IAR. Медленное заполнение двумерного массива.
СообщениеДобавлено: 19 авг 2017, 02:49 
Старожил

Зарегистрирован: 18 июл 2016, 21:17
Сообщения: 746
elisey писал(а):
Тут код смотреть нужно

BusMaster уже фактически привел код. Мегареспект ему, он с полуслова понял не только всю проблему, но и тонкости работы устройства!
Т.е. простейшая вещь - сначала инициализация LTDC, потом сразу же пишем в видео память (внутреннее ОЗУ) любую информацию.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: IAR. Медленное заполнение двумерного массива.
СообщениеДобавлено: 19 авг 2017, 02:51 
Старожил

Зарегистрирован: 18 июл 2016, 21:17
Сообщения: 746
Oxford писал(а):
dma надо подключать и заранее еще можно в озу или флеш чтото построить а потом через дма гнать. через проц всегда медленно.

В том то и дело, что это вот построение в ОЗУ идет слишком медленно. ДМА не нужно, т.к. видеопамять является внутренним ОЗУ.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: IAR. Медленное заполнение двумерного массива.
СообщениеДобавлено: 19 авг 2017, 02:56 
Старожил

Зарегистрирован: 18 июл 2016, 21:17
Сообщения: 746
BusMaster писал(а):
Почему memset работает быстрее - я ж уже показал - в его цикле гораздо меньше инструкций.

А по поводу заливки прямоугольников - ну у вас же F4xx, а у него есть DMA2D, или по-другому, Chrom-Art - видеоакселератор, предназначенный как раз для таких групповых операций. Его возможности вполне хороши, позволяют даже смешивать слои с преобразованием цветовых моделей.

Кстати говоря.. Если у вас размер дисплея 480*272, и вы используете не 8-битный цвет, а 16- или 24-битный, то у вас размера встроенной оперативки не хватит, и вам придется либо готовить картинку по частям, либо размещать бидеобуфер в SDRAM.

Именно 8-ми битный цвет! :) Вернее, 8-ми битный формат видео памяти, при 18-ти битной шине к дисплею. 18 бит позволяют получить 64 градации серого и еще остается по 32 градации на каждый цвет. Вариант с внешней памятью я пока побоялся заказывать, и как показал опыт, не зря :)
Мне надо будет закрашивать не прямоугольники, а фигуры сложной формы. Про memset я понял, спасибо вам!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: IAR. Медленное заполнение двумерного массива.
СообщениеДобавлено: 19 авг 2017, 02:59 
Старожил

Зарегистрирован: 18 июл 2016, 21:17
Сообщения: 746
Oxford писал(а):
научиться, если захочет )))

В том то и дело, что хотелось бы решить проблему легко и просто. Была надежда, что я не сделал какую нибудь хитрую инициализацию памяти и она работает медленно :)
А теперь придется изучать асм, чтобы понять, что там делает компилятор. Да еще и замаячила перспектива переписи на него графической библиотеки...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: IAR. Медленное заполнение двумерного массива.
СообщениеДобавлено: 19 авг 2017, 20:45 
Старожил
Аватара пользователя

Зарегистрирован: 22 июл 2017, 11:48
Сообщения: 3646
Там надо не только инициализовать LTDC, но и создать слой некоторого размера. И этот слой может иметь 8-битную цветовую модель, например L8. Загружаем таблицу индексных цветов (CLUT). Можем выбрать любые 256 полноразмерных цветов, которые потом будут выводиться по 8-битному индексу. Без загрузки CLUT инфа будет представлена в оттенках серого.

Даже обычный ДМА (для F4 - только контроллер DMA2) может работать в режиме передачи из-памяти-в-память (memory to memory). В этом случае адрес источника указывается в регистре адреса периферии, а получатель - в регистре адреса памяти. Для того, чтобы скопировать одно значение в некоторый диапазон адресов, нужно установить инкремент адресов памяти MINC и отключить инкремент адресов периферии PINC. Получается что-то в роде "один ко многим".

Заливку непрямоугольных фигур лучше выполнять по строкам, "от" и "до". Максимальная пиксельная скорость заливки в режиме DMA равна скорости работы AHB-шины. Поскольку DMA работает параллельно и независимо от инструкций ядра, то пока идет заливка строки, можно рассчитать начальн. точку и длину для следующей строки, и, дождавшись окончания заливки, переключить DMA на следующую строку и начать ее заливку.

Примерно похожий результат дает видеоакселератор DMA2D, но еще добавляет преобразование цветовых моделей и дополнительное смешивание слоев, с поддержкой альфа-канала (прозрачности). DMA2D хорошо работает при декодировании bmp-изображений с альфа-каналом. Типичный практический пример - наложение каких-либо непрямоугольных значков, иконок, графических элементов.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: IAR. Медленное заполнение двумерного массива.
СообщениеДобавлено: 20 авг 2017, 13:38 
Старожил

Зарегистрирован: 11 сен 2012, 11:19
Сообщения: 5690
BusMaster писал(а):
дождавшись окончания заливки, переключить DMA на следующую строку и начать ее заливку.
//cut
Примерно похожий результат дает видеоакселератор DMA2D,


Ты забыл добавить, что DMA2D автоматом высчитывает offset следующей строки ...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: IAR. Медленное заполнение двумерного массива.
СообщениеДобавлено: 21 авг 2017, 00:47 
Старожил

Зарегистрирован: 18 июл 2016, 21:17
Сообщения: 746
А, вот использовать дма для заливки строк, это мне кажется очень интересная идея! А вот если допустим надо взять строку, каждую точку как то обработать, типа умножить на коэф и/или сложить/вычесть. Так можно сделать без участия процессора?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: IAR. Медленное заполнение двумерного массива.
СообщениеДобавлено: 21 авг 2017, 08:05 
Старожил
Аватара пользователя

Зарегистрирован: 22 июл 2017, 11:48
Сообщения: 3646
А вот градиентные заливки акселератор делать не умеет. Но для этого можно использовать битмапы, а уж декодирование битмапов акселератор может выполнять самостоятельно. Правда, вот большого размера битмапы занимают немало места.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: IAR. Медленное заполнение двумерного массива.
СообщениеДобавлено: 21 авг 2017, 14:17 
Заглядывает иногда

Зарегистрирован: 09 июл 2011, 00:18
Сообщения: 61
Скорость работы memset будет на порядок выше простого перебора с любой оптимизацией. Не стоит забывать, что для встроенных функций учитываются аппаратные особенности реализации платформы. В частности, ARM может использовать регистры FPU для ускорения операций копирования/заполнения массива.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: IAR. Медленное заполнение двумерного массива.
СообщениеДобавлено: 21 авг 2017, 19:25 
Старожил
Аватара пользователя

Зарегистрирован: 22 июл 2017, 11:48
Сообщения: 3646
Да, но что может сравниться по скорости с заполнением через DMA2D? :) Закрашивание выполняется на скорости шины AHB, либо на скорости шины SDRAM, в случае с расположением видеопамяти во внешней ОЗУ.

Для однотонного закрашивания прямоугольных областей реализация проста до безобразия:
- выбрать режим register-to-memory в регистре конфигурации CR
- выбрать цветовую модель (формат пикселей) на выходе. должна соответствовать цветовой модели слоя
- установить цвет, которым будет залит прямоугольник
- установить начальный адрес в видеобуфере. соответствует координатам X-Y дисплея (точнее, координатам относительно слоя)
- установить размеры прямоугольника для заливки: число пикселей в строке (Х-координата), число строк (Y-координата) и смещение строк, то есть число пикселей до начала прямоугольника в следующей строке
- установить бит Start и дождаться окончания заполнения либо по прерыванию или флагу, либо по автом.сбросу бита Start
Всё!

Но есть и ограничения:
- акселератор не может выводить в 8-битный слой. На выходе может быть только 16/24/32 бита, то есть модели RGB888, ARGB8888, ARGB1555, RGB565, ARGB4444. Индексных цветов на выходе не будет.
- закрашивать может только прямоугольные области и рисовать гориз./вертик. линии.
Зато просто офигенная скорость, недоступная любому другому методу.

Код:
  RCC->AHB1ENR |= RCC_AHB1ENR_DMA2DEN;

  DMA2D->CR = DMA2D_CR_MODE;         // Reg->Mem Mode
  DMA2D->OPFCCR = 1;                 // Output Color = RGB888
  DMA2D->OCOLR = 0x00FF0000;         // Цвет заливки = красный (RGB888)

  uint8_t *pointer = gram_baselay;   // указатель на видеобуфер
  pointer += 50 * 3 + 480 * 10 * 3;  // Xs = 50, Ys = 10, WidthLine = 480, BytePerPix = 3
  DMA2D->OMAR = (uint32_t)pointer;   // адрес координат начала прямоугольника
  DMA2D->NLR = 150 << 16 | 100;      // Xsize = 150, Ysize = 100
  DMA2D->OOR = 480 - 150;            // Offset = WidthLine - Xsize

  DMA2D->CR |= DMA2D_CR_START;       // Start


Последний раз редактировалось BusMaster 21 авг 2017, 19:30, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: IAR. Медленное заполнение двумерного массива.
СообщениеДобавлено: 21 авг 2017, 19:28 
Старожил
Аватара пользователя

Зарегистрирован: 18 май 2013, 20:43
Сообщения: 4340
Откуда: Кемеровская область, Киселевск
У меня на ILI9341 по SPI через DMA заливка так сделана, я тут как то писал. Ограничиваешь квадрат, DMA выплевывает пачку.

_________________
RADIOWOLF.RU


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: IAR. Медленное заполнение двумерного массива.
СообщениеДобавлено: 21 авг 2017, 19:41 
Старожил
Аватара пользователя

Зарегистрирован: 22 июл 2017, 11:48
Сообщения: 3646
Есть разница между обычным DMA и акселератором на DMA2D. Обычный DMA не умеет рассчитывать приращение адреса для следующей строки, а так же не умеет пересчитывать цвет на выходе, если на входе он в другом формате. И у обычного DMA ограничена макс.длина передачи - не более 65k элементов. Зато обычный DMA может заполнять слой в индексной 8-битной модели.

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

А вот и ЗРЯ! Без внешней ОЗУ не очень то выходит эффективно работать с большой графикой. Постоянный поиск компромисса между чем-то и чем-то. Страдает либо скорость, либо "красивость" графики.

bw429 писал(а):
18 бит позволяют получить 64 градации серого и еще остается по 32 градации на каждый цвет.

Малость не так. Формат RGB666 даёт 64 градации яркости в каждой компоненте, то есть 64 * 64 * 64 = 262144 цвета (или 2^18 = 262144).
18-битный цвет конечно удобнее хранить в типе uint8_t, потому что uint32_t будет излишним. Но, как я уже писал, встроенной оперативки не хватит для буфера размером в полный кадр дисплея при 3 байтах на пиксель. 272*480*3 = почти 400 килобайт, такого размера ОЗУ нет ни в одном МК F4-серии.
Выход только один - индексные цвета в формате L8 или AL44, либо вывод по частям.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: IAR. Медленное заполнение двумерного массива.
СообщениеДобавлено: 23 апр 2019, 18:23 
Заглядывает иногда

Зарегистрирован: 05 дек 2017, 18:17
Сообщения: 162
Пытаюсь использовать DMA2D для заливки экрана с контроллером SSD1963 подключенного по FSMC.
Сейчас для заливки экрана использую DMA2_Stream1 в режиме mem-to-mem. Все работает, но поскольку регистр NDTR у DMA 16-битный, то заливку всего экрана делаю в два захода.
Контроллер использую F429, у него есть DMA2D.
Пробую использовать его, для заливки "в один прием". Взял пример кода от BusMaster, переделал на простое заполнение всего экрана одним цветом.
Код:
//Отправка команды экрану с размером окна в которое будет заливка и старт данных
SetWindows(0,0,800-1,480-1);
FSMC_LcdWriteCmd ( 0x2C );         

RCC->AHB1ENR |= RCC_AHB1ENR_DMA2DEN;

//Сброс битов режима и установка в 11, т.е. из регистра в память
DMA2D->CR &= ~DMA2D_CR_MODE;
DMA2D->CR |= (DMA2D_CR_MODE_0|DMA2D_CR_MODE_1);         

//Формат цвета. У меня RGB565
DMA2D->OPFCCR &= (DMA2D_OPFCCR_CM);                 
DMA2D->OPFCCR |= DMA2D_OPFCCR_CM_1;                 

//Цвет заливки, определен как #define RED 0xF800
DMA2D->OCOLR = RED;     

//Память куда выводить
//Определена как #define LCD_DATA ((uint32_t)0x60020000)
DMA2D->OMAR = LCD_DATA;   

//Экран 800*480 , заливаю целиком, смещение 0
DMA2D->NLR = 800 << 16 | 480;     
DMA2D->OOR = 0;           

DMA2D->CR |= DMA2D_CR_START;       // Start

while (DMA2D->CR & DMA2D_CR_START);
}


Заливается только примерно 1/5 экрана. Флагов ошибок со стороны DMA2D нет, только флаг TCIF об окончании передачи.

И еще не нашел, а можно ли убрать инкремент памяти? В случае с FSMC можно писать по одному и тому же адресу, без инкремента. В случае с обычным DMA так и работает. А если DMA2D использовать, то адрес памяти автоматически увеличивается (проверял на записи в буфер в памяти).


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 20 ] 

Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: VladislavS


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB