Linux altında I2C bir aygıta erişmek

turkuazaga

Üye
Katılım
23 Aralık 2018
Mesajlar
58
Texas Instruments'in AM3354 Sitara işlemcisinde çalışan hazır bir Linux sürümü kullanıyorum. İşlemciye I2C ile bağlı olan bir güç kontrol entegresi var. Bu entegre'ye I2C üzerinden nasıl erişebilirim. Bu proje'ye yeni başladım ve tam olarak nereden başlamam gerektiğinden emin değilim. Güç kontrol entegresine erişmek için bir linux kernel aygıt sürücüsünün yazılması gerekiyor mu? Yoksa bir uygulama programı ile de aynı şey yapılabilir mi?
 
Bir i2c aygıta hem uygulama programından, hem de bir device driver ile erişebilirsin. Uygulama programından erişmek için, ilgili i2c bus'a tekabül eden /dev/i2c-X aygıtını kullanman lazım. Genel prosedür şu şekilde:

1) Mesela bus 0 ile çalışıyorsak, "open" fonksiyonu ile /dev/i2c-0 aygıtını açıyoruz.

2) "ioctl" fonksiyonu ile okuma/yazma işlemini gerçekleştiriyoruz. Okuma ve yazma işlemini doğru bir şekilde yapılandırabilmen için, i2c protokolünü çok detaylı bir şekilde anlıyor olman lazım.

3) İş bitiminde de aygıtı "close" ile kapatıyoruz.
 
Bir kernel device driver içinden de i2c aygıtlarına erişebilirsin. Peki aradaki fark nedir? ne zaman uygulamadan, ne zaman kernel'dan yapmak lazım bu işi? Burada, erişimin zamanlaması önemlidir. Eğer nadiren i2c aygıtından bir veri okuyorsak (mesela i2c bus'a bağlı bir RTC çipi var ve ondan sistem saatini okuyoruz), bunu rahatlıkla bir uygulama programından yapabiliriz. Ama i2c erişiminin belli bir sırada, belli bir zamanlama ile ve sisteme oluşan bir olaya bağlı olarak en kısa zamanda yapılması gerekiyorsa, o zaman bu işin bir kernel device driver'da yapılması lazım. Mesela diyelim bir DAC'ın reset edilmesi gerekiyor, resetten çıktıktan sonra en geç 5 milisaniye içerisinde bir registerine birşey yazılması gerekiyor. Bu zamanlama kriterini sağlayabilmenin tek yolu, bu işi kernel'da yapmaktır.
 
Bir i2c aygıta hem uygulama programından, hem de bir device driver ile erişebilirsin. Uygulama programından erişmek için, ilgili i2c bus'a tekabül eden /dev/i2c-X aygıtını kullanman lazım. Genel prosedür şu şekilde:

1) Mesela bus 0 ile çalışıyorsak, "open" fonksiyonu ile /dev/i2c-0 aygıtını açıyoruz.

2) "ioctl" fonksiyonu ile okuma/yazma işlemini gerçekleştiriyoruz. Okuma ve yazma işlemini doğru bir şekilde yapılandırabilmen için, i2c protokolünü çok detaylı bir şekilde anlıyor olman lazım.

3) İş bitiminde de aygıtı "close" ile kapatıyoruz.

Bununla ilgili örnekler araştırdım internette ama sadece erişimin dışında bir sürü ilave başka şey yapan örnek programlar görüyorum. En basit şekliyle bir i2c aygıta bir byte yazan bir örnek kod var mı elinizde?
 
Elimde örnek kod çok :) Ama aynı internette gördüğün gibi çok basit değil. Bunun nedeni, i2c protokolünün çok basit olmaması. Öncelikle protokolün detaylarını çok iyi anlaman lazım. Eğer anlamazsan, sana vereceğim minimal örneğin de sana bir faydası olmayacaktır. Öncelikle protokol ile ilgili internette temel bilgileri oku anlamaya çalış.

