C'de Gerçek Zamanlı Buffer Kullanımı

Başlatan ErsinErce, 09 Ocak 2012, 06:43:42

ErsinErce

Seri Port -> STM32 -> RAM -> STM32 -> Codec yapısında bir aktarım şeklim ve 10KB dan başlayan veri bloklarım var malesef,
yazma ve okuma işlemleri ayrı zamanlarda olacak yani sadece RAM -> STM32 -> Codec yönüne aktarım gibi de düşünülebilir

Normalde 192KB RAM'imiz var ama ilerisi için hesaplamalarda bana lazım olacak bu yüzden ufak bir buffer ile doldur boşalt yapmayı düşünüyorum

Codec'i bir timer ile beslemeyi ve 1KB gibi bir dahili RAM'den ayırıp aktarımı bunun üzerinden yapmayı planlıyorum

ilk aklıma gelen bu 1KB lık alanı 2 ye bölüp eğer ilk 512 byte Codec'e gönderiliyorsa son 512 byte'ı doldurmak ya da tam tersi, şeklinde oldu,
tabi Buffer dolu bayrağı olacak, RAM için kullandığım SPI hattının frekansı 21MHz, Codec için kullandığım ise 5.25 MHz de

bu konuda daha başka nasıl yöntemler izlenebilir ya da ne tarz bir kurgu kullanılmalı fikir verebilirseniz çok sevinirim

ErsinErce


iyildirim

Bu tip işler için DMA kullanmak daha verimli oluyor. 
STM32F4 lerin DMA modülü ile uzun soluklu tecrübem olmadı.
Collision olasılığı bu işlemcide ne kadar var bilmiyorum ama garanti olması açısından tek bir ring buffer yerine iki buffer kullanıp, Uart dan gelen veriyi bir buffere alırken diğer buffer içeriğini yime DMA kullanarak SPI üzerinden göndermek mümkün görünüyor.
UART ' a atanmış DMA kanalının kesmesinde bufferları switch leyip SPI için adres vs. set ettikten sonra SPI 'a atanmış DMA kanalını da tetiklemek gibi bir yapı olabilir.
SPI hızı muhtemelen UART dan daha yüksek olacağı için UART dan gelen veri buffer'ın birini doldurana kadar diğer buffer'ın işlenmiş, içerdiği veri SPI üzerinden gönderilmiş olur.

iyildirim

Gerbay hocam haklısınız, elbette yapılır.

Ancak burada olduğu gibi blok transferler yapılıyorsa,  UART ve SPI hızları arasında fark varsa veri alımı ve gönderimi işini manage etmek gerekir.  Bu da buffer üzerinde iki ayrı pointer tutmak, pointerlerin pozisyonu hakkında karar vermek gibi işler için işlemciye yük getiriyor.   Üstelik her bir byte için.  Öte yandan bu işi tamamen işlemciye yıkacaksak hiç buffer kullanmadan direkt UART kesmesinde gelen veriyi  SPI'ya basmak da mümkün zaten.

İki ayrı DMA kanalını çift bufferla kullanıp, daha düşük hızlı olan UART 'a atanmış kanalda buffer dolunca kesme üretip, hızlı DMA kanalında kesme bile üretmeden, işlemciye minimum yük bindirerek yapmak da mümkün

Eğer gelen veri içeriği kontrol edilecek vs. gibi işler varsa ring buffer kullanmak daha mantıklı. Çift buffer dememin nedeni de DMA de collision olasığını elemek ve gelen veri hızının daha düşük olacağını öngörmem.

ErsinErce

burada kullanacağım olay iki durumu da kapsıyor aslında ama bahsettiğiniz gibi 3 farklı çevre birimin hızları birbirinden çok farklı
(seri port 115200, RAM 21MHz, Codec 5.25MHz)

Wi-Fi modülüne seri port ile erişiyorum, modülde bulduğum bir bug yüzünden HTTP protokolünü manuel başlatmak zorundayım bu sebepten
ilk başta ayarlamaları gönderip sonra bilgi çekmeye başlıyorum gelen bilginin ilk 1000 byte'ında ilk başta almam gereken değişken uzunluklu bir bilgi var,
sonrasında işleme tabi tutmadan direk RAM'e aktarmam gerekiyor,

daha sonra bilgi aktarımı tamamlandığında modülün net bağlantısını kapatıp ilk başta aldığım bilgiden sonraki kısmı 32byte lık bloklar halinde Codec'e basmam gerekiyor.

Circular buffer'a blok ve byte erişimi sağlayacak bir yapı oluşturmayı planlıyorum şu an için her iki durumu da kapsasın ve fazla zaman almasın diye
ama ne kadar sağlıklı olacak bilmiyorum

ilk başta DMA kullanmayı bende düşünüyordum ama işin içinde iş çıkmasından dolayı pek sıcak bakmamaya başladım
diğer yandan Codec'e bilgi aktarımı için kullanacağım bölümü DMA'ya yıkıp işlemciyi boşta bırakmak istiyorum
ama veri aktarımı tamamlanmadan bufferdaki ilgili bölümleri boşta bırakmak olmaz,
dolu kalsa (eğer yolu varsa) DMA'ya işlem sonunda kesme oluşturup aktarılan bölümün bufferdan yerini açtırsam,
bu sefer beslemeyi bekleyeceğim (DREQ) pinin kesmesi ile işleri bozabilir mi diye düşünüyorum

iyice allak bullak oldum =/