CMSIS DSP Kütüphanesini Projeye Eklemek

Başlatan Tagli, 16 Ocak 2022, 13:02:39

Tagli

Projelerimde STM32CubeIDE kullanıyorum ancak CubeMX, HAL vs. kullanmadığım için otomatik kod üretimi de yapmıyorum. Projeye CMSIS kütüphanesini elle ekliyorum, sonra include path'leri tanımlıyorum falan...

Core kısmı kolay, zaten birkaç tane header'dan ibaret. Ama DSP kısmı biraz karışık. Bu zamana kadar (CMSIS 5.7.0 dahil olmak üzere) DSP'nin kendi include klasörüne ek olarak, bir de önceden derlenmiş ve proje ile birlikte verilen .a uzantılı statik kütüphane dosyasını koyup IDE'ye gösteriyordum. Yaklaşık 6 MB boyutundaki bu binary dosya versiyon kontrol açısından biraz gıcık ediyor ancak sorunu git-lfs ile çözmek mümkün.

CMSIS 5.8.0'dan itibaren bu .a uzantılı önceden derlenmiş kütüphane dosyası dağıtılmaz oldu, yani internetten CMSIS'i çekince içinde bu gelmiyor. Ben de o zaman source klasörünü de projeye ekleyeyim, onu da derlesin dedim. Ama olmadı. Nedense linker DSP içindeki sanırım her fonksiyon için re-definition hatası veriyor (yanlış hatırlamıyorsam 1042 tane hata verdi). Halbuki çok standart bir işlem olması gerekirdi. İlgili source klasörünü eklemezsem de bu sefer hiç bulamıyor (doğal olarak). Nerede hata yapıyor olabilirim?

Ekleme: Şimdi 5.7.0'ı source olarak eklemeyi denedim, onda da aynı sorun oluyor.
Gökçe Tağlıoğlu

Tagli

#1
Bu yazının yardımı ile sorunu çözdüm.

CMSIS-DSP'nin source dosyalarında nedense şöyle bir salaklık/sapıklık yapmışlar: Atıyorum A adında bir klasör var. Bunun içinde x.c, y.c, z.c dosyalarının yanı sıra bir de A.c dosyası var. A.c dosyası içinde x.c, y.c, z.c include edilmiş. Evet doğru görüyorsunuz, .h değil, aynı klasördeki .c dosyalarını include etmiş.

Kütüphanenin normalde cmake ile derlenip, oluşacak statik kütüphanenin projeye eklenmesi planlanmış muhtemelen. Ancak yukarıdaki gibi bir sapıklığın sebebinin ne olabileceğini anlayamıyorum bir türlü. .c dosyası include etmek bence özrü/açıklaması olamayacak bir kural ihlali. Üstelik bu dosyalar zaten aynı klasörde duruyorlar.

Ekleme: Burada bir açıklama yapmışlar ama pek anlamadım.
Gökçe Tağlıoğlu

brandice5

Jonatan reis aslında açıklamış sebebini. Eğer sen full DSP kütüphanesini kullanmak istiyorsan, fonksiyonları ayrı ayrı dosyalarda değil tek dosayda derlemek derleme hızını arttırıyor diyor.

Ama diyelimki full DSP kütüphanesine ihtiyacın yok, sadece bir kaç fonksyion kullacaksın. O zaman tüm fonksiyonları derleyipte derleme zamanını uzatmanın ve kütüphane boyutunu arttırmanın bir anlamı yok, elle istediğin fonksiyonları tek tek seç projene ekle diyor. Bir nevi cherry-pick yani.

magnetron

hocam bu CMSIS ne oluyor

HAL veya SPL veya LL nin yapmadığı neyi yapıyor

Tagli

@brandice5 , o kısmı anladım gibi ama bahsettiği build system'i anlamadım. Fonksiyonları içeren küçük ve çok sayıdaki dosya olmadan diğer toplu include dosyası da bir işe yaramıyor. Yani build system'in dosyalara ulaşabilmesi, ama .c uzantılı olmalarına rağmen bunları değil sadece diğer toplu include dosyasını derlemesi gerekiyor. cmake bunu yapabiliyor mu? Yoksa üzerinde başka bir katman mı var?

Bu arada şunu da hatırlatmakta fayda var: Modern derleyiciler kullanılmayan foknsiyonları binary'den ayıklayabiliyorlar, böylece bunlar flash'ta gereksiz yer kaplamıyor. Yani bence her fonksiyonu ayrı .c dosyasına koymak bence biraz gereksiz olmuş. Belki daha eski derleyicileri de bu konuda desteklemek istemişlerdir. Örneğin SDCC derleyicisi (ARM ile ilgisi yok gerçi) her fonksiyon kendi dosyasında olmadığı sürece bunu yapamıyor.

