Jump to content

    

Allwinner A13 SoC уделал DSP C6745. Смеяться или плакать?

Recommended Posts

sasamy
On 6/27/2022 at 1:44 PM, repstosw said:

А что по адресу 0x7010000 хранится?

судя по DTS диапазон адресов 0x07010000 - 0x07010240 относится к одному из блоков управления тактированием

 

https://github.com/Tina-Linux/tina-t113-linux-5.4/blob/150c69d4f2b0886db269cc7883f007e2cdcd839c/arch/arm/boot/dts/sun8iw20p1.dtsi#L419

 

Quote

        r_ccu: [email protected] {
            compatible = "allwinner,sun8iw20-r-ccu";
            reg = <0x0 0x07010000 0x0 0x240>;
            clocks = <&dcxo24M>, <&rtc_ccu CLK_OSC32K>, <&rtc_ccu CLK_IOSC>,
                 <&ccu CLK_PLL_PERIPH0>;
            clock-names = "hosc", "losc", "iosc", "pll-periph0";
            #clock-cells = <1>;
            #reset-cells = <1>;
        };

драйвер тут

 

https://github.com/Tina-Linux/tina-t113-linux-5.4/blob/150c69d4f2b0886db269cc7883f007e2cdcd839c/drivers/clk/sunxi-ng/ccu-sun8iw20-r.c#L131

Edited by sasamy

Share this post


Link to post
Share on other sites

repstosw

Успешно запустил G2D. :sun_bespectacled:

 

Проверил на отрисовке прямоугольников и BitBlt.  Над прозрачностью и порядком отрисовки пришлось поломать голову, но сделал.

 

На картинке - Blt с учётом альфы.  Цветовое представление: ARGB.  Прикрутил декодер PNG-файлов. (по краям изображение хорошо сглаживается).

 

 

G2D.jpg.f70ea6f908f7b86937dd6df445de1cf1.jpg

 

Есть некоторые моменты:

 

1) GD2 не может одновременно использовать Mixer и Rotator.  Либо смешиваем, либо поворачиваем

 

2) Отсутствует отсечение: если изображение выходит за пределы рабочей области - повисает

 

3) Критичны размеры.  Например, прямоугольник размером 1x1 пиксель он не выведет.  Минимальный - 2x1 пиксел

 

 

 

Edited by repstosw

Share this post


Link to post
Share on other sites

mantech
В 28.06.2022 в 14:10, repstosw сказал:

Например, прямоугольник размером 1x1 пиксель он не выведет.

Больше интересует производительность, сколько по времени рисует закрашенный квадрат во весь экран НЕОНом и этим g2d?

В 28.06.2022 в 14:10, repstosw сказал:

если изображение выходит за пределы рабочей области - повисает

Эт как-то не радует, конечно.. Виснет ускоритель или вся система?

Edited by mantech

Share this post


Link to post
Share on other sites

repstosw
On 6/28/2022 at 9:23 PM, mantech said:

Больше интересует производительность, сколько по времени рисует закрашенный квадрат во весь экран НЕОНом и этим g2d?

Скоро об этом напишу.   Какой клок ставить ускорителю?

 

По поводу производительности  - даже если будет одинаково или чуть-медленее - не смертельно.  Главное, что параллельно.  CPU может делать другие вещи, в то время когда G2D рисует. Заложить буферизацию.

 

Ну например - время отрисовки CPU 10 мкс, а время отрисовки G2D - 15 мкс,  время процессора на выполнение остального кода - 10 мкс.

Здесь CPU шустрее рисует в 1,5 раза.  Но один он всё сделает за:  10 + 10 = 20 мкс

А вместе с GPU на всё уйдёт  MAX(15, 10) =15 мкс

В этом примере выигрыш в производительности 20/15 = 1,333  (на 30% что неплохо)

 

 

 

On 6/28/2022 at 9:23 PM, mantech said:

Эт как-то не радует, конечно.. Виснет ускоритель или вся система?

 Скорее всего ускоритель.  У меня пока программный поллинг (опрос занятости ускорителя перед отрисовкой следующего элемента).   Уточню позже.

Edited by repstosw

Share this post


Link to post
Share on other sites

mantech
В 28.06.2022 в 14:36, repstosw сказал:

даже если будет одинаково или чуть-медленее - не смертельно.  Главное, что параллельно.  CPU может делать другие вещи, в то время когда G2D рисует. Заложить буферизацию.

