Gömülü Grafiklerde DMA2D Projesi

İçindekiler

Graphics Accelerator Chrom-ART™ (DMA2D)

DMA2D nedir?

Gömülü grafik teknolojisinin gelişmesiyle birlikte, mikrodenetleyiciler giderek daha karmaşık grafik hesaplama ve görüntüleme görevlerini üstlenmeye başlamıştır. Ancak CPU’nun işlem gücü, yüksek çözünürlüklü ve canlı renkli grafikleri işlemek için yetersiz kalabilir. Neyse ki, STM32F429'dan itibaren, ST tarafından STM32 mikrodenetleyicilere Chrom-ART Accelerator veya DMA2D olarak bilinen, GPU'ya benzer bir harici çevre birimi eklenmiştir. DMA2D, birçok 2D grafik senaryosunda hızlandırma sağlar ve modern grafik kartlarında bulunan "GPU"ya benzer işlevleri etkili bir şekilde entegre eder.

DMA2D yalnızca 2D hızlandırma sunsa ve yetenekleri PC'lerdeki GPU'lara kıyasla nispeten basit olsa da, gömülü geliştirmedeki çoğu grafik görüntüleme hızlandırma gereksinimini karşılayabilir. DMA2D'yi etkili bir şekilde kullanarak, mikrodenetleyicilerde akıcı ve çarpıcı UI efektleri elde edebiliriz.

DMA2D İşlevleri

  1. Renk Dolgusu (Dikdörtgen Alanlar)
  2. Görüntü (Bellek) Kopyalama
  3. Renk Formatı Dönüştürme (ör. YCbCr'den RGB'ye veya RGB888'den RGB565'e)
  4. Şeffaflık Karıştırma (Alfa Karıştırma)

İlk ikisi bellek tabanlı işlemlerken, son ikisi hesaplama hızlandırmasını içerir. Şeffaflık karıştırma ve renk formatı dönüştürme, görüntü kopyalama ile birleştirilebilir ve önemli ölçüde esneklik sağlar.

Pratik geliştirme sürecinde, DMA2D'nin kullanımı geleneksel DMA denetleyicileriyle benzerlik gösterir. Bazı grafiksel olmayan senaryolarda, DMA2D belirli görevler için geleneksel DMA'nın yerini bile alabilir.

Farklı ST ürün serilerindeki DMA2D hızlandırıcılarının arasında küçük farklılıklar olabileceğini unutmamak önemlidir. Örneğin, STM32F4 serisi MCU'daki DMA2D, ARGB ve AGBR renk formatları arasında dönüştürme özelliğine sahip değildir. Bu nedenle, belirli bir işlevselliğe ihtiyaç duyulduğunda, destek olup olmadığını doğrulamak için programlama kılavuzuna başvurmak tavsiye edilir.

DMA2D Çalışma Modları

Geleneksel DMA'nın aygıt-aygıt, aygıt-bellek ve bellek-aygıt modlarına benzer şekilde, bir DMA bileşeni olan DMA2D de dört çalışma moduna sahiptir:

  1. Kayıt Defterinden Belleğe
  2. Bellekten Belleğe
  3. Piksel Renk Formatı Dönüştürme ile Bellekten Belleğe
  4. Piksel Renk Formatı Dönüştürme ve Şeffaflık Karıştırma ile Bellekten Belleğe

İlk iki mod basit bellek işlemlerini içerirken, son iki mod bellek kopyalama işlemini gerçekleştirirken aynı anda gerektiğinde renk formatı dönüştürme ve/veya şeffaflık karıştırma işlemlerini de yürütür.

DMA2D ve HAL Kütüphanesi

Çoğu durumda, HAL kütüphanesinin kullanılması kod yazımını basitleştirir ve taşınabilirliği artırır. Ancak, DMA2D kullanımı söz konusu olduğunda bir istisna söz konusudur. HAL ile ilgili temel sorun, verimliliği düşüren aşırı iç içe geçme yapısı ve güvenlik kontrollerinde yatmaktadır. Diğer çevre birimleriyle çalışırken verimlilik kaybı çok büyük olmayabilir, ancak hesaplama ve hıza odaklanan bir hızlandırıcı olan DMA2D için HAL kütüphanesinin kullanılması, hızlandırma verimliliğini önemli ölçüde azaltabilir.

