Hakan Kaya

ARM Uygulamaları – STM32F4 RAM Bölgesi

Bilgisayar dünyasında sayı sistemleri

Dijital elektronik ve bilgisayar biliminde bir çok sayı sistemlerini kullandığımız yerler ve zamanlar olacaktır. Bunların en önemlileri 2’li, 10’lu, 16’lıdır.

Sayı sistemlerindeki tek bir basamağa Bit, 8 tanesinin bir araya gelmesiyle Byte kavramları kullanılır.


2’li sayı sistemi (binary): 0,1 rakamlarını barındıran 1’den daha yüksek sayının olmadığı tabandır.

“Aslında her şey bir-sıfırdan oluşuyor…” lafındaki 1-0’lar…

Enerji var yada yok gibi karşıt durumların bilgisidir bir nevi.

Gömülü sistem üzerinde çalışırken sık sık görebileceğimiz”0b” ön eki ile tanımlanan sayılar binary tipinde olduğunu belirtir.

Bir den fazla sayı tabanı olduğu için hangisi binary hangisi hexadecimal olduğunu bu ve benzeri şekilde ön eklerle anlıyoruz.


10’lu sayı sistemi(decimal): 0,1,2…,7,8,9 gibi rakamların bulunduğu günlük hayatta, bakkalda, metroda, vapurda kullandığımız sayı sistemidir. En yüksek rakamsal değeri 9’dur.


16’lı sayı sistemi(hexadecimal): 0,1,2,…..,8,9,A,B,C,D,E,F rakamlarının bulunduğu tabandır. 10,11,12,13,14 ve 15 gibi sayıları tek bir rakam(sembol) ile ifade etmek için harflendirme yapılmıştır. En büyük rakam F ve değeri 15’tir.

Gömülü sistem programcılığında kullanırken bir sayının 16’lık tabanda olduğunu belirtmek için “0x” ön eki kullanacağız.

Rakamlar zaten birer simgeden başka bir şey değildir.


Windows işletim sisteminde hesap makinesini standart modundan programlayıcı moduna alırsanız dönüşümleri rahatlıkla elde edebilirsiniz. Hesap makinesini kullanamadığınız durumlarda dönüşüm yapmak yine de zor değil. Nasıl mı? Bakalım…

Örnek olarak binary tabanda 1101 sayısını ele alalım.

2’lik çözümleme yapıldığında 1.2^3 + 1.2^2 + 0.2^1 +  1.2^0 olarak açılır. Bu da 10’luk tabanda 13‘e eşittir. hexadecimal tabanda ise D‘dir.


Register nedir?

Çaylak gömülü sistem programcıları olarak bizler kodlar yazıyoruz, yani bizler veri oluşturuyoruz aslında ve bu verilerin

Burası mikro işlemcinin register’ları olsa beğenirdiyniz, ama burası hosting firmasının sunucuları…

kullanılmasına göre bir takım işlemlerin yapılmasını istiyoruz.

Yanda gördüğünüzün bir dizi çekmece olduğunu varsayalım. O kadar çok çekmecelerimiz var ki bunlara 0’dan başlayan ama binary cinsinden olan adresler verelim. Bir çekmecenin içine bazen özel bazen sıradan eşyalarımızı koyarız. Bu eşyalarımız bizim verilerimiz olsun.

Şimdi, Mikrokontrolörlerinde içinde yanda gördüğümüz gibi adres belleklerin olduğunu hayal edelim. İçlerine de bilgileri saklanıyor. Kimi bilgiler gizli, kimi bilgiler rutin işler için, kimi bilgiler başka bir bilginin anahtarı şifresi için…

O halde, oluşturduğumuz verileri (yazdığımız kodlari) 1011010..’larla ifade ederek yanda gördüğümüz gibi küçük çekmecelerde (adres belleklerinde) saklamamız gereklidir.

İşte bu çekmecelere register diyoruz. Ve bu register denilen şeylere veriler yazacağız bu yazımda.


ARM mimarisinde akış diyagramı nasıl, bu işlemler nasıl gerçekleşiyor kafamı kurcuklayan şeylerden biriydi. Öncelikle işlemci çekirdeği etrafındaki birimler neler bi’ göz atalım;

Küçük bir dip not belirteyim. Daha önce söylemiş olduğum “arm mimarisinde kesme işlemleri çekirdek ile bütünleşiktir” sözünü diyagramda açıkça görebiliyoruz sanırım. (NVIC)

Sadece microcontroller dünyasında değil bilgisayar dünyasında çalışmakta olan bir programa ait komutlar ve veriler ile daha sonra kullanılacak olan sonuç işlemleri registerlar’da (adres bellekleri) saklanır.