i2c bus üzerindeki verileri görüntüleyebilme özelliğine sahip bir osiloskop veya benzeri bir ekipman var mı elinde? Bir proje üzerinde çalışıyorum dediğine göre, çalıştığın firmada muhtemelen vardır. Eğer yoksa, bunun mutlaka tedarik edilmesi lazım. Birçok dijital osiloskop i2c protokolünü ya doğrudan destekliyor, yada bir lisans opsiyonu ile o destek satın alınabiliyor.

i2c konusunu öğrenmeye çalışırken soruların olursa da sor.
 
i2c-tools diye bir yazılım paketi var, onu derle ve sitara üzerinde çalışır hale getir. O paketin içinde belli bir i2c bus'tan veri okuma ve bus'e veri yazmaya yarayan programlar var. Onları kullanarak gereken okuma ve yazma işlemlerini dene. Böyle yaparsan, kendi yazacağın programla neleri okuman gerektiğini bilirsin ve ona göre programın doğru çalışıp çalışmadığını teyit edebilirsin.

Ama gene de i2c bus üzerinde ölçüm ve gözlem yapacak bir ekipmana ihtiyaç var.
 
i2c-tools paketinin içinde libi2c diye bir kütüphane de var. O kütüphaneyi kullanarak daha kolay bir şekilde i2c bus erişimi yapılabilir.

i2c-tools önceden lm-sensors paketinin bir parçası idi, ve PC'lerde bulunan hardware sensörlerini takip etmek için kullanılıyordu. Bu sensörlerin bağlı olduğu i2c bus, SMBus olarak adlandırılıyordu. O yüzden de bütün kütüphane fonksiyonları smbus_ prefix kullanıyor.
 
Evet libi2c ile de i2c bus erişimi yapılabilir. Eğer herşey yolunda giderse, mesele yok. Ama bir donanım veya yazılım sorunu nedeniyle i2c erişimi doğru çalışmazsa, gene osiloskop ile debug etmek gerekece. Bunun için de i2c protokolünün tüm detaylarını bilmek gerekiyor. O yüzden en iyisi, biraz zananını harcayıp i2c protokol detaylarını öğrenmek.
 
i2c-tools'u karta kurdum. Aşağıdaki şekilde bir register okutmayı deniyorum ama hata alıyorum. Problem ne olabilir?

root@am335x:~# i2cget 1 0x4a 0x02
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will read from device file /dev/i2c-1, chip address 0x4a, data address
0x02, using read byte data.
Continue? [Y/n]
Error: Read failed
root@am335x:~#
 
Last edited by a moderator:
Bus numarası, i2c adresi ve register adresinin doğru olduğundan emin ol.

Hardware'ciler bazan 7 bitlik i2c adresini sola dayalı olarak ifade ediyorlar (LSB read/write flag olduğu için), bu durumda onların verdiği adresi ikiye bölerek kullanman lazım. En garantisi, çipin datasheet'ine bak ve hangi adresin yapılandırıldığını bizzat kendin tespit et.

Register adresinin de doğru olduğundan emin ol. Eğer o adreste bir register yoksa, çip hata döndürecektir (i2c protokolünde buna NACK deniyor).

Başka bir ihtimal de, çip o anda i2c protokolünü işletecek durumda değildir. Mesela halen resette tutuluyordur.

Yani birçok ihtimal var. Emin olmanın tek yolu, i2c bus'a bir osiloskop ile bakmak.
 
i2c protokolü destekleyen osiloskop var. teledyne wavsurfer 3024z. Ama kullanmayı bilmiyorum, öğrenmek lazım.
 
Sanırım meslek hayatına yeni atıldın. Bu konuda sana naçizane bir tavsiyede bulunayım. Biraz açık ifade edeceğim, amacım seni kırmak değil.

