CubeIde ile Debug'dan değişken görmek için veri tipi tanımı nasıl olmalı ?

Başlatan samedkutuk, 21 Kasım 2020, 23:38:22

samedkutuk

Arkadaşlar Merhabalar,
Öncelikle umarım herkesin sağlığı yerindedir  :)
1-) Cubeide ile STM32 programlama çalışıyorum. Basit bir Timer7 kesmesi oluşturarak counter arttırıp artan değeri debug menusunde görmek istiyorum fakat zannımca değişken timer fonksiyonundan çıkmıyor.
Timer kesmesi içerisinde yazdığım kod aşağıdaki gibidir. Ayarladığım zamana uygun olarak Pin_15 ledi Toggle oluyor onu gözlemleyebiliyorum fakat değişkenin değerini debug da göremiyorum sebebi ne olabilir ?
2-)Main sayfamda yazdığım bir fonksiyonda bu değişkeni kullanmak istediğimde de bu değiken tanımlanmadı olarak hata veriyor. Sanırım burada da sorunum uygun değişken tipini uygun yerde tanımlamıyorum.
Bu konuda fikri olan var mıdır ?

İyi çalışmalar dilerim.
void TIM7_IRQHandler(void)
{
  /* USER CODE BEGIN TIM7_IRQn 0 */
 static uint8_t counter=0;
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_15);
if(counter >2){
	HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_14);
	counter=0;
}
counter++;
  /* USER CODE END TIM7_IRQn 0 */
  HAL_TIM_IRQHandler(&htim7);
  /* USER CODE BEGIN TIM7_IRQn 1 */

  /* USER CODE END TIM7_IRQn 1 */
}
samedkutuk

Tagli

Bu konu genelde benim de kafamı karıştırıyor ve başıma bela oluyor. Anladığım kadarıyla durum şöyle: Bir değişkenin debugger'da görülebilmesi için, kod duraklatıldığında "var olması" gerekiyor. Global değişkenler işleyiş boyunca hep varlar, bunlarda bir sıkıntı yok. Local static değişkenlerde durum nasıldı hatırlamıyorum. Aslında bunlar da teknik olarak hep "varlar", ancak belki scope dışında debugger'a görünmez olabilirler, emin değilim. Fonksiyon içindeki normal değişkenler ise ancak kod o fonksiyon içinde iken debugger'a görünür oluyorlar.

Senin alttaki counter kullanımı zaten yanlış. Local static bir değişken, tanımlandığı scope dışında var olamaz, daha doğrusu erişilemez. Yani static olduğu için fonksiyona ilk girişte vücut bulur ve ondan sonra sürekli vardır, ama fonksiyon dışından görünmez.

Ya debug yapabilmek için geçici olarak değişkenini fonksiyondan çıkarıp global olarak tanımlayacaksın, ya da fonksiyon içinde breakpoint koyup kodu orada durdurup local değişkenleri inceleyeceksin. Başka bir yolu varsa da ben bilmiyorum. Ama bence static olmayan bir local değişken için zaten hiç umut yok, çünkü stack üzerinde var oldukları için yeri yurdu belli değil, fonksiyon terk edildiği anda da zaten yok olur. Böyle bir şeye debugger'ın erişmesine imkan yok. Local static için belki benim bilmediğim bir yöntem vardır.

C++'ta kod yazarken ise debugger'a değişkenleri class veya namespace scope ile göstermen gerekiyordu yanlış hatırlamıyorsam. Benim de sürekli karıştırdığım ve her seferinde deneme yanılma ile çözdüğüm bir durum.
Gökçe Tağlıoğlu

samedkutuk

@Tagli  Hocam yanıtınız için teşekkür ederim.
Burada global değişken kullanımı ile ilgili sytax ın nasıl olduğuna dair kısa bir örnek vermeniz mümkün müdür ?
samedkutuk

Tagli

static uint8_t counter=0; satırını fonksiyonun dışına alman yeterli. Aslında bu durumda static ifadesine de gerek yok, ama duruma göre static olması daha iyi olabilir. Eğer static olursa, değişken internal linkage'a sahip olur, yani sadece o dosya içinde kullanılabilir. Bu durumda diğer .c dosyalarındaki aynı isimli global değişkenler ile çakışmaz.

