STM32F4 DMA interrupt problemi?

Başlatan Mucit23, 09 Nisan 2014, 15:49:21

Mucit23

Arkadaşlar Merhaba,

STM32F4'ün DMA modülü hakkında bir sorum olacak.

DMA transfer complete kesmesi, DMA nın buffer boyutu 1 den büyükse eğer dma her tetiklendiğinde kesme oluşurmu? Yoksa bufferin dolması beklenip öylemi kesme oluşur?

Sıkıntım şurada, DCMI ile DMA yı tetikliyorum. DMA dan istediğim, verdiğim dizinin bütün elemanlarına yeni değerleri yerleştirince kesme oluştursun.

DMA ayarlarım aşağıdaki gibi
  /* Enable DMA2 clock */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);  
  
  /* DMA2 Stream1 Configuration */  
  DMA_DeInit(DMA2_Stream1);

  DMA_InitStructure.DMA_Channel = DMA_Channel_1;  
  DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS;	
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) &image_array;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
  DMA_InitStructure.DMA_BufferSize = 19200;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
     
  DMA_Init(DMA2_Stream1, &DMA_InitStructure);
  /* DMA Interrupts config ***************************************************/
  DMA_ITConfig(DMA2_Stream1,DMA_IT_TC, ENABLE);
	
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream1_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
  NVIC_Init(&NVIC_InitStructure);


Kesme oluşuyor fakat dizinin dolması beklenmeden kesme oluşuyor. Yani DCMI'dan her tetik geldiğinde tahminimce DMA değeri alıp dizinin ilgili elemanına taşıyor ardından kesme oluşuyor. Üstelik süreklide oluşmuyor. DMA'nın Memory adresine FSMC adresini yazsam sürekli kesme oluşuyor ama dizi adresi verince tek bir frame boyunca kesme oluşuyor ardında duruyor.

Bu neden kaynaklanabilir?


superconductor

Hocam cozunurluk ve renk derinliginiz nedir? Acaba dma initde buyuklukler word oldugundanmi interrupt  once olusuyor diye dusundum.

Klein

TC kesmesi;  Buffer'in tamamı doldurulduktan sonra gerekleşir.  DMA ile kullanıln donanıma bağlı olarak değişiklik göstereceğini zannetmem. Belki bazı istisnalar olabilir ama ihtimal vermiyorum.

Mucit23

#3
Hocam DCMI dan gelen data 16bitlik (öyle olması gerekiyor) ama dma veri büyüklüklerini half word yapınca dma hiç çalışmıyor. 

Diziyi ise uint16_t türünde tanımlamışım.

Bu işlemi aslında adc ile yaptım.  Adc den dma yı tetikliyorum. Dma ise 64 adet örneği sırayla diziye yerleştirip en sonda kesme oluşuyordu. Dma ayarları hemen hemen aynı.

Hocam peki başka neden kaynaklanabilir

Klein

DMA hata kesmelerini de aktif edip , hataya düşüp düşmediğini kontol et. Belki bir yerlerde hataya düşüyor ve farketmiyor olabilirsin.
Ayrıca her TC kesmesinde bir sayıcıyı artırıp gerçekten veri adedi kadar  kesme geliyor mu  bakmak gerek.

Mucit23

Hocam dediklerinizi deneyeyim.

Acaba DMA buffer boyutu ile olabilirmi? Boyut şuanda 19200. Bu halde iken sadece tek bir frame boyunca kesme geliyor. (Öyle olduğunu tahmin ediyorum. ) Buffer boyutunu düşürmeyi denedim artık sürekli kesme oluşmaya başladı. Ama bufferin dolmasıyla değil yine aynı şekilde buffere yeni bir eleman geldiğinde kesme oluşuyor. Çok saçma bir durum.

Mucit23

Çalıştırdım çok şükür. Tam emin olmamakla birlikte interrupt rutininde problem olduğunu düşünüyorum.

İnterrupt rutinin aşağıdaki gibi yaptım.
void DMA2_Stream1_IRQHandler(void) 
{
	int i=0;
  if(DMA_GetITStatus(DMA2_Stream1, DMA_IT_TCIF1))
  {
		STM_EVAL_LEDToggle(LED3);
    for (i=0;i<19200;i++)
		{
      LCD_WriteRAM(image_array[i]);
    }
    /* Clear DMA Stream Transfer Complete interrupt pending bit */
    DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TCIF1);
  }
}