Eğer o osiloskobu kullanmayı sana birisinin öğretmesini beklersen, daha çok beklersin! Zaten o zihniyette isen, öğretecek birisi çıksa dahi sen öğrenemezsin! Bunun dışında, eğer mesai saatleri içinde, işini gücünü bırakıp osiloskop ile uğraşıp öğrenmeye çalışırsan, gene işin olmaz. Mesai saatleri içerisinde o osiloskop birilerine lazım olacak, senin masanın üzerinde sabahtan akşama kadar durmasına izin verilmeyecek.

O yüzden, akıllı ol, bugünden başlayarak, akşamları mesai saatleri sonrasında ofiste kal ve o osiloskopu kurcala. LeCroy internet sitesinde bir sürü dokümantasyon ve tutorial'lar var, onları incele ve öğren. Hani komandolara gözleri kapalı bir şekilde G3'ü toplamayı öğretirler ya, sen de gözü kapalı bir şekilde o osiloskop ile bütün ölçümleri yapacak duruma gel.

Eğer mesai saatleri sonrası ofiste kalmak ile ilgili "fazla mesai için para vermiyorlar, ben enayi miyim?" şeklinde düşünüyorsan, o zaman bu konuda konuşacak hiçbirşey yok, yolun açık olsun derim. Kusura bakma biraz açık ve direkt oldu, ama bu çok önemli bir konu. Şimdi doğru olanı yaparsan, doğru bir şekilde devam edersin. Şimdi hatalı davranırsan, hep öyle gidersin.
 
Son düzenleme:
Konuyu açık ve net ifade ettiğiniz için teşekkürler. Osiloskobu öğrenmek için gereken neyse yapmaya hazırım, o konuda hiçbir çekincem de yok. Ama elektronik mühendisliği okuduğum üniversitedeki kısıtlı imkanlardan dolayı böyle cihazlarla hiç karşı karşıya gelmedim. Teorik bilgiler ve ezberle okulu bitirdik, gerçek mesleği iş hayatında öğrenmek durumundayız.
 
Keşke üniversitende bu imkanlar olsaydı, ama en azından bir üniversiteye gidebilmişsin, o imkana sahip olmayanlar da var.

Aslında kendini şanslı hissetmelisin. O osiloskop, protokol opsiyonları ile beraber 8000 dolarlık bir cihaz, ve mesai saatlerinden sonra sen o cihazı istediğin gibi, saatlerce kurcalayabileceksin. Hatta bozsan bile kimse sana "sen bozdun bunu, öde parasını" demeyecek. Asıl böyle bir imkanı geri tepmek ENAYİLİK olur :D
 
Haklısınız benim de mesai dışı bu osiloskopla çalışma konusunda en ufak bir çekincem yok.Arduino kartı ile çok yazılım geliştirdim projeler yaptım ama bu I2C konusunda tamamen yeniyim.

Osiloskop ile i2c hatlarına bakmaya başladık.i2cget komutnu çalıştırıyorum, ama I2C SCL/SDA hatlarında hiç aktivite yok. Buradaki bir tecrübeli arkadaş ile beraber baktık çok kısa süreli bir hareket bile yok. Hangi "bus number" "device address" veya "register" kullansam kullanayım hiç farketmiyor. Acaba linux kernel ile ilgili birşeyler mi yapmam gerekiyor I2C nin kullanılabilmesi için?
 
Eğer sistemde /dev/i2c-1 dosyası varsa (senin cihazının 1 numaralı bus üzerinde olduğunu varsayıyorum), o zaman senin kernel'de I2C bus'ı okuma özelliği vardır. Benim üzerinde çalıştığım sistemden bir örnek vereyim:

Kod:
root@dc1-F8DC7A0F37C8:~# ls /dev/i2c* -al
crw-------    1 root     root       89,   0 Jan  1  1970 /dev/i2c-0
crw-------    1 root     root       89,   1 Jan  1  1970 /dev/i2c-1
root@dc1-F8DC7A0F37C8:~#