static ifadesi genel olarak biraz kafa karıştırıcı. Kullanıldığı yere göre anlamı değişiyor. Fonksiyon içinde kullanılmışsa o değişkenin stack'te değil kalıcı olarak RAM'de saklandığı anlamına geliyor ve bu durumda fonksiyondan çıkılsa bile değişken silinmiyor, fonksiyona tekrar girildiğinde eski değerine sahip oluyor. Fonksiyon dışındaki bir global değişkenin başına static yazılırsa, yukarıda anlattığım gibi internal linkage anlamına geliyor. Aklımda yanlış kalmadıysa const global değişkenler (garip oldu bu, yani "değişmeyenler" diyelim) varsayılan olarak zaten internal linkage'a sahip.
Gökçe Tağlıoğlu

z

Bu konu sadece Keil'de degil Delphi'de de problem.

Global degiskenler cok guzel monitor edilirken lokal degiskenleri monitor edemiyorum.

Bu genel bir kural degilse cozumu bana da lazim.  Global degiskenleri izlemek kadar basit olmali.

Aslinda teknik olarak hic bir zorlugu yok. Nedense debugger yazanlarin islerine gelmemis gibi gorunuyor.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

Tagli

Alıntı yapılan: z - 22 Kasım 2020, 02:31:06Aslinda teknik olarak hic bir zorlugu yok.
Hocam static local değişkenler konusunda haklısın. Ancak eğer bir local değişken static değilse, bence izlenmesi teknik olarak mümkün değil. Anladığım kadarıyla debugger aslında mutlak adresleri sorguluyor.
Gökçe Tağlıoğlu

z

Teorik olarak neden mumkun olmasin?

Degisken isimleri ve siralamasi belli. Sadece ramdaki  (stak) ofseti belli degil.

Breakpoint yendigi anda stack adresi belli. Yani o statik degiskenler nerede belli artik.

Birazcik hafiyelik gerekiyor.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

samedkutuk

Hocam yanıtınız için teşekkür ederim,
Evet fonksiyonun dışına çıkarıp static i kaldırınca debug menüsünde görebildim Fakat main dosyasında halen değişkeni kullanamıyorum tanımlı değil diyor.
Yapmaya çalıştığım şua aslında;
stm32f4xx_it.c
dosyasında
Alıntı Yapvoid TIM7_IRQHandler(void){}
kesmesinin içinde bir değişkeni arttırıp bu değişkeni main.c dosyamda kullanmak istiyorum

Alıntı yapılan: Tagli - 22 Kasım 2020, 01:03:52static uint8_t counter=0; satırını fonksiyonun dışına alman yeterli. Aslında bu durumda static ifadesine de gerek yok, ama duruma göre static olması daha iyi olabilir. Eğer static olursa, değişken internal linkage'a sahip olur, yani sadece o dosya içinde kullanılabilir. Bu durumda diğer .c dosyalarındaki aynı isimli global değişkenler ile çakışmaz.

static ifadesi genel olarak biraz kafa karıştırıcı. Kullanıldığı yere göre anlamı değişiyor. Fonksiyon içinde kullanılmışsa o değişkenin stack'te değil kalıcı olarak RAM'de saklandığı anlamına geliyor ve bu durumda fonksiyondan çıkılsa bile değişken silinmiyor, fonksiyona tekrar girildiğinde eski değerine sahip oluyor. Fonksiyon dışındaki bir global değişkenin başına static yazılırsa, yukarıda anlattığım gibi internal linkage anlamına geliyor. Aklımda yanlış kalmadıysa const global değişkenler (garip oldu bu, yani "değişmeyenler" diyelim) varsayılan olarak zaten internal linkage'a sahip.
samedkutuk

muhittin_kaplan

Bir değişkenin yaşam alanının dışında  debug da "görülebildiğini" hiçbir dilde ve IDE de görmedim.

samedkutuk

cevap veren tüm hocalarıma teşekkür ederim,
Ben önce debugda local değişkeni göremediğimi @Tagli hocamdan öğrendim ve değişkenimi fonksiyon dışına çıkararak ilk sorunumuçözmüş oldum.

ikinci sorunum ise kesme fonksiyonunun olduğu .c dosyasında bir değişken arttırarak o değişkeni main.c dosyasında kullanmak idi ve onu da extern tanımlama biçimi ile main.h dosyasına tanımlayıp daha sonda main.c dosyasında uint8_t olarak çekerek kullanabildim.
İlgili fotoğrafları aşağıda birilerinin işine yaraması dileği ile paylaşıyorum.

Bunlara ek olarak ynalışım var ise uyarmanızı eksiğim var ise önerilerinizi rica ederim :)
 