ARM mimarisinde ise bu işlemler Core Register‘larında daha bilindik isimle SRAM‘de (static random access memory) saklanır. Bir de bunların DRAM (dynamic random access memory ) olanları var. Dynamic belleklere göre sürekli güncellenme yapılmasına gerek yoktur. Güç beslemesi devam ettiği sürece bellekte veriler korunur. Güç kesildiğinde ise silinir. Ancak Flash Memory’lerle karıştırılmamalıdır.

SRAM yapısında 6 adet mosfet bulunur ve okuma-yazma işlemlerini oldukça hızlı yapmaktadır.

Bu gibi bilgileri uzun uzun ARM Information Center ‘dan bulabilirsiniz.

Peki bu Core Register’lar neler?

STM32F411 üzerinde 32-bit Cortex M4 çekirdeği kullanılıyor bunun üzerinden irdelemeler yapacağım.

Stack gösterimi yukarıdaki gibi olan registarlar’ın görevleri de aşağıda verilmiş. Uzun uzun aynı şeyi anlatmaya gerek yok.

Çalışma mantığı için şimdi biraz daha derine kurcuklamalar yapalım. Basit bir program yazalım bellekte saklandığı adresi takip edelim.


int sayac1 = 0;
int sayac2 = 0;

int main()
{
  while(1){
    sayac1++;
    sayac2++;
  }
}

Yeni bir proje açtınız, aygıtınızı seçtiğiniz ve kodu simulatörde başarılı şekilde debug edebildiğinizi varsayarak devam ediyorum.

Değişken izlemesi için View > Watch > Watch1 monitörünü açalım.

Değişkenlerimizin adını düzgün yazdığımızda şunun gibi verileri görebilmeniz gerekmektedir.

Core Register’ları da görüntülemek için View > Register ‘a tıklayın.

Debug’ı step step  ilerlettiğinizde R1 registerında ilk önce sayac1 değişkenin adresini, R0 registerında ise sayac1 değişkenin değerini göreceksiniz.

Bir sonraki stepte ise R1 registerda sayac2 değişkenin adresi yer alacak R0 registerinda ise sayac2 değişkenin değerini göreceksinizdir.

Ekranınızda assembly monitörü açıksa yeşil cursoru takip ettiğinizde PC (Program Counter) registerinda aslında tek tek aynı adresleri takip ettiğini de görebilirsiniz.

Peki bu ne demek? Kodlarımız Flash Memory saklanıyor ancak program verileri SRAM de saklıyor ve clock sinyalin geldiği her stepte (işlemci çalışma frekansında) PC counter adrese gidip bilgiyi okuyor, işlemi yaptırıyor. SRAM, DRAM’e oldukça hızlıdır bu konuda ancak oldukça da maliyetlidir.

View > Memory monitöründen Memory belleklerini görüntüleyebilirsiniz. Gösterimi 4x Digits yaparsanız 8 bit 8 bit gözükecektir. Her debug işleminde step into yaptığınızda 0x20000000 ve 0x20000004 adreslerindeki değer bir bir artacaktır.

Böylece SRAM adresi 0x20000000 adresinden başladığı debugtan öğrenmiş olduk. Bu bilgiye ulaşmak için bunca işleme gerek yoktu aslında datasheet’te memory map kısmında belirtilmişti. 🙂

Peki başlangıcı olan her şeyin bir gün bitişi olur düşüncesiyle SRAM de sınır bölgesine kadar gidelim neler olacak görelim.

Bunun için daha farklı bir kod yazalım. Sıra sıra tüm SRAM belleklerine veri yazalım.


int main()
{
int *pointer; // Gosterici
pointer = (int*)0x20000000; // Adres atama
*pointer = 0xAAAAAAAA; // Icine deger atama

while(1){
pointer++; // Sıradaki adres
*pointer = 0xAAAAAAAA; //Icine deger atama
}
}

Debugta step step memory monitöründen işlemleri yapıldığını görebilirsiniz. Sonuna kadar gittiğinde ise;

şeklinde bir hata ile karşılaşılacaktır.

Program Counter 0x8000092 geldiğinde yazılmak istenen adres 0x20020000 harita dışında oraya erişemiyorum gibi hata döndürecektir.

Ne var bu 0x20020000 adresinde bakalım;

Sınır bölgesi 0x2001ffff olduğu anlaşılıyor. Başlangıç ve bitiş noktasını biliyorsam toplam elimde olan SRAM miktarını da hesaplayabilirim sanırım.

Bitiş adresinden (0x2001FFFf +1 = 0x20020000) başlangıç adresini çıkarırsak (0x20000000) 0x20000 gibi değer buluruz bunu da decimal’e çevirirsek 131072 byte veri miktarımız olduğu gösterir. Bu kadar Byte kaç KB?

131072/1024 yaparsak 128KB olarak sonucu elde edebiliriz.

STM32F4 ‘ün datasheettinde yuvarlak hesap olarak 128 KB yazıyor. Niye bu kadar uğraştıysak 😀

Exit mobile version