@magnetron , CMSIS ARM'ın kendi hazırladığı bir kütüphane standartı. Her ARM işlemcide olabilecek bazı özellikleri kütüphane olarak sunuyor. Bazı özellikleri ise, başka kütüphanelerin izlemesi gereken kurallar gibi sunuyor. Hazır kütüphane olarak sundukları genelde çevre birimlerinden bağımsız, sadece işlemci çekirdeği ile ilgili kısımlar. SPL'yi bilmiyorum ama HAL veya LL kullanıyorsan arka planda CMSIS de var demektir zaten. CMSIS kütüphanesi ST'nin kendi Cube paketlerinin içinde de geliyor ama genelde son versiyon olmuyor.

Genelde CMSIS'in son versiyonu kullanıyor olmak çok da önemli değil. Genelde büyük değişiklikler olmuyor. Beni daha çok binary olarak saklanan kütüphane dosyası (.a uzantılı olan) rahatsız ediyordu. Son versiyonda (5.8.0) bu dosyayı hazır derlenmiş olarak göremeyince diğer yolu da araştırmak istedim, çünkü muhtemelen gelecekte de bu dosyayı paylaşmayacaklar.

Bu arada, CMSIS'i olduğu gibi versiyon kontrole koyma konusunda da kararsız kaldım. Daha önce header'ları koyuyordum gerçi. Ama şimdi source dosyalarını da koymam gerekecek. Kütüphane dosyalarının proje repo'sunda olup olmaması meselesi tartışmaya açık bir konu. Bu forumda daha önce sorup sormadığımı hatırlamıyorum ama StackOverflow'da sormuştum. Sonunda dahil etmeye karar verdim.
Gökçe Tağlıoğlu

Cemre.

Projeleri Keil ile oluşturup orada ilgili cmsis kütüphanelerini de seçebiliyorum. Eğer keil kullanıyorsanız cubemx ile de uğraşmadan yapabilirsiniz kolayca.

Tagli

Aslında belki kütüphaneyi dışarıda tutmak da işime gelebilirdi, eğer IDE standart bir yol sunarsa. Maalesef STM32CubeIDE'de böyle bir özellik göremedim. Yani .pack dosyalarını sisteme ekleyip projede çağırmayı bulamadım.

.pack dosyasını "Manage Embedded Software Packages" menüsünde eklemek mümkün. Ancak bu durumda CMSIS projede görünür olmadı. Anlaşılan ben bir adımı atlıyorum, belki de Cube bu işi kendisi otomatik yapıyor.
Gökçe Tağlıoğlu

brandice5

Alıntı yapılan: Tagli - 16 Ocak 2022, 18:26:53o kısmı anladım gibi ama bahsettiği build system'i anlamadım. Fonksiyonları içeren küçük ve çok sayıdaki dosya olmadan diğer toplu include dosyası da bir işe yaramıyor. Yani build system'in dosyalara ulaşabilmesi, ama .c uzantılı olmalarına rağmen bunları değil sadece diğer toplu include dosyasını derlemesi gerekiyor. cmake bunu yapabiliyor mu? Yoksa üzerinde başka bir katman mı var?

Jonatan'ın dediğine göre Keil'de ki "Run-Time Environment Manager" bu işi yapıyormuş. Sanırım Keil IDE ye has bir özellik.

https://www.keil.com/support/man/docs/uv4/uv4_ca_rtemanager.htm

Alıntı yapılan: Tagli - 16 Ocak 2022, 18:26:53Bu arada şunu da hatırlatmakta fayda var: Modern derleyiciler kullanılmayan foknsiyonları binary'den ayıklayabiliyorlar, böylece bunlar flash'ta gereksiz yer kaplamıyor. Yani bence her fonksiyonu ayrı .c dosyasına koymak bence biraz gereksiz olmuş. Belki daha eski derleyicileri de bu konuda desteklemek istemişlerdir. Örneğin SDCC derleyicisi (ARM ile ilgisi yok gerçi) her fonksiyon kendi dosyasında olmadığı sürece bunu yapamıyor.

Hayır, gereksiz değil. Nedenine gelince, bir static library yani .a (archive) dosyası aslında object (.o) dosyalarının paketlenmiş halinden başka birşey değildir.
Şimdi örneğin DSP kütüphanesi içindeki "FilteringFunctions" klasörünü ele alalım. Sanırım bu klasör içinde aşağı yukarı 100 adet ayrı fonksiyon C dosyası var.
Şimdi sen bu klasördeki bütün C dosyalarını ayrı ayrı derlersen sonuç olarak 100 adet object (.o) oluşacak ve oluşturulan archive (.a) dosyasında da 100 adet .o dosyası bulunacak.