Sonuç olarak, DMA2D işlemleri için ilgili HAL işlevlerini kullanmaktan genellikle kaçınırız. Verimlilik amacıyla, maksimum hızlandırma avantajı sağlayan doğrudan kayıt manipülasyonu kullanılır.

DMA2D kullanım durumlarının çoğunda çalışma modlarında sık sık değişiklik yapıldığı için, CubeMX'teki DMA2D'nin grafiksel yapılandırması pratikliğini yitirmektedir.

Gömülü Grafik Geliştirmede DMA2D'nin Kullanımı

Gerekli Araçlar

  • DMA2D Çıkışlı STM32 Geliştirme Kartı x1
  • Renkli TFT Ekran x1

Bu örnekte, RT-Thread tarafından üretilen, 480 MHz'e kadar saat frekansı ve 32 MB SDRAM'e sahip STM32H750XB içeren ART-Pi geliştirme kartını kullanıyoruz. Kartta ayrıca bir hata ayıklayıcı (ST-Link V2.1) bulunmaktadır. Ayrıca, RGB666 arayüzüne ve 320×240 (QVGA) çözünürlüğe sahip 3,5 inçlik bir TFT LCD ekran kullanıyoruz.

ART-Pi Development Board-Produced by RT-Thread (with TFT LCD Display)
ART-Pi Development Board-Produced by RT-Thread (with TFT LCD Display)

Geliştirme Ortamı

Bu makalede sunulan içerik ve kod, RT-Thread Studio, MDK, IAR vb. gibi çeşitli geliştirme ortamlarında kullanılabilir.

Bu makaledeki deneylere başlamadan önce, framebuffer teknolojisini kullanarak LCD ekranı çalıştıran temel bir projeye ihtiyacınız vardır. Sağlanan kodlardan herhangi birini çalıştırmadan önce DMA2D'yi etkinleştirmeniz gerekir.

DMA2D, şu makro kullanılarak etkinleştirilebilir:

				
					__HAL_RCC_DMA2D_CLK_ENABLE();
				
			

Uygulama Projesi: Dikdörtgen Doldurma

Gömülü grafikler, dikdörtgen doldurma, bellek kopyalama, saydamlık karıştırma vb. gibi çeşitli işlemleri kapsar. Örnek olarak dikdörtgen doldurmayı ele alacağız. Amaç, DMA2D kullanarak dikdörtgen doldurma yoluyla basit bir çubuk grafik oluşturmaktır:

A Simple Histogram
A Simple Histogram

Öncelikle, desenin arka planı olarak işlev görecek şekilde ekranı beyaz renkle doldurmamız gerekiyor. Ekrandaki mevcut desen, amaçladığımız tasarımı engelleyebileceğinden bu adım çok önemlidir. Ardından, çubuk grafik dört mavi dikdörtgen blok ve bir çizgi parçası kullanılarak oluşturulur; bu çizgi parçası, yüksekliği 1 olan özel bir dikdörtgen blok olarak düşünülebilir. Dolayısıyla, bu grafiği çizmek bir dizi "dikdörtgen doldurma" işlemini gerektirir:

  • Ekranın tamamını kaplayacak şekilde bir dikdörtgeni beyaz renkle doldurun.
  • Dört veri çubuğunu mavi renkle doldurun.
  • Yükseği 1 olan bir çizgi parçasını siyah renkle doldurun.

Esasen, tuvalin herhangi bir konumunda herhangi bir boyutta bir dikdörtgen çizmek, ilgili bellek konumundaki piksel verisini istenen renge ayarlamayı gerektirir. Ancak, bellekteki çerçeve tamponunun doğrusal depolanması nedeniyle, dikdörtgenin genişliği ekranın genişliğiyle tam olarak hizalanmadıkça, görünüşte sürekli olan dikdörtgen alanların bellek adresleri birbirine bitişik değildir.

Aşağıdaki şema, tipik bir bellek düzenini göstermektedir; burada sayılar, çerçeve tamponundaki her pikselin bellek adresini gösterir (çok baytlı pikseller dikkate alınmadan, temel adrese göre ofset). Mavi alan, doldurulacak dikdörtgeni temsil eder. Dikdörtgen içindeki bellek adreslerinin bitişik olmadığı açıktır.

