PIC İle MMC – SD Kart Kullanımı

| Temmuz 5, 2019 Tarihinde güncellendi
PIC İle MMC – SD Kart Kullanımı

MMC Haberleşme protokolü Bu bölümde, SD (Secure digital) kart haberleşmesi üzerinde duracağım.

SD kart, MMC kartın gelişmiş biçimidir. SD kart, SPI haberleşme protokolüne desteklediği gibi, daha hızlı olan SD bus haberleşme protokolüne de sahiptir. Bu yazıda SD kart ile SPI haberleşme protokolüyle haberleşme yöntemini anlatılacaktır. PIC’ te donanımsal SPI vardır ve her iki kart tipi (MMC ve SD) ile SPI üzerinden haberleşebilir. MMC kartlar piyasada SD karta göre çok yaygın olmadığı için, bu yazıda SD kartın SPI haberleşmesinden bahsedilecek.

mmc-sd-kartlar

SD kart iki haberleşme protokolü ile de haberleşebilir. İlki, SD Bus haberleşme protokolüdür. Bu protokolde her bir clock pulse’ ında 4 bit bilgi gönderilir. Bir byte iki pulse’ ta gönderilir. İkinci haberleşme protokolü ise SPI haberleşmesidir. SPI’ protokolünde, her clock pulse’ ında bir bit gönderilir/alınır. Bu yüzden SD bus haberleşme sistemi SPI’ a göre daha hızlıdır. SD kart ilk açılışta, elektrik verildiğinde otomatik olarak SD bus haberleşme protokolüne ayarlanmıştır ve doğrudan SD haberleşmesi yapılabilir. Ancak biz SPI haberleşmesi yapacağımız için, elektrik verildikten sonra SD haberleşme protokolünü SPI protokolüne geçirmek gerekmektedir. SPI protokolüne ayarlandıktan sonra tekrar SD bus protokolüne geçmek mümkün değildir, ancak elektriğini kesip tekrar elektrik verildiğinde SD bus modda haberleşebilinir.

SD kartın bacak bağlantıları aşağıdaki tabloda verilmiştir. Bacakların SD mod ve SPI moda göre anlamları belirtilmiştir. Kullanılmayan DAT1, DAT2 bacakları ve ayrıca DO bacağı bir dirençle Pull-Up’ a çekilmelidir.

sd-kart-tablo

SD kartın besleme voltajı 2,0 ile 3,6 volt arasındadır. Dolayısıyla, eğer PIC’ i 5 volt ile besliyorsanız, SD kart ile PIC’ i doğrudan haberleştiremeziniz. Bunun için araya logic level converter koymalısınız. Buna alternatif olarak, kendi PIC’ inizi de 3,3 volt ile beslerseniz, bu besleme voltajını hem PIC hem de SD kart için kullanabilirsiniz ve ara bir dönüştürücü koymanıza gerek kalmaz. Artık yeni çıkan PIC’ lerin çoğunda besleme voltajları 5 voltun altında olduğu için, bu projede besleme voltajı 3.3volt kabul edilmiştir. Tasarlanacak sistem de buna göre tasarlanacaktır. PIC seçiminde dikkat etmeniz gereken tek nokta, alacağınız uP’ ın donanımsal SPI’ a sahip olmasıdır. Ben bu proje için 40 pinli 18 serisi PIC kullandım. Bağlantılar gayet basit, aşağıda bacak bağlantıların tablosu var.

sd-kart-tablo22

sd-kart-tablo222

Tabloya dikkat ederseniz PIC ile SD kart arasındaki SDO ve SDI bacaklarının çapraz bağlandığını göreceksiniz. SD kartın SDO çıkışı open collector olduğu için çıkış’a pull-up koymayı unutmayın. SD kart daima slave konumundadır. PIC den istek geldikçe cevap verir.

PIC in SPI portonun ayarlanması

PIC’ i SD kartla donanımsal haberleşmeye hazır hale getirebilmek için SPI ayarlarının uygun bir şekilde ayarlanması gerekir.

