STM32F7 DCMI ayarları ve problemler.

Başlatan Mucit23, 09 Şubat 2016, 14:35:42

Mucit23

Selamlar,

Daha önce F4 discovery'de  OV9655 kamera ile biraz uğraşmıştım. DCMI kameralardaki frame yapısını vs oradan biraz tanıyorum. Forumda daha önce kameralarla uğraşan varmı bilmiyorum açıkçası ben şuan uğraştığım kamerada bayağı ilerledim fakat dcmi donanımında takıldım.  Biraz fikir alışverişine ihtiyacım var.

Şuanda Aptinanın MT9P031 sensörü üzerinde çalışma yapıyorum. Elimde aynı OV9655 modülü gibi bu sensör için yapılmış bir board var. Ben bu sensörü STM32F7'deki DCMI konnektörüne bağladım. Kameradan RAW video pixel datası almam gerekiyor.

Kamerayı I2C üzerinden konfigüre ettim. Bu konuda sıkıntı yok. Bütün register'lara erişebiliyorum. Yazma ve okuma yapabiliyorum.

Kameranın Pixel Out Frame Timing'i aşağıdaki gibi.


Şuanda Kameranın çıkışlarını Lojik Analyser ile inceliyorum. Lojik çıktılar aşağıdaki gibi.

Biraz daha yakınlaştırırsak her bir HSYNC darbesinde Pixel Datalarının geldiğini görebiliriz. 


Kameranın çalıştığını bu şekilde anlıyorum.

DCMI'da  HAL_DCMI_LineEventCallback kesmesi her bir HSYNC yükselen kenarında oluşuyor. Line Kesmesi çalışıyor yani Benim Sıkıntım Frame ve VSYNC kesmesinde.

Bu iki kesmede sadece 1 kere oluşuyor. Normalde VSYN kesmesi ile Frame kesmesi arasında bir fark yok değilmi? Çünkü VSYNC darbesi sadece Frame tamamlandığında geliyor olması lazım.

Aslında debug yaptığımda DCMI Raw interrupt status (DCMI->RIS) registerinden bütün kesmelerin oluştuğunu görebiliyorum. VSYNC ve Frame kesmeside oluşuyor aslında fakat 1 kere kesme oluştuktan sonra kesmeler pasif hale geliyor. Bunu DCMI interrupt enable registerinden (DCMI->IER) görebiliyorum.

DCMI ayarları ilk kez yapılandırıldığında bütün kesmeler aktif olarak başlıyor sistem. Kesme oluştuğu zaman kesme rutininde ilk başta kesme nereden gelmiş ona bakılıyor(VSYNC, ERR, Frame vs) Sonra kesme kapatılıp tekrar kesme ile ilgili işlemler yapılıp tekrardan kesmenin aktif edilmesi lazım. Ama hal libraryde böyle yapılmamış