Memory Distribution in Frame Buffer
Memory Distribution in Frame Buffer

Çerçeve tamponunun bu özelliği, dikdörtgen alanları doldurmak için memset gibi verimli işlemleri kullanmamızı engeller. Genellikle, herhangi bir dikdörtgeni doldurmak için aşağıdaki gibi iç içe geçmiş döngü yöntemini kullanırız. Burada xs ve ys, ekrandaki dikdörtgenin sol üst köşesinin koordinatlarıdır; width ve height dikdörtgenin boyutlarını belirler; color ise dolgu rengini belirtir:

				
					for (int y = ys; y < ys + height; y++) {
    for (int x = xs; x < xs + width; x++) {
        framebuffer[y][x] = color;
    }
}

				
			

Kod basit görünebilir, ancak yürütme sırasında koşul kontrolleri, adres hesaplamaları ve artırımlar gibi işlemler için önemli miktarda CPU döngüsü boşa harcanırken, gerçek bellek yazma işlemine ayrılan kısım çok azdır. Bu durum verimlilikte düşüşe yol açar.

Bu gibi durumlarda, DMA2D'nin kayıt-bellek çalışma modu devreye girer. DMA2D, bellekteki alan bitişik olmasa bile dikdörtgen bir bellek bölgesini hızla doldurabilir.

Yukarıdaki resimde gösterilen örneği kullanarak, bunun nasıl gerçekleştirildiğini inceleyelim:

Illustration of DMA2D Filling Memory Area
Illustration of DMA2D Filling Memory Area

Öncelikle, burada yalnızca bellek doldurma işlemiyle uğraşıyoruz, kopyalama değil; bu nedenle DMA2D'nin kayıt-bellek modunda çalışması gerekiyor. Bu, kod parçasında gösterildiği gibi DMA2D'nin CR kaydının [17:16] bitlerini '11' olarak ayarlayarak sağlanır:

				
					DMA2D->CR = 0x00030000UL;

				
			

Ardından, doldurulacak dikdörtgenin özelliklerini (bölgenin başlangıç adresi, piksel cinsinden genişliği ve yüksekliği gibi) DMA2D'ye bildiririz.

Bölgenin başlangıç adresi, dikdörtgenin sol üst köşesindeki pikselin bellek adresidir (şemadaki kırmızı pikselin adresi) ve DMA2D'nin OMAR kaydı tarafından yönetilir. Dikdörtgenin genişliği ve yüksekliği piksel cinsindendir ve NLR kaydının üst 16 biti (genişlik) ile alt 16 biti (yükseklik) tarafından yönetilir. Bu değerleri ayarlamak için kullanılan kod şöyledir:

				
					DMA2D->OMAR = (uint32_t)(&framebuffer[y][x]); // Set the starting pixel memory address for filling
DMA2D->NLR  = (uint32_t)(width << 16) | (uint16_t)height; // Set the width and height of the rectangle

				
			

Bunun üzerine, dikdörtgenin bellek adresleri birbirine bitişik olmadığından, bir veri satırını doldurduktan sonra DMA2D'ye belirli sayıda pikseli atlamasını söylememiz gerekir (yani, şemadaki sarı alanın uzunluğu kadar). Bu değer, OOR kaydı tarafından yönetilir. Atlanacak piksel sayısını hesaplamanın basit bir yöntemi vardır: ekran alanının genişliğinden dikdörtgenin genişliğini çıkarın. Bunu uygulamak için kod şöyledir:

				
					DMA2D->OOR = screenWidthPx - width; // Set the row offset, i.e., skip pixels

				
			

Son olarak, DMA2D'ye dolgu için kullanılacak rengi ve renk formatını bildirmemiz gerekiyor. Bunlar sırasıyla OCOLR ve OPFCCR kayıtları tarafından yönetilir. Renk formatı, LTDC_PIXEL_FORMAT_XXX makroları ile tanımlanır. Kod şu şekildedir:

				
					DMA2D->OCOLR   = color; // Set the color for filling
DMA2D->OPFCCR  = pixelFormat; // Set the color format, e.g., use the macro LTDC_PIXEL_FORMAT_RGB565 for RGB565

				
			