SPI ayarları:

Master mod.
SCK set low in IDLE state.
SDI input centered.
Clock Low to Hight.
Haberleşme hızı 250kHz göre ayarla. (1:64)

SD kartlarda SPI haberleşmesi özel bir protokol ile yapılır. Bu protokol birçok komut içerir. Aşağıdaki tabloda bu komutlar verilmiştir. Görüldüğü gibi, komut sayısı çok fazladır. Ancak biz burada bütün komutları ele almayacağız. Örneğin CMD0, CMD1, CMD9, CMD10, CMD16, CMD17, CMD24, CMD41, CMD51 gibi genel komutlarını ele alacağız.

spi-bus

SPI haberleşmesinde SD kartın ayrıca CS (Card Select) bacağını kullanılır. SD kartın CS bacağı sıfıra çekildiğinde SPI haberleşmesi başlamış olur. Ama önce CS lojik 1 konumunda iken en az 74 tane clock sinyali gönderilmelidir, biz 80 tane göndereceğiz. CS bacağı sıfıra çekildikten sonra CMD0 (ilk RESET komutu) gönderilir ve cevap olarak 01h bilgisi gelirse, reset işlemi başarılı olmuş demektir. Aşağıda reset komutunun sinyal şeması görülmektedir.

reset-mmcsd

Komutlar 6 byte (48bit) uzunluktadır, ancak gelen cevapların uzunluğu komuta göre değişir. CMDx yapısında ilk bit sıfırla başlar, sonra Master (Host) tarafının ikinci biti 1 dir. SD kartın cevabında ise bu bit daima sıfırdır. Akabinde 6 bit command bilgisi bulunur. Bu kısım, CMD0 için sıfır veya CMD9 için dokuz olur. Komut uzunluğu 6 bit olduğu için en azla 64 tane komut tanımlanabilir. Komut mesajının frame’ i aşağıdaki gibidir:

commant-48bits

Frame’ in sonunda 7 bit CRC kontrol bilgisi de vardır. SPI haberleşmesinde, sadece CMD0 komutunun CRC bilgisini kullanılır. Diğer komutlarda CRC kontrolü devre dışı bırakılmıştır. Yani CRC datası gönderilir ama SD kart bu datayı dikkate almaz. Bu yüzden sadece CMD0’ın CRC bilgisini tek bir seferde, sabit olarak girebiliriz. Sonrasında bu CRC bilgisi değiştirilmeden FFh olarak kullanılabilir. CMD0 bir argüman almadığı için argument kısmı sıfırdır. CMD0 SD karta “Software Reset” atmak için kullanılır, CMD0’dan sonra kart IDLE (boşta bekleme) modunda olur.

Bu durumda CMD0 için 6 bayt veriler 40h,00h,00h,00h,00h,95h şeklinde olmadı. CMD0 CRC değeri 95h olduğu için bu değer yazıldı. Argüman uzunluğu 32 bit olduğu için 4 bayt ile temsil ediliyor.

CMD0 cevap olarak en fazla 9 okuma içerisinde 01h değeriyle cevap vermelidir. Gelen cevaptan sonra da CS bacağını bire çekerek okuma kapatılır. Okuma bittikten sonra ikinci bir komut göndermeden önce bekleme yapılır. Bunun için de bir okuma yaptığımızda bu bekleme yapılmış olur. Bu işlemden sonra CMD0 tamamlanmış olur. CMD0 komutundan sonra SD kart bekleme konumuna geçer. Kartı tekrar devreye almak için CMD1 komutunun verilmesi gerekmektedir. Ancak CMD1 veya CMD41 sonra karttan okuma ve yazma yapılabilir.

