Перейти к содержанию
    

Allwinner T113-s3 уделал HiFi4 DSP. Смеяться или плакать?

2 hours ago, mantech said:

Данные могут приходить от программного PNG декодера, поэтому сброс кэша нужен, и выходной поток тоже может быть использован в постобработке.

В таком случае, использую инвалидацию кеша, когда процессор использует данные от декодера.  И сброс с кеша, когда процессор готовит данные для энкодера.

 

2 hours ago, mantech said:

Вот тут чет затупил, что это такое? first_dimension - это ширина источника, или что? Или это высота*ширину источника?

Длина и ширина источника.

 

2 hours ago, mantech said:

Вот здесь, я так понял, что нужно поставить G2D_FMT_ABGR_AVUY8888, т.к. плоскость RGB ?

Да.  Константа с нужным порядком следования компонент RGB.

 

2 hours ago, mantech said:

Тут как понимаю 2 адреса из-за плоскости Y\C  в RGB нужен только первый?

Да. Для RGB нужен только с индексом [0].  остальные не нужны.

 

2 hours ago, mantech said:

Ну и вот тут бы пояснительную бригаду)))

Это координаты левого верхнего угла вывода изображения в финальном видеобуфере.

Изменено пользователем repstosw

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Собственно инициализация блока для поворота вот так (в этом тексте поворот на 0 градусов - используется как копирование)
 

/* Коприрование с применением блока G2D_ROT */
static void
hwaccel_rotcopy(
	uintptr_t saddr,
	unsigned sstride,
	uint_fast32_t ssizehw,
	uintptr_t taddr,
	unsigned tstride,
	uint_fast32_t tsizehw
	)
{
	ASSERT((G2D_ROT->ROT_CTL & (UINT32_C(1) << 31)) == 0);

	G2D_ROT->ROT_CTL = 0;
	G2D_ROT->ROT_IFMT = VI_ImageFormat;
	G2D_ROT->ROT_ISIZE = ssizehw;
	G2D_ROT->ROT_IPITCH0 = sstride;
//	G2D_ROT->ROT_IPITCH1 = sstride;
//	G2D_ROT->ROT_IPITCH2 = sstride;
	G2D_ROT->ROT_ILADD0 = ptr_lo32(saddr);
	G2D_ROT->ROT_IHADD0 = ptr_hi32(saddr) & 0xff;
//	G2D_ROT->ROT_ILADD1 = ptr_lo32(saddr);
//	G2D_ROT->ROT_IHADD1 = ptr_hi32(saddr) & 0xff;
//	G2D_ROT->ROT_ILADD2 = ptr_lo32(saddr);
//	G2D_ROT->ROT_IHADD2 = ptr_hi32(saddr) & 0xff;

	G2D_ROT->ROT_OPITCH0 = tstride;
//	G2D_ROT->ROT_OPITCH1 = tstride;
//	G2D_ROT->ROT_OPITCH2 = tstride;
	G2D_ROT->ROT_OSIZE = tsizehw;
	G2D_ROT->ROT_OLADD0 = ptr_lo32(taddr);
	G2D_ROT->ROT_OHADD0 = ptr_hi32(taddr) & 0xff;
//	G2D_ROT->ROT_OLADD1 = ptr_lo32(taddr);
//	G2D_ROT->ROT_OHADD1 = ptr_hi32(taddr) & 0xff;
//	G2D_ROT->ROT_OLADD2 = ptr_lo32(taddr);
//	G2D_ROT->ROT_OHADD2 = ptr_hi32(taddr) & 0xff;

	//G2D_ROT->ROT_CTL |= (UINT32_C(1) << 7);	// flip horisontal
	//G2D_ROT->ROT_CTL |= (UINT32_C(1) << 6);	// flip vertical
	//G2D_ROT->ROT_CTL |= (UINT32_C(1) << 4);	// rotate (0: 0deg, 1: 90deg, 2: 180deg, 3: 270deg)
	G2D_ROT->ROT_CTL |= (UINT32_C(1) << 0);		// ENABLE
	awxx_g2d_rot_startandwait();		/* Запускаем и ждём завершения обработки */

}