Kesme rutinine bakarsak
void HAL_DCMI_IRQHandler(DCMI_HandleTypeDef *hdcmi)
{  
  /* Synchronization error interrupt management *******************************/
  if(__HAL_DCMI_GET_FLAG(hdcmi, DCMI_FLAG_ERRRI) != RESET)
  {
    if(__HAL_DCMI_GET_IT_SOURCE(hdcmi, DCMI_IT_ERR) != RESET)
    {
      /* Disable the Synchronization error interrupt */
      __HAL_DCMI_DISABLE_IT(hdcmi, DCMI_IT_ERR); 

      /* Clear the Synchronization error flag */
      __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_ERRRI);

      /* Update error code */
      hdcmi->ErrorCode |= HAL_DCMI_ERROR_SYNC;

      /* Change DCMI state */
      hdcmi->State = HAL_DCMI_STATE_ERROR;

      /* Process Unlocked */
      __HAL_UNLOCK(hdcmi);

      /* Abort the DMA Transfer */
      HAL_DMA_Abort(hdcmi->DMA_Handle);
      
      /* Synchronization error Callback */
      HAL_DCMI_ErrorCallback(hdcmi);
    }
  }
  /* Overflow interrupt management ********************************************/
  if(__HAL_DCMI_GET_FLAG(hdcmi, DCMI_FLAG_OVFRI) != RESET) 
  {
    if(__HAL_DCMI_GET_IT_SOURCE(hdcmi, DCMI_IT_OVF) != RESET)
    {
      /* Disable the Overflow interrupt */
      __HAL_DCMI_DISABLE_IT(hdcmi, DCMI_IT_OVF);

      /* Clear the Overflow flag */
      __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_OVFRI);

      /* Update error code */
      hdcmi->ErrorCode |= HAL_DCMI_ERROR_OVF;

      /* Change DCMI state */
      hdcmi->State = HAL_DCMI_STATE_ERROR;

      /* Process Unlocked */
      __HAL_UNLOCK(hdcmi);

      /* Abort the DMA Transfer */
      HAL_DMA_Abort(hdcmi->DMA_Handle);

      /* Overflow Callback */
      HAL_DCMI_ErrorCallback(hdcmi);
    }
  }
  /* Line Interrupt management ************************************************/
  if(__HAL_DCMI_GET_FLAG(hdcmi, DCMI_FLAG_LINERI) != RESET)
  {
    if(__HAL_DCMI_GET_IT_SOURCE(hdcmi, DCMI_IT_LINE) != RESET)
    {
      /* Clear the Line interrupt flag */  
      __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_LINERI);

      /* Process Unlocked */
      __HAL_UNLOCK(hdcmi);

      /* Line interrupt Callback */
      HAL_DCMI_LineEventCallback(hdcmi);
    }
  }
  /* VSYNC interrupt management ***********************************************/
  if(__HAL_DCMI_GET_FLAG(hdcmi, DCMI_FLAG_VSYNCRI) != RESET)
  {
    if(__HAL_DCMI_GET_IT_SOURCE(hdcmi, DCMI_IT_VSYNC) != RESET)
    {
      /* Disable the VSYNC interrupt */
      __HAL_DCMI_DISABLE_IT(hdcmi, DCMI_IT_VSYNC);   

      /* Clear the VSYNC flag */
      __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_VSYNCRI);

      /* Process Unlocked */
      __HAL_UNLOCK(hdcmi);

      /* VSYNC Callback */
      HAL_DCMI_VsyncEventCallback(hdcmi);
    }
  }
  /* End of Frame interrupt management ****************************************/
  if(__HAL_DCMI_GET_FLAG(hdcmi, DCMI_FLAG_FRAMERI) != RESET)
  {
    if(__HAL_DCMI_GET_IT_SOURCE(hdcmi, DCMI_IT_FRAME) != RESET)
    {
      /* Disable the End of Frame interrupt */
      __HAL_DCMI_DISABLE_IT(hdcmi, DCMI_IT_FRAME);

      /* Clear the End of Frame flag */
      __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_FRAMERI);

      /* Process Unlocked */
      __HAL_UNLOCK(hdcmi);

      /* End of Frame Callback */
      HAL_DCMI_FrameEventCallback(hdcmi);
    }
  }
}


Mesela Frame interrupt bölümü içerisinde  __HAL_DCMI_DISABLE_IT(hdcmi, DCMI_IT_FRAME); komutu ile kesme pasif hale getirilmiş. Bunun dışında kesmelerin aktif edildiği bir yer göremiyorum. Bu kod parçası hal library nin kendi dcmi interrupt rutini.  Eğer kesme kapatılıyorsa bir yerde tekrar aktif edilmesi lazım. O noktayı bulamıyorum
HSYNC içinde aynı durum söz konusu ama HSYNC interrupt oluştuktan sonra kesme tekrar aktif hale geliyor. Bu yüzden normal olarak DCMI kesmesi çalışıyor.

Bu sorun yüzünden iki gündür ilerleme kaydedemedim.

Sorunu net olarak açıklamak için biraz uzun yazdım. Sorun sizce konfigürasyonlarla mı ilgili? Hal library'de neden böyle bir durum söz konusu fikri olan varmı?

Teşekkürler

ArifAhmet

Hocam belki kucuk bir ihtimal ve cok emin olmamakla beraber. HAL_Init fonksiyonu cagirildiginda hal ayrica hal_msp.c dosyasinada bakiyor. Orayi inceleyebilirsiniz.
Yaşasın Open Source!

Mucit23

#2
Arif hocam yok. Kütüphaneyi neredeyse ben yazdım. MSP dosyasına gitmiyor. Bütün ayarlamalar benim yazdığım kütüphane içerisinde yapılıyor.

Biraz ilerleme kaydettim aslında

Açıklama yapmadan önce bir soru sorayım. STM32'lerde kesme içerisindeyken kesme kaynağını kapatmak, disable yapmak gereklimidir?

