STM32 cubeIDE-SWV İLE HATA AYIKLAMA-1

STM32 cube IDE platformu üzerinde proje oluşturarak gömülü uygulama geliştirme konularında epeyi yol aldık. Artık sıra biraz daha ileri konulara geldi.

Bu başlangıç, bundan böyle hayatımızı daha zorlaştıracak işlere el atacakmışız izlenimi veriyor ama öyle değil. Tersine, şimdiye kadar kullanmadığımız bazı teknikleri öğrenip, çalışmalarımızı kolaylaştıracak yeni araçlar keşfedeceğiz.

Bu yayında ARM Cortex M çekirdeğinin SWV ve ITM araçlarını kullanmayı öğreniyoruz. Bu serinin ilk bölümünde konuya giriş yapıp, başlangıç ayarlarına ve bir kod blokunun çalışma süresinin SWV ile nasıl ölçülebileceğine bakacağız.

HATA AYIKLAMA ARAÇLARI

Konumuz: hata ayıklama, İngilizce karşılığıyla “Debugging”. Yazılım geliştirme sürecinin önemli bir bölümünü hata ayıklama çalışmaları oluşturuyor. Yaygın olarak kullandığımız teknik ise koşmakta olan kodumuzu muhtelif noktalarda durdurarak, ya da ekrana, seri porta gönderdiğimiz mesajlarla değişkenlerimizin değerlerini gözlemek oluyor.

Bunun için elimizin altında bulduğumuz ilk araçlar kullandığımız geliştirme platformunun bize sundukları oluyor. STM32 cubeIDE nin Debug modunda iken yukarıda görülen penceresini ve benzerlerini hepimiz kullanmaktayız.

Yalnız, programımızın çalışmasını duraklatarak yapılan bir hata ayıklama süreci, kesmeler, zamanlayıcılar, bunların olaylara yanıt sürelerinin devrede olduğu bir curcuna içinde pek işe yaramıyor.

Bu yayında, başlangıç dönemini geçirmiş her yazılımcının zaten bildiği bu IDE araçları ile, ya da program içine serpiştirdiğimiz duraksatma-görüntüleme yöntemlerine dayanan hata ayıklama tekniklerini anlatmayacağım.

Onun yerine ARM Cortex çekirdeklerinin sunduğu biraz gözden ırak kalmış SWV ve ITM olarak anılan araçların kullanımını anlatacağım.

SWV ve ITM ARAÇLARI – NEDEN KULLANALIM

ARM Cortex-M çekirdeklerinde bulunan SWV – Serial Wire Viewing ve bunun bir parçası olan ITM-Instrumentation Trace Macrocell araçları bazı durumlarda alışılmış hata ayıklama yöntemlerine göre daha kullanışlı ve yetenekliler:

  • Program parçacıklarının çalışma sürelerinin çok hassas şekilde ölçülmesi
  • Anormal değerler alan değişkenler ve bellek konumlarının üzerinde iz sürülmesi
  • Program akışının durdurulmasından etkilenen süreçlerin analizi (Örneğin kesme’ler)
  • Görüntüleme yapılacak bir ekran bulunmaması
  • Debug verisi gönderilebilecek bir seri port bulunmaması

SWV ve ITM KULLANILARAK YAPILABİLENLER

  • ST-Link debugger’a, bir kod blokunun başlangıcında ve bitişinde birer karakter göndererek arada geçen süreyi nanosaniyeler çözünürlüğünde ölçebiliriz
  • CPU yu en çok meşgul eden süreçleri istatistiksel verilerle sıralayıp, optimizasyon için nerelere odaklanacağımızı belirleyebiliriz.
  • Seçtiğimiz değişken ya da bellek adreslerindeki değişiklikleri “time stamp” dediğimiz zaman etiketleri ile birlikte kaydedip (log) inceleyebiliriz.
  • Program akışını kesmeden, oluşan kesmeleri (Interrupt) kaydedip inceleyebiliriz
  • İlave bir UART bağlantısı ya da ekran kullanmaksızın program akışı içinden cubeIDE konsollarına text mesajlar gönderebiliriz.
  • Değişkenlerin zaman eksenindeki değişimlerini osiloskop benzeri bir pencerede grafik olarak görüntüleyebiliriz.
  • Hepsinden önemlisi, Bütün bunları CPU ya hemen hiç bir yük getirmeden ve meşgul etmeden yapabiliriz.

Bunların karşılığında bu araçların kullanımını öğrenmek için biraz vakit ve enerji ayırmak gerekiyor elbette.

ST Link V2 YE İLAVE BAĞLANTI – SWO TELİ

Ha, bir de; ST-Link SWD modunda kullandığımız 4 tele (GND, VCC, SWDIO, SWCLK) ilaveten SWO hattını da kullanacağız. Bu teli eklemek için elimize havyayı almamız gerekebilir.

13 Nolu SWO pinini, STM32F103 de PB3 pinine bağlamak gerekiyor.


Öte yandan bu “öğrenme ve bir adet tel ekleme” çalışması geri dönüşü çok hızlı bir yatırım, bir koyup beş alıyorsunuz karşılığında.

Bu yayın serisinde, mikro denetleyicilerle uğraştığım bunca yıldan sonra, hadi artık bunu da kullanayım artık, iyi bir şey galiba dediğim, sonunda da daha önce niye kullanmamışım diye hayıflandığım bu geliştirme araçlarını anlatacağım.

Bu anlattıklarımı Magnus Unemyr’nın buradan erişebileceğiniz Blog Sitesinden öğrendim.

KULLANDIĞIM DONANIM ve PROJE KURULUMU

Son iki yıldır Apple MacOS üzerinde, STM32 Cube IDE platformunda çalışıyorum. Bu sunum için kullandığım STM32F103C8 Pico modülü. Modül ile PC birbirine ST Link V2 debugger/programlama probu ile bağlı.

STM32F103C8 Pico Model ve ST Link V2

Fotoda ST-Link in SWD modunda kullanılması için yeterli olan 4 telli konnektörünün dışında iki tane daha tel görünüyor. Bunlardan Mavi renkli olanı NRST teli. Bu uygulamada fonksiyonel değil, olmasa da olur. Diğer ilave tel ise Beyaz renkli olan, PB3 ile ST-Link’in SWO pinlerini birleştiriyor.

Görüldüğü gibi, burada anlatacağım izleme, görüntüleme işleri için gereken her şey bunlardan ibaret. Osiloskop yok, PC ye veri aktarmak için UART bağlantısı yok, kodu izleyebilmek için mesajların gönderileceği bir ekran da yok. STM32 Modülün beslemesi de PC nin USB sinden olunca, çalışırken masaya oturmanıza bile gerek yok.

STM32 Yİ SWV MODUNDA ÇALIŞTIRMAK

Bu paragrafta yeni proje oluşturarak başlayıp ilerleyeceğim. İlk bir kaç sayfayı hızlıca geçebilirsiniz.

Önce yeni bir proje başlatarak, STM32F103C8 MCU için kurulumunu yapalım.

File/New/STM32 Project menusü ile yeni projeyi oluşturmaya başlıyoruz.
MCU seçimi

MCU seçimini yaptıktan sonra Next tuşuna basılınca aşağıdaki CubeMX penceresi geliyor.

Cube MX penceresi

Bir sonraki adımda SYS sekmesi altındaki Debug ayarlarını yapacağız. Burada daha öncekilere göre biraz farklı bir seçim yapacağız. Hep “Serial Wire” seçeceğini seçerdik. Bu defa 5. seçenek olan “Trace Asynchronous Sw” yi seçeceğiz. Böylece cube MX, PB3 pininin SWO olarak kullanılacağını bilecek.





Yukarıdaki seçim yapıldığında her zaman alışık olduğumuz PA13-PA14 SWD pinlerine ek olarak PB3 pinin de yeni görevi olan SWO ile etiketlendiğini göreceğiz.

Sırada Osilatör seçimi var. Kullandığım Pico modülde harici kristal olduğundan ben seçimimi aşağıdaki gibi yaptım.

Harici kristal seçimi

Şimdi de sistem saat ayarlarını yapalım. Sistem frekansı 72MHz olacak şekilde aşağıdaki ayarları yapalım.

Sistem saat yapılandırması

Artık Project/Generate Code komutu ile proje kodlarımızı oluşturabiliriz.

Cube MX da yapılacak ayarları tamamladık, artık “Generate Code” ile proje şablonumuzu oluşturabiliriz.

TEST PROGRAMIMIZ

main.c while(1) ana çevrimi içindeki test programımız. Bu ilk bölümdeki çalışma için HAL_Delay fonksiyonlarını kapalı tutacağız.