В моем случае это не имеет значения, т.к. надо нарисовать кучу квадратов, затем текст и только потом переключится на другое дело - один фиг ждать надо завершения, но использование подобных корок накладывает ограничения на переносимость, НЕОН-то во всех армах есть, а вот g2d только в Т113, в v3s, например его нет, так что перенести не получится, и если скорость примерно одинаковая, то смысла большого не вижу,ИМХО...

 

ЗЫ. Кстати, хотел спросить, как вы делаете синхронизацию рисования картинок или прямоугольников с обновлением экрана. Допустим, частота 50Гц, и вам надо нарисовать картинку, ждете прерывания окончания очередного обновления экрана и начинаете рисовать? А если оно уже началось, то надо снова 1\50 сек ждать? Долго ведь получается...

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

Edited by mantech

Share this post


Link to post
Share on other sites

repstosw
On 6/28/2022 at 10:25 PM, mantech said:

ЗЫ. Кстати, хотел спросить, как вы делаете синхронизацию рисования картинок или прямоугольников с обновлением экрана. Допустим, частота 50Гц, и вам надо нарисовать картинку, ждете прерывания окончания очередного обновления экрана и начинаете рисовать? А если оно уже началось, то надо снова 1\50 сек ждать? Долго ведь получается...

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

 

Я рисую в заднем буфере. Когда всё отрисовано - скидываю весь буфер на экран. В этом случае синхронизация с экраном нужна только 1 раз - когда  скидываю буфер целиком на экран.  Синхронизация самая простая - опрос регистра LCD_GINT0_REG и сброс ему бита:

 

void VSync(void)
{
 LCD_GINT0_REG&=~(1<<15);         //clear LCD_VB_INT_FLAG
 while(!(LCD_GINT0_REG&(1<<15))); //wait  LCD_VB_INT_FLAG
}

 

Перед этим, нужно разрешить VB:

 

 LCD_GINT0_REG|=(1<<31); //Enable the Vertical Blank interrupt

 

Можно также через прерывание TCON .  Оба способа работают.   Но так как на прерывании у меня обновление DMA для звука, то использую опрос VSync() перед отправкой данных на экран.

Всё очень плавно и гладко движется.  Причем даже сбрасывать с кеша не нужно.  Экранная память буферизована, но не кеширована, также бит 12 (TEX) установлен.  Память заднего буфера - обычная:  кеширована и буферизована.   Это режим с наибольшей производительностью, когда задний буфер надо и читать и писать процессором. А экранная память только читается TCON/DE,  и пересылка NEON'ом (запись)  1 раз.

 

У C6745 есть PRU, там можно этот VSync заставить ждать сопроцессором, основной CPU идёт дальше...

 

Возвращаясь к G2D: он работает на любом участке DDR:  для каждой картинки можно назначить свой адрес источника, или сделать один общий атлас картинок в памяти, а потом вырезать нужную и показывать. G2D это всё может! :yes:

Edited by repstosw

Share this post


Link to post
Share on other sites

GenaSPB

Я попытался сделать:

В dbuff ставится младший бит и ждем пока снимется.
Но судя по иногда промаргивающему изображению, это не то...

    write32((uintptr_t) & glb->dbuff, 0x01uL);    // 1: register value be ready for update (self-cleaning bit)
    while ((read32((uintptr_t) & glb->dbuff) & 0x01uL) != 0)
        ;
// Allwinner_DE2.0_Spec_V1.0
// 5.10.3.4 Blender
// GLB
struct de_glb_t {
    uint32_t ctl;        /** Offset 0x000 Global control register */
    uint32_t status;    /** Offset 0x004 Global status register */
    uint32_t dbuff;        /** Offset 0x008 Global double buffer control register */
    uint32_t size;        /** Offset 0x00C Global size register */
};

Share this post


Link to post
Share on other sites

mantech
В 28.06.2022 в 16:52, repstosw сказал:

Когда всё отрисовано - скидываю весь буфер на экран.

В смысле? Копируете весь теневой буфер в экранный или перекидываете адреса DE с активной экранной области на теневую во время обратного хода?

ЗЫ. Хотя, если теневая область закэширована, то походу только копирование...

Edited by mantech

Share this post


Link to post
Share on other sites

GenaSPB
On 6/28/2022 at 5:59 PM, GenaSPB said:

В dbuff ставится младший бит и ждем пока снимется.