Bir önceki mesajımda verdiğim HAL_DCMI_IRQHandler fonksiyonunda LINE kesmesinin oluştuğundan ama Frame ve VSYNC kesmesinin ise 1 kere oluştuğundan bahsetmiştim. HAL library'de bir sıkıntı olduğunu düşünüyorum çünkü Frame ve VSYNC kesmesinin içerisinde __HAL_DCMI_DISABLE_IT komutu ile VSYNC ve FRAME kesmesi kapatılıyor. Dahada açılmıyor. Bu yüzden iki kesmede sadece bir kere oluşuyor. LINE kesmesinde ise kesme kapatılmamış. Bu yüzden o sürekli çalışıyor.

Anlamıyorum HAL library'de mi sıkıntı var? Benim normalde bu kodlara hiç müdahale etmemem gerekiyor.

Şuanki durum ise şöyle. Kamera çalışıyor VSYNC, FRAME ve LINE kesmeleri normalde olması gerektiği gibi çalışıyor. (Şimdilik öyle görünüyor) Fakat DCMI'dan data alamıyorum. Lojik analyser ile Kameranın D0-D7 hattını inceliyorum veri geliyor fakat DCMI->DR registerinin sürekli sıfır olduğunu görüyorum. Normalde anlık olarak pixel değerleri gelmesi gerekir değilmi? Debugda incelediğim zaman hiçbirşey göremiyorum DCMI_DR registerinde.

Şuanki sorun bu. Eğer halledebilirsem kamerayı çalıştırmış olacam .

Mucit23

Frame kesmesinin içinde kesmenin kapatılmasının sebebi galiba şudur.

Normalde sistem DMA ile çalışıyor. DMA kurulduğu zaman Bütün bir Frame aktarıldığında DMA_TC kesmesi oluşuyor. DMA TC kesmesi içerisinde HAL_DCMI_FrameEventCallback fonksiyonunun çağrıldığını gördüm. Yani frame kesmesi DMA ile çağrılıyor aynı anda DCMI tarafından da çağrılmaması için kesme rutini içerisinde DCMI_Frame kesmesi kapatılmış.

DCMI düzgün çalışmadığından DMA'da çalışmıyor.

Şuanki duruma göre DCMI'da kesmeler vs oluşuyor. Frame vs geliyor bunları lojik analyser ile görebiliyorum ama DCMI data almıyor. DCMI_DR registeri sürekli sıfır. Tek sorun budur.

Donanımdamı sorun var yazılımdamı bilmiyorum bundan emin olmak için STM32F4_Dis-Cam kamera modülünü alacağım. Doğrudan ST'nin kütüphane desteği var. Çalıştırırsam eğer DCMI donanımını biraz daha anlamış olurum.



Mucit23

Arkadaşlar DCMI'da senkronizasyon nasıl sağlanıyor?

Kameranın Frame Timing tablosu aşağıdaki gibi


DCMI ayarlarında senkronizasyon için birkaç parametre var.

  /* DCMI configuration */
  phdcmi->Init.CaptureRate      = DCMI_CR_ALL_FRAME;
  phdcmi->Init.HSPolarity       = DCMI_HSPOLARITY_LOW;
  phdcmi->Init.SynchroMode      = DCMI_SYNCHRO_HARDWARE;
  phdcmi->Init.VSPolarity       = DCMI_VSPOLARITY_LOW;
  phdcmi->Init.ExtendedDataMode = DCMI_EXTEND_DATA_8B;
  phdcmi->Init.PCKPolarity      = DCMI_PCKPOLARITY_RISING;
  phdcmi->Instance              = DCMI;

Burada PCKPolarity Parametresi Pixel Datasının Yükselen kenardamı yoksa düşen kenardamı içeri alınacağını belirtiyor.

HSPolarity  ve VSPolarity parametrelerini anlyamadım. Şimdi Bu parametrelerin ikisinide LOW yapınca DCMI_DR registerinde değişen değerler görüyorum. İkiside HIGH olduğu zaman herhangi bir ver göremiyorum.

Yukarıdaki resime bakarsanız FV ile LV yani HSYNC sinyali lojik1 de iken data geliyor. Senkronizasyonun sağlanması için LV ve FV pinlerinin low olduğu anlarmı tespit edilmesi gerekiyor? Senkronizasyon nasıl sağlanır?

Bu halde Data geliyor. Fakat gelen Datalar 32 bitlik. Ben 8 bit data alınacak şekilde ayarlamıştım. Neden 32 bit data gelirki? Yanlış bir data gelse bile 8 bit olması gerekmezmi?