Остальные функции можно у меня в репо посмотреть. stride - шаг строк в памяти в байтах.

	const unsigned tstride = GXADJ(tdx) * PIXEL_SIZE;
	const unsigned sstride = GXADJ(sdx) * PIXEL_SIZE;
	const uintptr_t taddr = (uintptr_t) dst;
	const uintptr_t saddr = (uintptr_t) src;
	const uint_fast32_t ssizehw = ((sh - 1) << 16) | ((sw - 1) << 0);
	const uint_fast32_t tsizehw = ((sh - 1) << 16) | ((sw - 1) << 0);		/* размер совпадающий с источником - просто для удобства */

 

Изменено пользователем GenaSPB

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, GenaSPB сказал:

Собственно инициализация

Всем спасибо, буду разбираться. Кстати, этот g2d может ресайзинг делать из меньшей в большую и наоборот?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, умеет. В том числе и с color key. Смотреть у меня - https://github.com/ua1arn/hftrx/blob/develop/src/display/framebuf.c
исходники теста искать по словам Hello!

20230201_205107.jpg

20230129_153855.jpg

Изменено пользователем GenaSPB

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

22 часа назад, GenaSPB сказал:

Да, умеет.

Чет не едет этот поворот, может он вообще только квадратные объекты поворачивает?

Сделал так:

int G2D_ImageRotate(uint32_t *img_src,uint32_t *img_dest,uint16_t *width,uint16_t *height)
{
	g2d_blt G2D_Rot;

	uint32_t  w=width;
	uint32_t  h=height;

	 G2D_Rot.flag=G2D_BLT_ROTATE270;

	 G2D_Rot.src_image.w=w;//Длина и ширина источника.
	 G2D_Rot.src_image.h=h;

	 G2D_Rot.src_rect.w=w;
	 G2D_Rot.src_rect.h=h;

	 G2D_Rot.src_image.format=G2D_FMT_ABGR_AVUY8888;
	 G2D_Rot.src_image.pixel_seq=G2D_SEQ_NORMAL;

	 G2D_Rot.src_image.addr[0]=(u32)(TMPIMG_BASE); //Y
	 G2D_Rot.src_image.addr[1]=0; //UV

	 G2D_Rot.src_rect.x=0;
	 G2D_Rot.src_rect.y=0;

	 G2D_Rot.dst_image.addr[0]=(u32)(SAVEFG_BASE); //Y
	 G2D_Rot.dst_image.addr[1]=0; //UV

	 G2D_Rot.dst_image.w=w;
	 G2D_Rot.dst_image.h=h;

	 G2D_Rot.dst_image.format=G2D_FMT_ABGR_AVUY8888;
	 G2D_Rot.dst_image.pixel_seq=G2D_SEQ_NORMAL;

	 G2D_Rot.dst_x=0;//координаты левого верхнего угла вывода изображения в финальном видеобуфере.
	 G2D_Rot.dst_y=0;
	 G2D_Rot.color=0x000000;
	 G2D_Rot.alpha=0xFF;
	 g2d_blit(&G2D_Rot);
	 cache_flush_range((uint32_t)SAVEFG_BASE  ,(uint32_t)(SAVEFG_BASE+0x800000)); //инвалидация кеша - декодер записал в память
	 *width=h;
	 *height=w;
}

Нужно просто заменить софтовый аналог:

void ImageRotate(uint32_t *img_src,uint32_t *img_dest,uint16_t *width,uint16_t *height)
{

uint16_t i=0,q;
uint32_t w;
uint16_t lenx=*width;
uint16_t leny=*height;
uint32_t *src=(u32)(TMPIMG_BASE);//img_src;
uint32_t *dests=(u32)SAVEFG_BASE;//img_dest;
uint32_t *dest=dests;
while (i<leny)
  {
   q=0; w=leny*(lenx-1);
   while (q<lenx)
     {
      q++;dest=dests+w;w=w-leny;*dest=*src; src++;
     }
   i++;dests=img_dest+i; 
  }
*width=leny;
*height=lenx;
}