İkinci seçecek olarak sadece "FilteringFunctions.c" dosyasını kullanırsan, compilation unit 1 adet olacağı için sonuçta 1 adet object (.o) dosyası oluşacak ve oluşturulan archive dosyasında sadece 1 adet object dosyası bulunacak.

Şimdi gelelim derleyicinin yaptığı optimizasyona. Evet derleyici optimizasyon yapıyor ama fonksiyon bazında değil, object bazında.
Yani sen bu 100 adet fonksiyonun sadece 1 adedini kullandığın durumda, derleyici birinci seçenekte oluşan archive dosyasının içindeki sadece 1 adet object dosyasını linkleyecek ve kalan 99 object dosyasını linklemeyip binary ye eklemeyecek.

Ama ikinci seçeneği seçersen, sadece 1 adet fonksiyon kullansan bile bütün fonksiyonlar tek bir object dosyada bulunduğu için object dosyanın tamamı linklenecek ve senin final binary çıktın kullanmadığın 99 adet fonksiyonu da içerecek.

Yani sonuç olarak Jonatan reis diyor ki, DSP kütüphanesinin bütününü veya bütününe yakınını kullacacaksan, tek compilation unit kullanmak daha avantajlı.
Ama yok sadece bir kaç fonksiyon kullanacaksan, compilation unitleri ayır, derleyici zaten kullanılmayanları atar.

Tagli

Alıntı yapılan: brandice5 - 16 Ocak 2022, 20:36:27Ama ikinci seçeneği seçersen, sadece 1 adet fonksiyon kullansan bile bütün fonksiyonlar tek bir object dosyada bulunduğu için object dosyanın tamamı linklenecek ve senin final binary çıktın kullanmadığın 99 adet fonksiyonu da içerecek.
Modern derleyiciler için bu geçerli değil diye biliyorum. Örneğin GCC'de "place functions in their own sections" (-ffunction-sections) diye bir seçenek var. Elbette tüm fonksiyonlar .o dosyasının içinde olacak ama anladığım kadarıyla kullanılmayan section'lar link sırasında elenebiliyor. Bu durumu kendi yazdığım kodda da gözlemleyebiliyorum. Normal bir .c dosyasında bol miktarda fonksiyon tanımlı olsa da, kullanmadıklarımı binary'de görmüyorum.

Eski ya da basit derleyiciler buna imkan vermiyor olabilir. CMSIS geniş bir ürün yelpazesine hitap ediyor. Belki bu bahsettiğim optimizasyon seçeneğinin mevcut olmadığı toolchain'lere de en iyi şekilde hizmet vermek istiyorlardır.

Bu arada tabi ki tüm DSP kütüphanesini tek .c dosyasına koymazdım ama şimdi mesela "FilteringFunctions" klasöründeki dosyalar tek bir .c dosyasında birleştirilebilirdi bence.
Gökçe Tağlıoğlu

brandice5

@Tagli evet, gcc'de -ffunction-sections parametresi var, ama birkaç sebepden dolayı bence hala diğer yöntemi kullanmak daha mantıklı;

1. Bu parametre default olarak aktif değil. Ayrıca sadece kütüphane oluştururken bu parametreyi aktif etmek yeterli değil, ana uygulamayı linklerkende "-Wl,--gc-sections" parametresini eklemek gerekiyor.
2. Kütüphaneyi kaynak kod olarak değil de, derlenmiş static kütüphane olarak alırsanız bu parametreyi aktif etme şansınız olmayacak. Dolayısıyla ana uygulamayı gerekli parametreler ile derleseniz bile işe yaramayacak.
3. Portable değil, dediğiniz gibi diğer derleyicilerde çalışmayabilir.
4. Dosya boyutunda -ffunction-sections parametresinden kaynaklanan bir overhead oluşuyor. Gerçi bunu toplam ayrık object dosya botutuyla karşılaştırmak lazım, burada belki avantaj olabilir.
5. Derlenecek compilation unitleri tek tek seçerseniz derleme hızına oldukçe etki edecektir. -ffunction-sections yönteminde sadece 1 fonksiyon kullansanız bile yine kalan 99 fonksiyonuda derlemek zorundasınız.

Sonuç: hangisini kullanacağınız size kalmış. Ben ekstrem bir durum olmadıkça mevcut yöntemi kullanırdım.