Это как раз надеюсь на синхронизацию с vsync

Share this post


Link to post
Share on other sites

GenaSPB

оставил своё и добавил ваше - помогло. Но вообще где-то должен быть способ по настоящему синхронизироваться, не в ручную ловить момент.

Т.е. как в STM32 LTDC и Renessas VD5: выставил в регистр новый адрес страницы, дождался когда дисплей на него перейдет - и все, поехал заполнять старый буфер.

Edited by GenaSPB

Share this post


Link to post
Share on other sites

repstosw
On 6/29/2022 at 12:59 AM, GenaSPB said:

Я попытался сделать:

В dbuff ставится младший бит и ждем пока снимется.
Но судя по иногда промаргивающему изображению, это не то...

 

Рисовалки типа G2D и DE отставить... Тут только TCON, без вариантов. Обновлять изображение нужно в те моменты, когда TCON не сканирует память. Иначе артефакты на экране будут визуально ощутимы.

 

О вкусах не спорят: Double Buffering vs. Page Flipping : https://docs.oracle.com/javase/tutorial/extra/fullscreen/doublebuf.html

 

Для моих целей (игры) более подходит двойная буферизация, чем переключение страниц. Потому что не всегда надо перерисовывать всё полностью.

 

Перед переключением страницы тоже нужно ждать VSync:

 

void DE_SwitchBuffer(u8 channel,u8 buffer) //channel = 0,1,2 ; buffer = 0,1
{
 int j;
 switch(channel)
 {
  case 0: //CH0
   for(j=0;j<3;j++)writel(buffer?CH0_BUFFER1:CH0_BUFFER0,&de_vi_regs0->cfg[0].top_laddr[j]); //CH0 LAYMB_LADD
  break;
  case 1: //CH1
   for(j=0;j<3;j++)writel(buffer?CH1_BUFFER1:CH1_BUFFER0,&de_vi_regs1->cfg[0].top_laddr[j]); //CH1 LAYMB_LADD
  break;
  case 2: //CH2
   writel(buffer?CH2_BUFFER1:CH2_BUFFER0,&de_ui_regs->cfg[0].top_laddr);                     //CH2 LAYMB_LADD
  break;
 }
}

void DE_ComposerApply(void)
{
 writel(1,&de_glb_regs->dbuff); //composer enable
}

void main(void)
{
  //...
  u8 page=0;
  
  while(1)
  {
     //...
     VSync();
    
     DE_SwitchBuffer(0,page);
     DE_ComposerApply();
    
     page^=1;
    
     Draw_Scene(page);
     //...
  }
  //...
}

 

On 6/29/2022 at 3:08 AM, GenaSPB said:

оставил своё и добавил ваше - помогло. Но вообще где-то должен быть способ по настоящему синхронизироваться, не в ручную ловить момент.

 

Разрешить прерывание от TCON. В обработчике переключать страницу.

 

Чтобы вручную не ловить момент - можно задействовать второе ядро у T113-s3  или его HiFi-DSP.  И сделать отложенную отрисовку на экран: дать команду сопроцессору, а тот будет ждать VSync, а main CPU пойдёт дальше.   Я так делал на C6745, у него есть пара сопроцессоров, как раз один из них рисовал на экран и ждал VSync.

 

Ну или чисто софт-вариант: потоки (threads).   Создать поток и в нём проверять.:biggrin:

Edited by repstosw

Share this post


Link to post
Share on other sites

repstosw
On 6/28/2022 at 10:25 PM, mantech said:

Допустим, частота 50Гц, и вам надо нарисовать картинку, ждете прерывания окончания очередного обновления экрана и начинаете рисовать? А если оно уже началось, то надо снова 1\50 сек ждать? Долго ведь получается...

 

Не долго.  50 Гц это 20 мс. За эти 20 мс процессор может горы свернуть. Не уверен, что оставшаяся часть вашей программы займёт больше времени.   Долго может быть только первая итерация цикла. Затем система входит в синхрон и на эти 20 мс успевает ещё не только выполнить код, но и дождаться следующего VSync.

 

Но если вдруг 20 мс не хватит, тогда да, очередной VSync будет пропущен и придётся ждать следующего.  В этом случае уже будет не 50 FPS, а в 2 раза меньше.

А если программа требует более 40 мс, то уже 2 VSync будут пропущены.  FPS тут просядет уже в 3 раза...  

Это в любом учебнике по игрострою расписано.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.