Жалко нет аналога на НЕОНе, каждый раз мозги выпаривать с этими корками...

Задача просто повернуть на 270 картинку с исходным разрешением 1080х1920  в вид  1920х1080.

Изменено пользователем mantech

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Масштабирование это отдельная операция, поворот отдельная.

35 minutes ago, mantech said:

1080х1920  в вид  1920х1080

Это к ROT

cache_flush_range - а зачем ПОСЛЕ работы аппаратуры?
 

Изменено пользователем GenaSPB

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, GenaSPB сказал:

cache_flush_range - а зачем ПОСЛЕ работы аппаратуры?

Пока проверяю НЕОНовским копировщиком в экранную область

2 часа назад, GenaSPB сказал:

Это к ROT

Вы проверяли как поворачивается прямоугольник размером с весь экран? Если да, можете привести значения для вашего разрешения экрана для этих параметров? И какой режим экрана используете, у меня ABGR8888

sstride, ssizehw, tstride, tsizehw

 

Единственное, чего я добился - это поворот квадратной области 1080х1080, полный прямоугольник не хочет ни в какую...

Изменено пользователем mantech

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кому инетерсно как запустить DSP с имиджа Xtensa

в линкере выделяем память - я выделил последние 4М для ДСП

__DSP_BASE = 0x47C00000;  
__DSP_SIZE = 4M;  					/* Step 1M */

__RAM_SIZE = 128M - __DSP_SIZE;

MEMORY
{
  RAM (rwx)  	  : ORIGIN = 0x40000000, 		LENGTH = __RAM_SIZE 		
  DSP (rwx)  	  : ORIGIN = __DSP_BASE, 		LENGTH = __DSP_SIZE 	
}

настраиваем MMU для этого региона

MMU_TTSection((uint32_t*)tbbArea, __dsp_base, sizeDSP, Sect_Device_RW);

собираем приложение для дсп, там настраиваем LSP для нашего региона

MEMORY
{
  iram0_0_seg :                       	org = 0x00400000, len = 0x660
  iram0_1_seg :                       	org = 0x00400660, len = 0x9A0
  iram0_2_seg :                       	org = 0x00401000, len = 0x17C
  iram0_3_seg :                       	org = 0x0040117C, len = 0x20
  iram0_4_seg :                       	org = 0x0040119C, len = 0x20
  iram0_5_seg :                       	org = 0x004011BC, len = 0x20
  iram0_6_seg :                       	org = 0x004011DC, len = 0x20
  iram0_7_seg :                       	org = 0x004011FC, len = 0x20
  iram0_8_seg :                       	org = 0x0040121C, len = 0x20
  iram0_9_seg :                       	org = 0x0040123C, len = 0xEDC4
  dram0_0_seg :                       	org = 0x00420000, len = 0x8000
  dram1_0_seg :                       	org = 0x00440000, len = 0x8000
  ddr1_0_seg :                        	org = 0x37C00000, len = 0x400000
}

настраиваем _cache_config(); в board_init(); собираем получаем ELF.

Бинарник в голом виде там не получится, поэтому с эльфа надо данные выдирать самим

ельф можно потрошить с сдк линукса : там в драйверах есть файл dsp.c, так как у меня нет задачи запускать имидж с линукса я oemhead не добавлялю...

я написал свою выдиралку, она дает хидер в таком виде прямо с эльфа

#ifndef DSPIMAGE_H 
#define DSPIMAGE_H 

typedef struct 
{ 
 	unsigned int RAM; 
 	unsigned int Offset;
 	unsigned int Length;

} dspImgMapStruct;

const unsigned char dspImgData[] = {
	.......
};

const unsigned int dspImageBlocksCount = 11;

const unsigned int dspImageDataLength = 4680;

const unsigned int dspEntryPoint = 0x00400660;

const dspImgMapStruct dspImgMap[11] = {

	{0x00400660, 0x00000000, 0x0000016C}, 
	...

};