Önceden DCMI dan data gelir gelmez lcd ye gönderiliyordu. Şimdi ilk önce diziye biriktiriliyor sonra LCD ye gönderiliyor. Bu yüzden görüntü biraz yavaşladı gibi. Fakat bir problem var. Kamera biraz çalışıyor sonra sistem donuyor. Yani artık interrupt oluşmuyor. Bu neden kaynaklanabilir?

Klein hocam birde şunu sorayım? DMA nın veri alacağı adres 32 bit, Yazacağı adres ise 16 bitlik ise DMA bu durumda nasıl davranır?

Mesela DCMI Data Register 32 bitlik, Bu yüzden DMA_PeripheralDataSize ve  DMA_MemoryDataSize değerlerini WORD yapmasam çalışmıyor dma, Halbuki DCMI Data register 32 bit olmasına rağmen ben 16 bitlik data alıyorum.

Mucit23

Arkadaşlar sistemin donmasını çözemedim henüz. Ama şöyle bir durum var Kamera DCMI veya DMA donanımlarında donma olmuyor. Tümüyle MCU donuyor. Yani örneğin arka planda dcmi dma kesme felan kamera ile uğraşırken main de led yakıp söndürüyorum. Bazen 1 dk bazen 30 saniye sistem çalışıyor sonra tümüyle mcu donuyor. Çünkü mainde yakıp söndürdüğüm led'de artık yanıp sönmüyor.

Bu durum DMA ile diziye değer yazmadan önce olmuyordu.

DMA ve DCMI deki hata kesmelerinide açıyorum hata kesmeside oluşmuyor.

Olası problemler neler olabilir? Acaba DMA ile ilgili bir durummu?

Mucit23

Konu güncel.

Dünden beri bakınıyorum çözüm bulamadım. Nedense DMA ile Diziye veri yazınca oluyor bu durum. İşlemci Tümüyle donuyor. DMA ile Direk FSMC ye veri yazınca donma olmuyor.

DMA ve DCMI den hata kesmesi gelmiyor.
Nasıl çözebilirim. Açıkçası nereye bakacağımıda bilmiyorum. Fikri olan varmı?

SpeedyX

İşlemci resetleniyor olabilir mi?
Buffer boyutları (dma-size) değişip çok büyük veri aktarımı yapıyor olabilir mi?
DMA DCMI bayrağını kontrol ederek yazma yaptığı için problem çıkmıyor ama kontrolsüz sabit boyutla yazma yapınca overflow türevi bir olay oluşma ihtimali var.
Yazma boyutlarıyla oynayıp farkediyor mu kontrol edebilirsin.
DMA başlatmadan kesmeleri iptal edip deneme yapabilirsin.
Bir küçük ihtimal de, DMA ile yazdığın yere kesme de veya main de asenkron yazma yapılma durumu.

Mucit23

Hocam işlemci resetlense tekrar baştan başlaması gerekmezmi? Bende artık hiçbir kodu isleyemez hale geliyor. Tümüyle mcu donuyor. Hocam bence dma buffer boyutuyla ilgili bir problem var. Daha once dma kesmesi problemi varkeb farklı buffer boyutlarıyla farklı sonuçlar almıştım. Ama anlamıyorum dma zaten max. 16 bit bufferi desteklemiyormu. Yani teoride benim buffer size degerine 0xFFFF verebilmem gerekir. Neden dma problem çıkartıyor anlamıyorum.  Eğer overflow durumları varsa nasil tespit edebilirim?

SpeedyX

Yazma yapılan dizi değişkenin aralığının dışına çıkılıyor olabilir, debuggerda conditional breakpoint desteği varsa, şartlı durdurma yapılarak görülebilir.

Peki DMA ile diziden diziye kopyalama yapmayı deneyebilir misin? Öncelikle diğer donanımla alakası olmadığına emin olmak lazım.
Yada şimdiki setup ında olduğu gibi, tek bir RAM değişkeninden büyük diziye kopyalama yap, tüm dizi aynı değerle dolsun.
Sorun DMA ise yine kilitlenmesi gerekiyor.

Mucit23

Hocam Diziden diziye kopyalamayı nasıl yaparım? DMA yı tetikleyecek bir donanım olması gerekmezmi? Yine DCMI ile Tetikleyip Peripheral Adress kısmına ikinci dizinin adresinimi vereceğim?

Aslında Dma Bufferini 1 yapıp kesme içerisinde sırayla kendim diziye değer yazsam daha iyi olacak gibi. Sizin dediğiniz testleri bir yapayım. Olmadı kesme içerisinde direk diziye kendim yazacağım. Hem zaten dizi boyutu büyüdüğü zaman (örneğin 320x240 olsa) yine böyle yapmak zorunda kalacağım.


Mucit23