CMD0’ın C kodu ile nasıl kodlanacağına gelince; aşağıdaki gibi bir örnekle olabilir. Tabii ki böyle yapılacak diye bir kural yok, farklı şekillerde de yapılabilir. Ancak benim incelediğim değişik kaynaklı kodlarda, kodların hepsi birbirlerine birebir benzememektedir. Temelde, komutları icra eden bir fonksiyon vardır. Parametre olarak kimi sadece command ve argüman alır ve geri dönüş değeri iletmez, kimisinde geri dönüş değeri vardır, kimisinde parametre olarak CRC değeri de geçer. İncelediğim farklı algoritmaları birleştirerek şöyle bir kod yazdım;

mmcsd-kod

CMDo dan sonra CMD1 uygulanır. CMD1 komut yapısı şekildeki gibi 41h,00h,00h,00h,00h,FFh dir. Cevap olarak 00h gönderilmelidir. Bu işlemden sonra kart okuyup yazmaya hazırdır. Aşağıdaki şekilde CMD1 gönderilmesi gösterilmektedir.

init-cmd1

CMD0 veya CMD1 den cevap olarak neden 01h ve 00h geldiğine bakalım. Bunun için bütün komutların olduğu tabloya bakmak gerek. Response olarak R1 denmiş, peki nedir bu R1? Aşağıdaki şekilde R1, 1 byte ile ifade edilmiştir.

r1-response-format

Şekile baktıktan sonra CMD0’ ın neden 01h değeriyle cevap verdiğini anlamışsınızdır. CMD0 ile kart idle komununa alınıyor. Kart da cevap olarak idle konumunda olduğu bilgisini veriyor. CMD1 ile kartı aktif hale geciriyoruz. Bu sırada bize hiçbir hata dönmemesi gerek. Yani 00h ile cevap vermeli. Aksi takdirde, sıfır dışında verilen bir cevap bize bir hata olduğunu bildirir. Hatanın ne olduğunu, yukardaki tabloyu incelenerek bulunabilir. Bunun haricinde CMD13 (send status) R2 modu ile cevap verir. R2 iki bytetır. R2 cevap kısmının içersindeki bitlerin anlamları şöyledir;

r2-response-format

Karta bilgi yazmadan önce, kartta özel bilgilerin olduğu registerların içinin okunmasında fayda var. Zira kartın kapasitesi, sektör sayısı, çalışma voltajı v.b. bilgilerin hepsi bu registerlarda saklanır. Dolayısıyla, kullanılan SD karttan farklı bir karta, yanlış birşeyler yazmamak için önce bu kontrolleri yapmakta fayda vardır. Bu registerlarda tutulan bilgiler ise aşağıdaki gibidir;

– CID (Card Identification) registerı: 128-bit uzunluğundadır ve CMD10 ile elde edilir. CID bilgileri şunlardır; Manufacturer ID (24bit), Product name (56bit), HW Revision (hardware), FW Revision (Firmware), Serial Number (Unique ID no), Month code (Manufactore date- Month), Year Code (manufacture date – Year. 1997 yılından itibaren (SanDisk) ).

cid-fields

– CSD (Card Specific Data) registeri 128 bit uzunluğundadır ve CMD9 ile elde edilir. Ancak bu registerın içerdiği bilgiler çok uzun olduğu için açıklama yapmadan, direk tablosunu veriyorum;

csd-fields

CSD ve CID komutlarını okuma şekli aşağıdaki gibi olur. CMD gönderildikten sonra 00h ile komutu aldığını teyid eder. Sonrasında kartan cevap gelmesi ise belli bir zaman sonra olur. Burada 8 okumadan sonra yazmış ama bu süre değişebilir. Programda, belli bir süre sürekli okuma yapılır, ta ki FEh bilgisi okunana kadar. FEh, bilgi göndermenin başladığı bilgisidir. Bundan sonraki okumalarda ise bilgileri elde edilir. Bilgilerin sonunda 2 byte CRC bilgisi de gelir. Onu da okumak gerekir. Bu işlemden sonra kart okuması gercekleşmiştir.

cid-read-blok

csd-read-blok