Burada iki tane i2c bus görüyoruz. Bus 0'd STA311B diye bir FFX audio processing DSP'si var. Bus 1'de de bir RTC var

Örnek olarak DSP'den tek byte okuma yapalım. DSP, bus 0 üzerinde, çip adresi de 0x20. Register adresi 0 içeriğini okuyalım:

Kod:
root@dc1-F8DC7A0F37C8:~# i2cget -y 0 0x20 0
0x81
root@dc1-F8DC7A0F37C8:~#


register 0x60'den itibaren 16 byte okuyalım:

Kod:
root@dc1-F8DC7A0F37C8:~# i2cdump -y -r 0x60-0x6f 0 0x20
No size specified (using byte-data access)
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
60: 20 20 60 60 60 33 33 33 1b 1b 1b 30 30 2f 2f 20      ```333???00//
root@dc1-F8DC7A0F37C8:~#


Öncelikle /dev/i2c-0 veya /dev/i2c-1 veya hangisi var onu bir kontrol et ve sonucu yaz. Eğer entegrenin hangi bus'ta olduğunu bilmiyorsan, bütün bus'ların listesine bakalım hepsini tek tek deneriz.
 
Baktım 3 tane /dev/i2c-* var. Bus 0, bus 1, bus 2. Power entegresi bus 1'de onu kesin biliyorum, çünkü Sitara'nın belli harici pinlerine çıkıyor. Kernel kodu üzerinde çalışan arkadaş da bugün Bus 1 olduğunu söyledi.
 
Tamam o zaman, kernel'da i2c desteği var. Yalnız harici pad'lerin bazılarında I2C_1 yazsa bile o padler I2C_1 olmayabilir :) bu ARM mimarisi çok pis birşey, her pad birçok farklı rol üstlenebiliyor. Ama madem sizin kernel elemanı da öyle dedi, doğru bus'a baktığınızı varsayalım.

O bus üzerinde başka çip var mı, yoksa tek çip bu sizin "power" çipi mi? osiloskop ile bakınca, SDA ve SCL yi hareketsiz diyordun. Bunlar seviye olarak high mı low mu?
 
Bus 1 de iki çip daha var.Bir tane I2C EEPROM var,bir tane FPGA var power entegresinden başka.Ama sadece power entegresine (PMIC) odaklanabilmek için onları söktürdüm bugün.Şu anda sadece PMIC var ve SCL ve SDA ikisi de sürekli low.

EDIT: PMIC reset pini de Sitara'ya gidiyordu, onu oradan söküp tüm kartı resetleyen hardwre reset çipine bağlattım.Osiloskop ile baktık,PMIC düzgün reset alıyor.
 

Forum istatistikleri

Konular
5,790
Mesajlar
99,028
Üyeler
2,464
Son üye
s4met

Son kaynaklar

Son profil mesajları

cemalettin keçeci wrote on HaydarBaris's profile.
barış kardeşim bende bu sene akıllı denizaltı projesine girdim ve sensörleri arastırıyorum tam olarak hangi sensör ve markaları kullandınız yardımcı olabilir misin?
m.white wrote on Altair's profile.
İyi akşamlar.Arabanız ne marka ve sorunu nedir.Ben araba tamircisi değilim ama tamirden anlarım.
* En mühim ve feyizli vazifelerimiz millî eğitim işleridir. Millî eğitim işlerinde mutlaka muzaffer olmak lâzımdır. Bir milletin hakikî kurtuluşu ancak bu suretle olur. (1922)
Kesici/Spindle hızı hesaplamak için SpreadSheet UDF'leri kullanın, hesap makinesi çok eski kalan bir yöntem :)
Dr. Bülent Başaran,
Elektrik ve Elektronik Mühendisi
Yonga Tasarım Özdevinimcisi
Üç güzel "çocuk" babası
Ortahisar/Ürgüp/Konya/Ankara/Pittsburgh/San Francisco/Atlanta/Alaçatı/Taşucu...

Back
Top