Bu kod parçacığı ile bir for() çevrimi içinde a,b,c değişkenlerine periyodik olarak değerler atıyoruz. Bu işlemin hemen başında ve sonunda ITM Port 0, yani PB3 pini üzerinden ST Link debugger’a, zamanlarıyla etiketlenmiş iki işaretlericiyi ‘A’ ve ‘B’ harflerini gönderiyoruz. Bu iki harf arasında geçen süreyi basit bir çıkarma işlemi ile hesaplayarak for() çevrimimizin süresini öğreneceğiz.

Aralardaki iki adet HAL_Delay() fonksiyonunu bu ilk bölümdeki süre ölçüm çalışması sırasında kapalı tutacağız. Onlar daha sonraki bölümlerde, SWV den daha fazla veri almaya kalkıştığımızda oluşabilecek “overFlow” lara karşı süreci yavaşlatmak için gerekecekler.

Programızı derledik. Burada açık olarak görünse de ilk aşama çalışmalarda HAL_Delay() fonksiyonlarını kapalı tutmayı unutmayın. Yoksa ölçeceğimiz süre çok uzun çıkar, for çevriminin değil, gecikme fonksiyonlarının sürelerini ölçmüş oluruz..

Şimdi debug yapılandırmalarını yapalım. Böceğin yanındaki aşağı yönlü oka basarak debug menüsünü açalım.

Burada Debug Configurations, ardından da sol taraftaki pencereden projemizin ismine tıklayacağız, açılan penceredeki “debugger” sekmesini tıklayalım.

Burada SWD kutucuğu seçilmiş olarak gelmiş olmalı, öyle değilse tıklayarak seçelim. Pencereyi biraz yukarı kaydıralım, alt tarafı görünsün.

Burada SWV enable kutucuğunu tıklayarak işaretliyoruz. Core Clock olarak başlangıçta yapmış olduğumuz ayarlara uygun olarak 72MHz yazıyoruz. SWO Clock, bizim ST_Link probumuz için 2000 kHz.

Kalan ayarlarda değişikliğe gerek yok. Debug tuşuna basarak programımızı MCU ya yükleyelim. Her zaman olduğu gibi program çalışmaya başlayıp “HAL_INIT” adımına kadar gelir, ve orada bekler.

SWV KONSOLLARININ AÇILMASI

Programımız burada bekler durumda iken, SWV bilgilerini görüntüleyeceğimiz paneli açalım. Bunun için Window sekmesi altında Show View alt menüsünü seçelim, bu seçim yapıldığında türlü çeşitli bilgi konsollarını içeren bir liste penceresi açılıyor.

Açılan listede SWV panelleri her zaman görünmeyebilir, bu durumda “Other” seçeneği ile listenin devamını açmamız gerekir. İlk olarak “SWV ITM Data Console” panelini seçelim.

Ekranın alt bölümünde aşağıdaki gibi SWV ITM Data Konsolu açılır.

SWV ITM Data Consolu

Bu panel, programımızın içinden ITM_SendChar() fonksiyonu ile göndereceğimiz kodların görüntüleneceği bir konsol. Verilerimiz burada sadece text olarak görüntülenecekler. Her bir karakterin geliş zamanı ile birlikte listeleneceği panel ise “SWV Trace Log” adlı bir başka konsol, birazdan ona da geleceğiz.

ITM PORT 0 IN ETKİNLEŞTİRİLMESİ

Şimdi burada iken ITM_SendChar() fonksiyonunun verileri göndereceği 0 nolu ITM Portunu açalım.

Bunun için bu konsolun sağ üst tarafındaki küçük imgelerden yapılandırma anlamına geleni tornavida-anahtarlı olanını tıklayalım.

Şimdi ITM ayarlarını yapacağımız bu pencere açılmış olmalı:

Burada sadece sağ alt taraflarda olan port 0 a ait kutucuğu işaretleyelim. Görüldüğü gibi ITM 32 farklı porta veri gönderebiliyor. Bizim işimiz şimdilik o kadar karmaşık değil, Port 0 yeterli. OK diyerek bu paneli kapatabiliriz.

KAYDA BAŞLAYALIM – ÖNCE ITM DATA KONSOLUNDA TEXT

Şimdi, konsolumuzu kayıt moduna geçireceğiz. Bunun için kırmızı yuvarlak “kayıt” butonuna tıklayacağız.


Butona basınca kayıt modu başlar, butonun görünümü de soldaki gibi değişir.