Bu işlemden sonra bir de SD kartın içine bilgi yazma kısmı var. SD karttaki bilgilere erişmek herhangi bir EEProm veya RAM’ de olduğu gibi değildir. Yani doğrudan bir byte alana ulaşılmaz veya sadece 1 byte veri yazilmaz. SD kart içerisindeki alanlar, Sector veya Bloklara bölünmüştür. Her bir sector de 512 byte bilgi içerir. Tek bir sektöre bilgi yazabilmek için CMD24 kullanılır. Bilgi yazma modunun şu şekilde bir yapısı vardır;

CMD0, CMD1, CMD9 ve CMd10 gönderirken arguman kullanmiyor, hep sıfır yazıyorduk. Şimdi ise CMD24 teki arguman parametremiz hangi sektöre bilgi yazmak istediğimizi belirtecek. Bu noktada herhangi bir 4bytelık sector adresi seçilebilir. Bu komuttan sonra kart, 00h bilgisini iletmelidir. Arkasından yazılacak komutlar gönderilebilir ancak göndermeye başlamadan önce belli bir süre beklemek gerekir. Aşağıdaki şekilde 8 okuma süresi kadar bekleme süresi konmuş ama garanti olması için bu okuma süresini uzun tutmakta fayda var.

Kartın bilgi almaya başlaması, FEh bilgisi gönderildikten sonra başlar. FEh’ den sonra gelen bilgiler yazılacak data olarak alınır. 512 byte bilgi gönderildikten sonra 2 byte CRC bilgisi de iletilir. SPI haberleşmesinde CRC kontrolü yapılmadığı için FFh gönderilmez. Bu bilgiyi gönderdikten sonra, durum cevabı iletilir. Gelen cevap 1F ile ve(and) lendiğinde 05h bilgisi elde edilmelidir. Aksi takdirde bilgi gönderimi hatalı olmuş demektir. Bu işlemden sonra kart kendi içersinde bu komutu icra edecektir. Ancak bu işlem belli bir süre aldığı için başka komut göndermeden önce bir süre beklenmesi gerekir. 10000 okuma yapılarak bu bekleme sağlanabilir.

mmc-sd-write-yazma

Kart yazma işlemi bittiken sonra, geriye sadece tek byte kart yazma komutu kalıyor. Onun da basit bir yapısı var. Önceki anlattığımız metot ile tek farkı, sabit 512 byte uzunlukta okuma yapmak zorunda olunmamasıdır. Şöyle ki; CMD16 komutu ile okunmak istenen uzunluk belirtilir. CMD16 ile hiçbir değer belirtilmemiş ise varsayılan değer 512 olarak kabul edilir. CMD17 ile istenilen adres bloğu, CMD16 ile belirtilen uzunluk kadar okunur. Normal okumadakine benzer bir şekilde kullanılır. Tek fark CMD17 cevabından belli bir süre sonra cevap gelmesidir. Bilgi göndermeye başlandığını anlamak için FEh cevabı gelene kadar okuma yapılır. Cevap olarak gelen FEh, bilgi göndermenin başladığını belirtir. FEh cevabı alıntıktan sonra gelen datalar SD kartın içindeki bilgilerdir. 512 byte datadan sonra 2 byte da CRC datası gönderilir. Bu bilgiyi kullanmadığımız için sadece 2 byte okuma yapmak bizim için yeterlidir. Böylece okuma işlemi gerçekleştirilmiş olur.

set-block-read-mmc-sd2

Neden cevap olarak 05h elde etmemiz gerektiğine gelince; Bu cevabın yapısı aşağıdaki şeklideki gibidir. Yani cevap olarak “Data accepted” cevabı vermelidir.

05h-sd-mmc

Bu işlemlerden sonra artık biz SD veya MMC kart SPI yolu ile cok kolay bilgi yazabilir ve okuyabiliriz.

512mb-sd-kart-ust

512mb-sd-kart-arka

PicProje E-Dergi 2 Yazar: arslan74

Yayım tarihi: 2018/07/05 Etiketler:



Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir