DMA çalışması hakkında anlayamadığım konu

Başlatan Mucit23, 07 Mart 2016, 11:04:53

Mucit23

Selamlar,

Bu konuda bir sorum olacak.

STM32F7 Discoda OV9655'den veri transferi DMA ile yapılıyor. Örnek uygulamada 320x240 çözünürlük için DMA veri boyutu olarak 0x9600, 480x272 çözünürlük için ise 0xFF00 tanımlanmış.

Kamera RGB565 formatında çıktı veriyor. Her bir pixel 16 bit. Bu değerleri nasıl hesapladılar diye düşünürken şöyle bir sonuca vardım.

DMA ayarlarında Donanım ve Memory boyutları WORD olarak tanımlı

  hdma_handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
  hdma_handler.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;

Bildiğim kadarıyla bu işlem 32 bit transfer yapılacağını bildiriyor.

320x240 için hesaplarsak toplamda 76800 pixel var. Her bir pixel 16 bit olduğundan dma tek seferde 2 adet pixelin datasını 32 bit ile taşıyabilir. Dolayısıyla 76800/2=38400=0x9600 yapar.

Aynısı 480x272 için geçerli.
480x272=130560 pixel yapar.

130560/2=65280=0xFF00 yapar. Yani değerler tutuyor.

Aklıma takılan konu şudur.

DCMI'data veri boyutunu 8 bit olarak ayarlı durumda. DMA veri boyutu ise 32 bit. Sistem bu şekilde nasıl çalışıyor anlamadım. Sistemin doğru çalışması için DMA'nın sırayla DCMI'dan 4 byte veri alıp düzgün bir şekilde hizalayıp 4. tetikleme geldikten sonra transfer yapması lazım.

Günün sorusu; DMA DCMI ikilisi nasıl düzgün bir şekilde çalışıyor? 

Mucit23

Bu konuda bilgisi olan yokmu? Kaynak adresin veri boyutu 8 bit ve DMA transfer boyutu 32 bit ise DMA nasıl çalışıyor?

Bir de şu konu var. Eğer Transfer boyutumuz 65535'den fazla ise DMA Double Buffer modunda çalışıyor. Bu özellik için ekstra bir ayar gerekiyormu? Nedir nasıl çalışır öğrenmem lazım.

yldzelektronik

Bildiğim kadarıyla aynı şekilde çalışıyor @Mucit23.

Sonuçta dmanın ne olduğunu biliyorsun.Gösterdiğin adresten gösterdiğin adrese gösterdiğin genişlikte veri taşır.32bit diye hepsini doldurmak durumunda değilsin ki.Kaldı ki halfword vardı diye de hatırlıyorum dma ayarlarında.
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

DaRt

#3
Dcmi ve fsmc arasında dma ile sürekli bir ver akışı olacağı için dma mode circular olacak. Dmayı br kez kurduk mu sonsuza kadar transfer sağlayacak. Dolayısı ile double buffer moda gerek yok. Örneğin  sdcarddan alınan veriyi wav olarak çalacaksak veriyi paket paket alıp daca göndermek gerekir. biz bir paketi alırken diğer paketi seslendirebiliriz. böyle durumda gerekir double buffer

Diğer taraftan biz dcmi arayüzünü kurarken verilerin 8bit olarak alınacağını söylüyoruz ve dcmi arayüzü bizim için dcmi adresine yazıyor bunu. Ayrılan alan 32 bit. Daha sonra biz dma ya diyoruz ki dcmi adresinden veriyi sürekli olarak fsmc alanına yaz. Fsmc de 32 bit. Dmanın herhangi bir dönüşüm yapmasına gerek yok. Daha sonra fsmc arayüzüne diyoruz ki fsmc adresinde veri var ve bu veri 32 bit sen bunu 16 bit kanaldan yolla lcdye. Bu çevrimler donanımsal olarak yapılıyor. Nasıl yapılıyor. bunun için http://www.st.com/web/en/resource/technical/document/application_note/DM00046011.pdf dokumanın 11 ve 12. sayfaları açıklıyor biraz.

