STM32F4 Discovery Maceraları - 5 : CRC Donanımı (StdPeriph CRC Kütüphanesi İle)

Başlatan muuzoo, 19 Temmuz 2012, 23:47:47

muuzoo

Bu yazının aslı http://gunluk.muuzoo.gen.tr/2012/07/19/stm32f4-discovery-maceralari-5-crc-donanimi/ adresinde yayınlanmıştır.

------------------------------------------------------------------------------------------------------------------------------------------------------------

STM32F4 ile bir macerada daha birlikteyiz. Bu seferki hedefimiz CRC donanımını uygun bir şekilde kullanabilmek. Her zamanki gibi ilk önce güzel bir müzik açıp olaya girişiyoruz. Müziksiz olmaz :) . İlk olarak STM32F4′ün olmazsa olmaz belgesi olan DM00031020.pdf dosyasını inceleyerek başlıyoruz. Göreceğiniz üzere CRC donanımı hakkında topu topu 3 sayfalık bir yer ayrılmış. Bu şu anlama geliyor; fazla teferruat yok demek. Dikkat edilecek hususlar ilk sayfada sıralanmış:

    *CRC-32 Ethernet polinomu kullanılıyor : 0x4C11DB7
    *32 bitlik tek bir saklayıcı kullanılıyor (giriş/çıkış)
    *İşlem 4 AHB çevrim süresinde tamamlanıyor.
    *Genel maksatlı 8 bitlik bir saklayıcımız da var.
    *CRC birimi reset edilirse içeriği 0xFFFFFFFF değerini alır.

Evet bu anahtar bilgilerden sonra sıra geldi bu donanım için yazılmış olan kütüphane fonksiyonlarını incelemeye. Bunun için de stm32f4xx_dsp_stdperiph_lib_um.chm dosyasını inceliyoruz. İlgili donanım için gerekli fonksiyon tanımlamaları şunlar olarak verilmiş:

CRC Fonksiyon Tanımlamaları      

//Resets the CRC Data register (DR).
void CRC_ResetDR (void)
 
//Computes the 32-bit CRC of a given data word(32-bit). 
uint32_t CRC_CalcCRC (uint32_t Data)
 
//Computes the 32-bit CRC of a given buffer of data word(32-bit).
uint32_t CRC_CalcBlockCRC (uint32_t pBuffer[], uint32_t BufferLength)
 
//Returns the current CRC value.
uint32_t CRC_GetCRC (void)
 
//Stores a 8-bit data in the Independent Data(ID) register. 
void CRC_SetIDRegister (uint8_t IDValue)
 
//Returns the 8-bit data stored in the Independent Data(ID) register.
uint8_t CRC_GetIDRegister (void)


Bu fonksiyonlara ait ayrıntılı kullanım bilgisine bahsettiğim belgeden ulaşabilirsiniz. Burda sadece fikir vermesi açısından fonksiyon tanımlamalarını vermek istedim. Sıra geldi örnek bir çalışma yapmaya. Ayrıca bu kodu yazarken ufak bir asm kodu da kullanacağız ve c ile kod yazarken nasıl asm kodu eklenebileceğini de göreceğiz. İlk olarak crc kütüphanesini kodumuza ekliyoruz. Eğer başından beri bu sitede yazılan yazıya göre hareket ediyorsanız daha ilk çalışmamızda projemize dahil ettiğimiz "stm32f4xx_conf.h" dosyası içindeki tanımlamalardan #include "stm32f4xx_crc.h" tanımlamasını etkinleştiriyoruz. Ya da bu tanımlamayı kodumuza dahil ediyoruz, seçim size kalmış. Daha sonra da aşağıda verdiğim kodu test amaçlı kullanıyoruz.

CRC_Test Kodu
      

/* CRC Donanımı Kullanımı.
 * main.c
 *
 *  Created on: 19 Temmuz 2012
 *      Author: m2k
 */
#include "stm32f4xx.h"
 
GPIO_InitTypeDef  GPIOD_InitStructure;
 
/*Bit sıralamasını tersleyen fonksiyon*/
uint32_t ReverseBit (uint32_t data) {
   asm("rbit r0,r0; bx lr");
   return data;
}
 
int main(void) {
  uint32_t sonuc = 0;
  /* GPIOD ve CRC Periph clock enable */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD|RCC_AHB1Periph_CRC, ENABLE);
 
  /* Configure PD12, 13, 14 and PD15 in output pushpull mode */
  GPIOD_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  GPIOD_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIOD_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIOD_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIOD_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
 
  CRC_ResetDR();
  GPIO_Init(GPIOD, &GPIOD_InitStructure);
 
  sonuc = ReverseBit(0x34333231);
  sonuc = CRC_CalcCRC(sonuc);
  sonuc = ReverseBit(sonuc);
  sonuc^= 0xFFFFFFFF;
 
  while (1) {
     if(sonuc == 0x9BE3E0A3)
      GPIO_SetBits(GPIOD,GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);
     else
      GPIO_ResetBits(GPIOD,GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);
 
  }
}


Şimdi yaptıklarımı açıklayayım. CRC donanımına sadece veri girişi yapıp daha sonra da sonucu okuyabilirdik fakat bu durumda elde ettiğimiz değerler, yazılımlarda (ethernet, winzip,winrar v.b.) kullanılan crc32 ile uyumlu değil. O yüzden bir kaç ufak numara çevirmemiz gerekti. İlk olarak bize lazım olan şey bit sıralamasını terslemek. Bunun için bir "c" fonksiyonu da yazabilirdik ama burada mikrodenetleyicimizin asm komut kümesinde bulunan "rbit" komutunu kullandık ve c içinde asm olarak çağırdık. İlgili satırlar şunlar:

ReverseBit     

/*Bit sıralamasını tersleyen fonksiyon*/
uint32_t ReverseBit (uint32_t data) {
   asm("rbit r0,r0; bx lr");
   return data;
}


Daha sonra sıralaması terslenmiş olan değerimizi ki burda kullandığım örnek değer ascii "1234″ olan bilginin hex karşılığı olan "0×34333231″ değerinin bit sırası terslenmiş halidir, CRC_CalcCRC fonksiyonuna giriyoruz. Burada şöyle bir bilgilendirme yapmalıyım. Şimdi kullandığımız veri olan "1234″ bilgisinin yazıldığı sıraya dikkat ediniz. İlk girilen ascii "1″ değerinin karşılığı olan "0×31″ değeri en sağda yer almış durumda. Bu duruma dikkat ediyoruz.

CRC donanımından aldığımız değerin  bit sırasını tekrar tersliyoruz ve son larak 0xFFFFFF değeri ile xor işlemine tabi tutuyoruz. Bu işlemleri neden yapıyoruz derseniz eğer CRC32 standartının gerekliliği ile alakalı bir durum. Elde ettiğimiz değeri ise "0x9BE3E0A3" değeri ile kıyaslıyoruz. Bu değeri nasıl hesapladık derseniz BURADAKİ  İnternet sitesinden kopya çektik :) . Elde ettiğimiz değer doğru ise ledler yanarak bizim sonucumuz doğru olduğunu gösteriyor.
gunluk.muuzoo.gen.tr - Kişisel karalamalarım...