Herkese iyi çalışmalar dilerim :)











samedkutuk

Tagli

Alıntı yapılan: z - 22 Kasım 2020, 10:47:52Teorik olarak neden mumkun olmasin?
@z hocam, fonksiyon içindeki static değişkenlerin yerleri zaten derleme anında bile bellidir. Bunlar stack üzerine yerleştirilmezler. Ama ilk değerlerini almaları fonksiyonun ilk çağrıldığı ana denk gelir. Mesela bu static local değişken bir C++ nesnesi ise, fonksiyon ilk çağrıldığında constructor'ı çağrılır. Bunlara debugger üzerinden ulaşmanın mantıken bir yolu olması lazım, ama ben bilmiyorum.

Static olmayan local değişkenlere ulaşmanın ise bir yolu olamaz. Eğer breakpoint fonksiyon içinde ise bunlara ulaşılabilir. Bunu zaten yapabiliyoruz, muhtemelen senin bahsettiğine benzer bir yöntemle. Sonuçta debugger o sırada stack pointer'ı biliyor, değişkeni de bulabilir. Ama işleyiş fonksiyon dışına çıktığı anda o değişken artık yok. Çünkü stack geri sarılmış, muhtemelen üzerine başka bir fonksiyonun stack'i binmiş, o adreste de başka bir şeyler var artık.

Yine de bir dipnot olarak yazayım: Bazı kısıtlı cihazlarda derleyici fonksiyonların reentrant olmadığını varsayarak local değişkenlerin hepsini static olarak bellekte bir yere yerleştirebilir. Böyle derleyicilerde fonksiyonlar stack kullanmazlar. Tabi ki bu durumda aynı fonksiyonu mesela hem kesmede hem de normal kodda çağıramazsınız (ama bunun da çaresi var). Benzer şekilde recursion da yapamazsınız. Microchip'in bir dokümanında bununla ilgili bir şeyler okuduğumu hatırlıyorum. Belki XC8 böyle idi, emin değilim. Ayrıca bu özelliği açıp kapama için bir derleyici opsiyonu da olmalı. Ama XC8 bir kolaylık da sağlıyor: Aynı fonksiyon hem normal kodda hem de kesmede çağrılırsa, o fonksiyonun bir kopyası oluşturuluyor otomatik olarak. C++'taki template'ler gibi bir mantığı var yani. Neyse, lafı çok uzattım. Böyle bir derleyicide local değişkenler gerçekte static olurlar ve bunlara erişmek teorik olarak mümkündür. MPLAB X'te debug yaparken bunu yapabiliyor muyduk hatırlamıyorum.

@samedkutuk , extern ifadesi derleyiciye "Böyle bir değişken var ama burada değil dışarıda bir yerde tanımlı, linker söyleyecek sana bunu" demektir. Yani extern geçen yerde değişken için bir yer ayrılmaz. Linker bunu link aşamasında artık hangi dosyada tanımlanıp derlenmişse oradan bulup bağlar. Tabi bunun için bu değişkenin external linkage'a sahip olması gerekir. Değişkeni static ifadesi ile tanımlarsan internal linkage olur, yani linker'a görünmez olur gibi düşünebilirsin. Senin durumunda böyle olmasını istemiyorsun, çünkü o değişkene başka dosyadan erişmen gerekiyor. Ama özel bir sebep yoksa external linkage genel olarak tercih edilmeli. Yoksa farklı dosyalardaki global değişkenler eğer isimleri aynı ise birbirleri ile çakışırlar ve linker hatası alırsın. C++ kullanırken her değişkenin başına static yazmak yerine bunları topluca isimsiz bir namespace içine de atabilirsin.
Gökçe Tağlıoğlu

samedkutuk

@Tagli  hOCAM BEN 8 BİT pic ler ile çaqlışıyordum henüz stm ile yeni başladım çalışmaya external linkage kullanımını kısaca göstermeniz mümkün müdür ?

Alıntı yapılan: Tagli - 22 Kasım 2020, 16:05:40@z hocam, fonksiyon içindeki static değişkenlerin yerleri zaten derleme anında bile bellidir. Bunlar stack üzerine yerleştirilmezler. Ama ilk değerlerini almaları fonksiyonun ilk çağrıldığı ana denk gelir. Mesela bu static local değişken bir C++ nesnesi ise, fonksiyon ilk çağrıldığında constructor'ı çağrılır. Bunlara debugger üzerinden ulaşmanın mantıken bir yolu olması lazım, ama ben bilmiyorum.