Edit: Konunun fsmc ile ilgili olmadığını sonradan anladım. Alakasız olmuş biraz ama dursun kenarda.

Mucit23

#4
@yldzelektronik, Konuya dahil olduğun için teşekkürler. Benim anlamadığım konu şu.

İlk verdiğim örnekte birkaç sayısal değer vermiştim.

Alıntı Yap320x240 için hesaplarsak toplamda 76800 pixel var. Her bir pixel 16 bit olduğundan dma tek seferde 2 adet pixelin datasını 32 bit ile taşıyabilir. Dolayısıyla 76800/2=38400=0x9600 yapar.

DMA'nın transfer boyutunu belirlemem gerekiyor. Bu yüzden konuyu anlamam lazım. İlk mesajımda 320x240 RGB565 için DMA transfer boyutunun yani 0x9600 değerinin nasıl hesaplandığını anlatmıştım. Yukarıdaki örnekte Her bir pixel datası 16 bit olduğu için 2 adet pixel datası 32 bit'te birleştirilip öyle gönderiliyor. Evet dediğin gibi bu işin DMA ile alakası olmaması lazım. Çünkü ben dma'da veri kaynak ve hedef adreslerin veri boyutunun 32 bit olacağını belirtmişim.

Debug esnasında Kamera çalışırken sistemi durdurduğumda DCMI->DR (Data register)registerinin 32 bit değerler aldığını görüyorum. Halbuki ben sadece kameradan 8 bit data girişi yapıyorum.

Şunu kesinleştirmem lazım.

DCMI donanımında gelen verinin 8 bit olacağını aşağıdaki satırla belirliyorum.

phdcmi->Init.ExtendedDataMode = DCMI_EXTEND_DATA_8B;

O halde şöyle diyebilirmiyiz. DCMI donanımında kameradan veri girişi 8 bit olduğu zaman her gelen 4 byte'ı shift yaparak 32 bitte birleştirip ondan sonra DMA'ya iletiyor. DMA'da sıradaki adrese yazıyor.

Sonuç olarak hesaplarda şöyle bir farklılık çıkıyor. 480x272 çözünürlük için bakalım. Toplamda 480*272=130560 pixel var.

Eğer DCMI her 4 byte'ı 32 bitte birleştiriyorsa benim toplam transfer sayım 130560/4=32640=0x7F80 olur.
Eğer DCMI her bir byte'ı ayrı ayrı taşıyorsa 130560 adet transfer yapar. Transfer sayısı 65535'den fazla olduğu için Double buffer gerekli olur.

Öyle yada böyle bu işin doğrusunu öğrenmem lazım. Diğer türlü ilerlemek zor oluyor. Keşke @Klein buralarda olsaydı o bu konuları iyi biliyordu.

Double buffer yüksek boyutta gerekli anladığım kadarıyla. Örneğin DCMI'dan 2592'ye 1944 boyutlarında bir resim alsam İllaki Double buffer gerekli olacak. Şuan double buffer ile uğraşmamak için çözünürlüğü düşük tutuyorum. 

mesaj birleştirme:: 08 Mart 2016, 12:23:02

Evet aynen dediğim gibi sanırım. DCMI gelen dataları birleştiriyor. Şimdi hesaplar oturdu gibi. Böyle yapmalarının sebebi sanırım DMA'nın aşırı meşgul olmasını engellemek. RM0385 kodlu datasheet sayfa 485'de anlatılmış. Ben ilk başta DMA ile ilgili olduğunu düşünmüştüm.

Şimdi tek bir sorunum var. DMA kesmeleri ile birlikte DCMI kesmelerini aktif edince DMA çalışmıyor. DMA TC kesmeleri vs oluşuyor ama hafızaya sürekli 0xFF yazıyor. Ama DCMI kesmelerini kapatınca hafızanın ilgili bölgesinde kamera ile değişen değerler görüyorum.

Uğraştığım kameradan görüntü alabilmem için bundan sonra RGGB Bayern to RGB işine yönelmem lazım.