Tüm ayarlar yapıldıktan sonra, DMA2D dikdörtgeni doldurmak için gerekli tüm bilgileri elde etmiştir. Aktarımı başlatmak için, DMA2D'nin CR kaydındaki 0. biti '1' olarak ayarlıyoruz:

				
					DMA2D->CR |= DMA2D_CR_START; // Start DMA2D data transfer, where DMA2D_CR_START is a macro with the value 0x01

				
			

DMA2D aktarımı başladığında, sadece işlemin tamamlanmasını bekleriz. DMA2D aktarımı tamamladıktan sonra, CR kaydının 0. bitini otomatik olarak '0' olarak sıfırlar; bu sayede aşağıdaki kodu kullanarak işlemin tamamlanmasını bekleyebiliriz:

				
					while (DMA2D->CR & DMA2D_CR_START) {} // Wait for DMA2D transfer completion

				
			

İpucu: Bir işletim sistemi kullanıyorsanız, DMA2D aktarım tamamlanma kesmesini etkinleştirebilirsiniz. Ardından, bir semafor oluşturabilir, aktarımı başlattıktan sonra bu semaforu bekleyebilir ve DMA2D aktarım tamamlanma kesme hizmet rutininde serbest bırakabilirsiniz.

İşlevin genelliği açısından, başlangıç aktarım adresi ve satır ofseti işlevin dışında hesaplanır ve işlevin içine aktarılır. İşte işlevin tam kodu:

				
					static inline void DMA2D_Fill(void * pDst, uint32_t width, uint32_t height, uint32_t lineOff, uint32_t pixelFormat, uint32_t color) {
    
    /* Configure DMA2D */
    DMA2D->CR      = 0x00030000UL;                                  // Configure for register-to-memory mode
    DMA2D->OCOLR   = color;                                         // Set the color for filling (format should match the configured color format)
    DMA2D->OMAR    = (uint32_t)pDst;                                // Starting memory address of the fill region
    DMA2D->OOR     = lineOff;                                       // Row offset, i.e., skip pixels (in pixel units)
    DMA2D->OPFCCR  = pixelFormat;                                   // Set the color format
    DMA2D->NLR     = (uint32_t)(width << 16) | (uint16_t)height;    // Set the width and height of the fill region (in pixel units)

    /* Start transfer */
    DMA2D->CR   |= DMA2D_CR_START;

    /* Wait for DMA2D transfer completion */
    while (DMA2D->CR & DMA2D_CR_START) {}
}

				
			

Kolaylık olması açısından, bunu ekranınızın koordinat sistemine göre bir dikdörtgen doldurma işlevi içine alalım:

				
					void FillRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color) {
    void* pDist = &(((uint16_t*)framebuffer)[y*320 + x]);
    DMA2D_Fill(pDist, w, h, 320 - w, LTDC_PIXEL_FORMAT_RGB565, color);
}

				
			

Son olarak, bu bölümün başında gösterilen grafiği çizmek için şu kodu kullanalım:

				
					// Fill background color
FillRect(0,   0,   320, 240,  0xFFFF);
// Draw data bars
FillRect(80,  80,  20,  120,  0x001F);
FillRect(120, 100, 20,  100,  0x001F);
FillRect(160, 40,  20,  160,  0x001F);
FillRect(200, 60,  20,  140,  0x001F);
// Draw X-axis
FillRect(40,  200, 240, 1,    0x0000);

				
			

Kodun çalışma şekli şu şekildedir:

The Final Effect of DMA2D Rectangle Filling
The Final Effect of DMA2D Rectangle Filling

Abone ol

Aylık blog güncellemeleri, teknoloji haberleri ve vaka analizleri almak için abone listemize katılın. Asla spam göndermeyeceğiz ve istediğiniz zaman aboneliğinizi iptal edebilirsiniz.

Yazar Hakkında

Picture of Aidan Taylor
Aidan Taylor

I am Aidan Taylor and I have over 10 years of experience in the field of PCB Reverse Engineering, PCB design and IC Unlock.

Yardıma mı ihtiyacınız var?

Scroll to Top

Anında Fiyat Teklifi

Instant Quote