Şimdi, HAL_INIT() satırında beklemekte olan kodumuzu devam komutu ile çalıştırabiliriz. main.c içindeki while çevrimine girilince ITM_SendChar() fonksiyonları ile gönderilen A ve B karakterleri ITM Data Konsolunu dolduracaktır.

Evet, ITM port 0 a verilerimizi gönderebildik, ST Link de bunları algılayıp STM32 cube IDE ye aktardı, konsolumuzda görüntüledik. Ama bu, iletişimimizin sağlanabildiğini ve programımızın çalışmakta olduğunu göstermekten öte bir fayda sağlamıyor.

SWV TRACE LOG KONSOLUNDA ZAMAN BİLGİLERİNİN LİSTELENMESİ

Bizim amacımız A ile B arasındaki zaman aralığını ölçmek idi. Bunun için SWV Trace Log konsolunu kullanacağız.

Programımızı durdurup başa alalım, yine HAL_INIT() de bekler durumda olsun. Bu konsolun seçilip açılması da aynen ITM Data Console’da olduğu gibi, tekrar anlatmayacağım. ITM Port 0 seçimini bir önceki adımda yapmıştık, o nedenle burada tekrar yapmaya gerek yok. Sadece “kayıt” tuşuna basarak kaydı başlatalım ve programımızı koşturalım.

Konsolumuzun içi aşağıdaki gibi dolacaktır. Bir saniye çalıştıktan sonra programı durdurarak görüntülenen verilere bakalım.

Görüldüğü gibi ARM Cortex M çekirdeği bizim için epey bir şey kaydediyor. Port a gelen verinin değerini, kaçıncı saat periyodunda geldiğini, kaçıncı mikro saniyede geldiğini… Her seferinde tek karakter gönderdiğimiz sürece sorun yok. “ABCDE” gibi bir karakter dizisi gönderirsek zaman bilgilerini alamıyoruz.

Burada ‘A’ yani 65 ile ‘B’ yani 66 satırlarının zaman damgaları arasındaki farkı hesaplarsak, içerideki for() çevriminin süresinin 97,917 µs (7050 saat çevrimi) olduğunu bulabiliriz. Gayet güzel değil mi? Bu işi CPU ya hiç yük getirmeden, sürecimizin doğal süresini etkilemeden yapıyoruz. Yani, hemen hemen etkilemeden – ITM_SendChar() CPU dan sadece 1 saat çevrimi, 14ns alıyor.

Not: Yukarıdaki trace kaydı ve hesaplama, test programımızdaki HAL_Delay(1) satırları kapalı iken yapılmıştır.

SWV Trace Log paneli ve ITM SWV Data Consolun her ikisi de yukarıdaki gibi bir sefer açıldıktan sonra, aynı görüntüleme oturumu esnasında sekmeler tıklanarak birinden diğerine geçilerek iki panel de görüntülenebilir.

Sırada değişkenlerin SWV/ITM uzerinden izlenmesi var ama onu yayının ikinci bölümünde anlatayım.

HIZ KISITLAMASI

Görüldüğü gibi bu mikradenetleyicilerin işlem hızı çok yüksek. Eğer, porta gönderdiğimiz veriler çok yoğun olur ve üst üste gelirse iletişim kapasitesini ve tampon bellek kapasitelerini kolaylıkla aşabiliyor. Bu durumda veri paketi kayıpları oluyor, ve yapılacak ölçümlerin güvenilirliği bozuluyor.

Neyse ki SWV/ITM sistemi bize böyle bir durum olduğunu bir “overflow” uyarısı ile haber veriyor.

Over flow uyarıları

Overflow mesajları yani veri kayıpları seyrek aralıklarla geldiğinde, ekran görünümü yukarıdaki kadar kötü olmayabilir. Ama sol alt köşedeki “Overflow packets: …” mesajı her durumda belirecektir.

Böyle bir durumda verilerin güvenilir olmayacağını dikkate alarak, veri gönderim periyodunu uzatacak ve veri boyutlarını küçültecek önlemler almak gerekir. Test programımızdaki HAL_Delay(1) bekletmelerinin amacı da bu işte. Sadece ‘A’ ve ‘B’ gönderildiğinde bu bekletmelere gerek yok ama değişkenleri de izlemeye alınca overflow lar başlıyor.

Bu yayının sonu – Selçuk Özbayraktar Ağustos 2020 – 2. Bölüm ile devam edecek

Leave a Reply

Your email address will not be published. Required fields are marked *