#endif

В итоге данные хранятся как RO в прошивке, занимают минимум места.

После этого запускается это все красиво таким образом

#include "dsp.h"
#include "dspImg.h"

void DSP_LoadImage(void)
{
	for(int i = 0; i < dspImageBlocksCount; i++)
	{
		memcpy((uint8_t*)dspImgMap[i].RAM, &dspImgData[dspImgMap[i].Offset], dspImgMap[i].Length);
	}
}

void DSP_Setup(void)
{
	CCU_SetDSP(CCU_DSP_SRC_PERI2X, 1);

	BIT_SET(SYS_CFG->DSP_BOOT_RAMMAP_REG, BIT_SRAM_REMAP_ENABLE);

	BIT_CLEAR(CCU->DSP_BGR_REG, BIT_DSP0_RST);	      // DSP Reset Assert

	DSP0_CFG->DSP_ALT_RESET_VEC_REG = dspEntryPoint;
	BIT_SET(DSP0_CFG->DSP_CTRL_REG0, BIT_START_VEC_SEL);

	BIT_SET(DSP0_CFG->DSP_CTRL_REG0, BIT_RUN_STALL);
	BIT_SET(DSP0_CFG->DSP_CTRL_REG0, BIT_DSP_CLKEN);

	BIT_SET(CCU->DSP_BGR_REG, BIT_DSP0_RST);		 // DSP Reset De-assert

	DSP_LoadImage();

	BIT_CLEAR(SYS_CFG->DSP_BOOT_RAMMAP_REG, BIT_SRAM_REMAP_ENABLE);

	BIT_CLEAR(DSP0_CFG->DSP_CTRL_REG0, BIT_RUN_STALL);
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А попробуйтье указать у выходного прямоунольника ражмеры оиличающиеся от входного? В моем же случае прворота нет. И stride чскорее всего другой

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 минут назад, GenaSPB сказал:

А попробуйтье указать у выходного прямоунольника ражмеры оиличающиеся от входного?

Пробовал, все полосит и вообще мусор не экране, иногда в хардфаулт вылетает, видимо лезет за пределы экранного буфера.

7 минут назад, GenaSPB сказал:

В моем же случае прворота нет.

И не проверяли его вообще?

ЗЫ. У вас случаем НЕОНовского варианта ротатора нет, чет в инете на эту тему совсем тускло...

Нашел только на 90град и однобайтовая матрица.

Изменено пользователем mantech

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 minutes ago, mantech said:

хардфаулт вылетает, видимо лезет за пределы экранного буфера.

Ну это точно пепепутали со stridе. Осоьенно полосит.

При возмлжгости на днях поворот пррверю.

 

Зы: буферы не перекрываются у вас?

 

Изменено пользователем GenaSPB

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

12 минут назад, mantech сказал:

ЗЫ. У вас случаем НЕОНовского варианта ротатора нет, чет в инете на эту тему совсем тускло...

 

https://www.linkedin.com/pulse/using-simd-arm-neon-speed-up-applications-salvatore-c-chieppa

https://stackoverflow.com/questions/11259596/128-bit-rotation-using-arm-neon-intrinsics

Изменено пользователем vasilius

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 минут назад, GenaSPB сказал:

буферы не перекрываются у вас?

Нет, источник и получатель разные буферы по 8 мбайт, выровненные по 0х1000

5 минут назад, vasilius сказал:

первую не могу открыть, надо снова впн ставить, а во воторой что там делается, не понял, там походу в пределах вектора что-то вращают...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

18 минут назад, mantech сказал:

 

первую не могу открыть, надо снова впн ставить, а во воторой что там делается, не понял, там походу в пределах вектора что-то вращают...

 

Using SIMD ARM NEON to speed up applications.pdf

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 hours ago, mantech said:

разные буферы по 8 мбайт, выровненные по 0х1000

то что я говорил - stride - шаг строк - разное? Хотя не обязано... в вашем случае хоть по восемь килобайт на строку
h & w - разное?

Изменено пользователем GenaSPB

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...