Static olmayan local değişkenlere ulaşmanın ise bir yolu olamaz. Eğer breakpoint fonksiyon içinde ise bunlara ulaşılabilir. Bunu zaten yapabiliyoruz, muhtemelen senin bahsettiğine benzer bir yöntemle. Sonuçta debugger o sırada stack pointer'ı biliyor, değişkeni de bulabilir. Ama işleyiş fonksiyon dışına çıktığı anda o değişken artık yok. Çünkü stack geri sarılmış, muhtemelen üzerine başka bir fonksiyonun stack'i binmiş, o adreste de başka bir şeyler var artık.

Yine de bir dipnot olarak yazayım: Bazı kısıtlı cihazlarda derleyici fonksiyonların reentrant olmadığını varsayarak local değişkenlerin hepsini static olarak bellekte bir yere yerleştirebilir. Böyle derleyicilerde fonksiyonlar stack kullanmazlar. Tabi ki bu durumda aynı fonksiyonu mesela hem kesmede hem de normal kodda çağıramazsınız (ama bunun da çaresi var). Benzer şekilde recursion da yapamazsınız. Microchip'in bir dokümanında bununla ilgili bir şeyler okuduğumu hatırlıyorum. Belki XC8 böyle idi, emin değilim. Ayrıca bu özelliği açıp kapama için bir derleyici opsiyonu da olmalı. Ama XC8 bir kolaylık da sağlıyor: Aynı fonksiyon hem normal kodda hem de kesmede çağrılırsa, o fonksiyonun bir kopyası oluşturuluyor otomatik olarak. C++'taki template'ler gibi bir mantığı var yani. Neyse, lafı çok uzattım. Böyle bir derleyicide local değişkenler gerçekte static olurlar ve bunlara erişmek teorik olarak mümkündür. MPLAB X'te debug yaparken bunu yapabiliyor muyduk hatırlamıyorum.

@samedkutuk , extern ifadesi derleyiciye "Böyle bir değişken var ama burada değil dışarıda bir yerde tanımlı, linker söyleyecek sana bunu" demektir. Yani extern geçen yerde değişken için bir yer ayrılmaz. Linker bunu link aşamasında artık hangi dosyada tanımlanıp derlenmişse oradan bulup bağlar. Tabi bunun için bu değişkenin external linkage'a sahip olması gerekir. Değişkeni static ifadesi ile tanımlarsan internal linkage olur, yani linker'a görünmez olur gibi düşünebilirsin. Senin durumunda böyle olmasını istemiyorsun, çünkü o değişkene başka dosyadan erişmen gerekiyor. Ama özel bir sebep yoksa external linkage genel olarak tercih edilmeli. Yoksa farklı dosyalardaki global değişkenler eğer isimleri aynı ise birbirleri ile çakışırlar ve linker hatası alırsın. C++ kullanırken her değişkenin başına static yazmak yerine bunları topluca isimsiz bir namespace içine de atabilirsin.
samedkutuk

Tagli

@samedkutuk sen olayı çözmüşsün zaten. Senin static demeden tanımladığın uint8_t genel_sayici external linkage'a sahip. Böyle bir değişkene başka bir .c dosyasından erişebilirsin. Ancak erişeceğin dosyada extern uint8_t genel_sayici şeklinde belirtmen lazım. Yukarıda da belirttiğim gibi bu ifade derleyiciye, o değişkenin başka bir yerde tanımlı olduğunu anlatır. Sen bunu doğru bir şekilde uygulamışsın.
Gökçe Tağlıoğlu

samedkutuk

Anladım hocam,
Anladığım kadarıyla .h Dosyasında Extern diye tanımladığım değişkenlerine .h dosyasını içeren tüm .c dosyalarından erişebiliyorum.
Tabi .c dosyalarında veri tipi ile tanımlamak zorundayız

Alıntı yapılan: Tagli - 22 Kasım 2020, 16:19:22@samedkutuk sen olayı çözmüşsün zaten. Senin static demeden tanımladığın uint8_t genel_sayici external linkage'a sahip. Böyle bir değişkene başka bir .c dosyasından erişebilirsin. Ancak erişeceğin dosyada extern uint8_t genel_sayici şeklinde belirtmen lazım. Yukarıda da belirttiğim gibi bu ifade derleyiciye, o değişkenin başka bir yerde tanımlı olduğunu anlatır. Sen bunu doğru bir şekilde uygulamışsın.
samedkutuk

Tagli

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