Flash bu kadar hızlı mı doluyor?

Başlatan papsukkal, 22 Nisan 2024, 12:15:34

papsukkal

Son zamanlarda STM32F030F işlemci ile oynuyorum. Ayrı ayrı projelerde 02 kanal ADC DMA, 2 kanal PWM DMA, 1 UART, 1 I2C çalıştırdım. Daha sonra bu projeleri birleştirmeye karar verdim.

Temelde ADC ve PWM, DMA  üzerinden sabit sinyal okuyor ve üretiyorlar. I2C sadece tanımlı. Bunun ile ilgili hiç bir kod yazılı değil henüz. UART ile ilgili telefonda oluşturduğum uygulama ile temel seviyede haberleşecek kadar kod var.

STM32F030F4 16k flash hafızaya sahip. Temel seviyede yaptığım bu konfigürasyonlar 16k ya sığmıyor. 19k civarı kod oluştu. ilk başta derlemedi.

MEMORY
{
  RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 4K
  FLASH    (rx)    : ORIGIN = 0x8000000,   LENGTH = 32K
}

FLASH LENGHT TANIMINI 16 dan 32 ye değiştirince derleme tamamlandı ama 19k boyutunda kod oluştu.

Bunun sebebi HAL kütüphaneleri mi? Register düzeyinde çalışınca daha mı az yer tutar kodlarımız? Bu kodları hafifletmenin bir yöntemi var mı?

Bu konuda bilgi-tecrübe ve önerileriniz nelerdir?

Z80

#1
Evet bunun sebebi HAL kütüphaneleri. CMSIS kullanmanızı şiddetle öneririm. Daha az yer tutar ve daha basittir.

Belki ilk başlarda biraz zorlanırsınız ama sistemi bir kere oturtunca çok rahat edersiniz.

Bana CMSIS, HAL'den daha kolay geliyor. Registerlerle uğraşmak gözünüzü korkutmasın.

IDE olarak KEIL, derleyici olarak da CLANG yani KEIL içinde "Compiler V6" kullanın. Değişik optimizasyon seçenekleriyle çok farklı boyutlar elde edebilirsiniz.

AST

Dünden beri bununla uğraşıyorum.ATmega328 için yazdığım kod 10K.Aynı yazılımı CubeIDE ile STM e uyarlayayım dedim 27K.Heap ve stack azaltınca RAM kullanımı düşüyor.Fakat Flash hafızası için pek bir optimizasyon ayarı göremedim.
Derleme ayarlarında "-flto" kullanımını önermişler.Bende pek işe yaramadı.Sizin kodunuzda iş görebilir.
Build işlemini "Release" konfigürasyonunda yapıyorsunuz değil mi?
Keilin daha iyi kod optimizasyonu yaptığı belirtilmiş.

flowchartx

Keilde -Oz image optimizasyon var belli bir derecede kodları optimize ediyor. Tabi kodun doğru çalıştığına emin olup kullanılması gerekir.

Tagli

"Build Analyzer" penceresinde bellek tüketimlerinin ayrıntıları görülebilir. Varsayılan olarak isme göre sıralıyor ancak "Size" sütununa basılırsa boyuta göre de sıralar. Her section içindeki tüm semboller (fonksiyonlar, değişkenler) burada gözüküyor (sol taraflarındaki küçük oklara basarak listeleri açın). Gerçi bazen nedense bir şeyi iki kez sıraladığı oluyor ama anladığım kadarıyla iki kez yer kaplamıyorlar. Bu pencere sayesinde Flash'ı veya RAM'i nelerin şişirdiğini kolaylıkla görebilirsiniz. Elbetteki buradaki alana dinamik RAM kullanımları dahil değil. _user_heap_stack bunu temsil etmesi için konulmuş ancak gerçek değeri değil sadece bizim linker dosyasında bildirdiğimiz tahmini kullanım miktarını yansıtıyor.

Bu arada buradaki içerikler derleyicinin ürettiği .map dosyasından çekiliyor aslında.

Gökçe Tağlıoğlu

AST

Bugün aynı yazılımı Keil(5.29)'da HAL kütüphaneleri ile derledim, 21K(optimizasyon 3).

papsukkal

Aslında stm32f030f4 yerine stm32g030c6 kullanmaya karar verdim. 32k flash ve timer sayısı ile ve fiyatı ile bana daha uygun olduğunu fark ettim. Ama farklı derleyiciler ve farklı modlarla kod boyutunun değişebileceğini de öğrenmiş oldum.
 
Arm konusunda daha çok yeni olduğumdan bahsettiklerinizi araştırıp öğrenmem gerekiyor. Mesela @AST  hocamın bahsettiği release modunda mı derlediğimi bilmiyorum. Sadece derliyorum.

@Tagli hocamın bahsettiği build analyzeri inceleyeceğim.

CubeIdeye henüz hakim değilken keile geçmek sanırım kafamı karıştırır ama ilerleyen zamanlarda elbette.

Daha öğrenecek çok şeyim var vesselam.

joshuato

Ben de ARM Cortex-M üzerinde geliştirme yapıyorum. ЄBu, AVR'ye kıyasla daha karmaşık mimarisi nedeniyle gerçekten daha karmaşıktır, ancak aynı zamanda daha fazla özellik ve performans sağlar.

papsukkal

@AST Release modu ile 10k ya düştü. Debug modundaymışım. Teşekkür ederim

serkan

#9
Bu seçenekleri denedinizmi.? 101 kb yi 80 kb ye düşürdü.
 


Tagli

Bazı optimizasyon ayarlarının birbirleri ile çatışan öncelikleri olduğunu unutmamak lazım. Yüksek hız için optimize edilmiş bir kod daha fazla bellek tüketebilirken, tam tersi şekilde düşük bellek tüketimi için optimize edilmiş bir kod daha yavaş çalışabilir. Bu durum sadece derleyici ayarları ile ilgili değil, kodun yazılış şekli ile de ilgili. İhtiyaçlara ve kısıtlara göre karar vermek gerekli.
Gökçe Tağlıoğlu

papsukkal

#11
@serkan deneyeyim.

Aslında soracağım o kadar çok soru var ki.. Cevabını bulduğum bir soru yanında en az iki soru getiriyor.

Debug mod ile Relase mod arasında tam olarak ne farklar var ki bu kadar hacim değişiyor? @Tagli hocamın dediği gibi hız ile alakalı optimizasyonlar mı buna neden oluyor? Release mod seçili iken de daha az olan kodlarla gayet güzel debug yapılabiliyor?

Neden cubeideyi kurunca default olarak debug mod geliyor? Debug modun Avantajı nedir?

flowchartx

Debug modunda hata ayıklama için daha fazla bilgiviçerir. Bu nedenle fazla bellek kullanılır ve çok fazla optimize yapılmaz. Release genellikle artık kod bittiktwn sonra hex almak için yapılır hata ayıklama için çok az bilgi eklenir ve iyi bir optimizasyon yapılır. Releaseda yapılan bu iyi optimizasyon bellek kullanımında azaltır. Ben böyle biliyorum daha iyi bilenler düzeltebilir :)

Tagli

"Debug" ve "Release" aslında konfigürasyon isimleri. Optimizasyon seviyeleri için GCC'nin notasyonunu kullanmayı tercih ediyorum. Bunlar -O0, -Og, -O1, -O2, -O3 ve -Os.

-O0'da hiç optimizasyon yok, kod hem yavaş çalışıp hem çok yer kaplıyor. Aslında debug için bile pek iyi bir seviye değil.

-Og ve -O1 birbirine çok yakın. -Og debug için optimize ediyor, ama -O1 ile de güzel debug yapılabiliyor. Benim kullandığım varsayılan seviye -O1 ki bence bu kodun son halinde de kullanılabilecek makul bir optimizasyon seviyesi.

-O2 bir tık daha fazla optimizasyon yapıyor. Debug yeteneğini kaybetmeye başlıyoruz burada.

-O3 ve -Os aslında yol ayrımı. -O3 hızı arttırmaya, -Os ise bellekten kazanmaya odaklanıyor.

Aslında daha başka seçenekler de var, ki ben yukarıdakileri de yarım yamalak açıklayabildim. GCC'nin kendi dokümantasyonuna bakmak lazım ayrıntılar için. ARM derleyicisi için bunların hangileri geçerli ve anlamlıdır ben de bilmiyorum. CubeIDE'nin menüsünde bu kadar seçenek yok, ama belki elle manuel olarak eklenebiliyordur.

Bence çok kafayı yormaya gerek yok aslında. Tavsiyem, -O1 yap geç. -O0 ile -O1 arasında uçurum var. Ama ondan sonra çok ciddi bir bellek kullanımı farkı görmeyeceksin.
Gökçe Tağlıoğlu

flowchartx

@Tagli hocam peki konu açılmışken size bir soru sormak istiyorum. Diyelim ki bir proje geliştiriyorsunuz işlemci seçimi vs. hepsi yapıldı, hardware tamamen hazır. Siz kodları yazmaya başladınız belli bir yerden sonra sığmayacağını ya da bin bir taklayla sığdıracığınızı anlıyorsunuz. Bu durumda nasıl bir yol izlersiniz ? Hardware'i bozmadan eziyet çekip kodu sığdırmak mı yoksa işlemciyi değiştirmek mi?