STM32F4 DMA + GPIO ile Senkronize transfer nasıl yapılır?

Başlatan Mucit23, 25 Nisan 2017, 17:00:42

Mucit23

Selamlar

DMA ile GPIO üzerinden bir donanıma paralel veri aktarımı yapalım. DMA, N boyutlu bir veriyi sıra ile GPIO'ya aktaracak. Ama bu aktarım sırasında veriyi aktardığı donanımın veriyi içeri alabilmesi için clock uygulanması gerekiyor. Yani her bir veri çıktığında otomatikmen bir clock palsi üretilmesi gerekiyor. 

STM32F4xx serisi üzerindeki DMA donanımı bu işi otomatik yapabilirmi?

baran123

Hocam o şekilde varmı bilmiyorum ama veri her porta aktarıldığında oluşan kesme illaki vardır. Aktarım tamamlandı kesme gibi bir şey olmalı. Bu kesme içerisinde bir clock palsi üretilebilir sanırım dimi ?

Mucit23

Baran o şekilde olur elbet düşündüm onu. Öyle yaparsam defasında işlemci kesmeye gidecek. Bu iş için özel bir yapı vardır diye düşünüyordum.


Uzun zamandır STM ile uğraşmıyorum. Bilgilerimin üstü baya tozlanmış

skara1214

soyle olsa;
gpioda 8 bit yollayacaksan ;9 bit yolla o 1 bitte  clock olsun ve 1 data transfer edeceğin yerde 2 data transfer et; ilk datada 9. bit 1 olsun 2. datada 9. bit 0 olsun böylece  dma 2 kere çalışır ama en azından işlemci zaman kaybına uğramadan sorunu çözer. eğer 2 dma süresi çok hızlı gelirse clock için;  3-4 dma tasıması yaptırıp clock süresini ayarlayabilirsin gibime geliyor.
Herkes ölür ama herkes gerçekten yaşamaz


skara1214

burada anlatılan one shot timeri   dma tetiklemesi olarak kullanma . tüm işlemcilerde vardır gibime geliyor.
Herkes ölür ama herkes gerçekten yaşamaz


Cemre.

Bir Timer'ı bir kanalı %50Duty PWM çıkışı (Mode 2) olacak şekilde ayarlayıp aynı Timer Update Event'ı ile DMA aktarımını tetiklesek olmaz mı?


Mucit23

Selamlar. Aradan 1 sene geçmiş. Bu konu tekrar gündemime geldi. Hızlı bir şekilde clock üreterek nasıl paralel veri aktarımı yapılabilir DMA ile bu konuyu düşünüyorum. Bu konuyu çözersem RGB Matrix ekranları 24bit renk derinliğinde sürebilirim.

@Cemre. Timer + DMA yı şimdi bende düşünüyorum. STM32F103 ile deneme yapıcam ama işleyişi tam olarak anlayamadım. Burada Clock Sinyali Timer çıkışımı olacak? Biraz daha ayrıntı verebilirmisin?

Elektroemre

Alıntı yapılan: Mucit23 - 16 Haziran 2018, 10:27:39Selamlar. Aradan 1 sene geçmiş. Bu konu tekrar gündemime geldi. Hızlı bir şekilde clock üreterek nasıl paralel veri aktarımı yapılabilir DMA ile bu konuyu düşünüyorum. Bu konuyu çözersem RGB Matrix ekranları 24bit renk derinliğinde sürebilirim.

@Cemre. Timer + DMA yı şimdi bende düşünüyorum. STM32F103 ile deneme yapıcam ama işleyişi tam olarak anlayamadım. Burada Clock Sinyali Timer çıkışımı olacak? Biraz daha ayrıntı verebilirmisin?

Uygun şekilde FSMC konfigüre edilip, senkron paralel data aktarımı için kullanılabilir. Gerekli clock polaritesi ve gecikme vs de ayarlanabilir.

Tagli

Hiç denemedim ama zamanında konuyu araştırmıştım. ST'nin bununla ilgili bir uygulama notu var.
Gökçe Tağlıoğlu

Mucit23

FSMC ile belki olur ama kesinlikle kullanmak istemiyorum. Birincisi konfigürasyonu çok karmaşık. İkincisi Düşük seviyeli MCUlarda bulunmuyor.

Tagli tamda aradığım not buydu. En kısa zamanda deneme yapacağım.

devrecii

Daha önce konu açmıştım stm32f103 ile dma -> gpio 4mhz den yukarısını elde edememiştim.

https://www.picproje.org/index.php/topic,72942.0.html

stm32f1 de dma1 kanal 2 yi kullanmştım çünkü 1. kanal bir yerden cloclk alıyor onu bulup kapatamadım

DMA kanal2 ve timer5 idi (stm32refde hangi kanal nerden yazıyor). Timer sayaç başa dönerken clock üretiyor gpio ya veri ulaşması zaman alacaktır. Pwm sinyali çok hızlı ulaşıyor fakat gpio yavaş bu nedenle aradaki zaman farkını osiloskopdan inceleyip pwm i tam veri ulaştığı zaman 1 olacak şekilde değerini verirsen  sorunsuz clock çıkışı da alabilrisin.

Ayrıca yaptığın zaman  stm32f4 Max gpio  hızını buraya yazarmısın bizde öğrenelim neymiş.

Mucit23

Stm32f103 de deneyeceğim. 4mhz clock hızı baya yüksek bir hız. Bu hızlarda veri basabilirsem başlangıç için gayet iyi bir hız

Mucit23

Selamlar

Kaç gündür işlerden hiç elimi vuramadım. Bugün biraz baktım. Bu işin HAL kütüphanesi ile yapmam gerekiyor. HAL Kütüphanesininin yapısını hala tam olarak oturtamadım. STD library ile çok farklı bir işleyişi var. Init aşamasında sorun yaşadım. Anlamadığım birkaç nokta var. Şuanda sadece TIM3'ün update event'i ile Hafızadan GPIO'ya veri taşımaya çalışıyorum. 

Öncelikle Timer3'ü Normal olarak kurdum.

  TIM_InitStruct.Instance = TIM3;
  TIM_InitStruct.Init.Prescaler = 72-1;
  TIM_InitStruct.Init.CounterMode = TIM_COUNTERMODE_UP;
  TIM_InitStruct.Init.Period = 1000-1;  
  TIM_InitStruct.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  TIM_InitStruct.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
 TIM_InitStruct.Init.RepetitionCounter = 0;
  if (HAL_TIM_Base_Init(&TIM_InitStruct) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 

Her 1ms'de bir Update olayı oluşturacak. Daha sonra DMA Ayarlarımı yaptım.

  DMA_InitStruct.Instance = DMA1_Channel2;
  DMA_InitStruct.Init.Direction = DMA_MEMORY_TO_PERIPH;
  DMA_InitStruct.Init.PeriphInc = DMA_PINC_DISABLE;
  DMA_InitStruct.Init.MemInc = DMA_MINC_ENABLE;
  DMA_InitStruct.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; // 16 bits
  DMA_InitStruct.Init.MemDataAlignment = DMA_PDATAALIGN_HALFWORD;
  DMA_InitStruct.Init.Mode = DMA_NORMAL;
  DMA_InitStruct.Init.Priority = DMA_PRIORITY_LOW;
 if (HAL_DMA_Init(&DMA_InitStruct) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 

Bundan sonra TIM3 ile DMA'yı birbirine bağlamak gerekiyor. Bunu şu şekilde yaptım.

__HAL_LINKDMA(&TIM_InitStruct,hdma[TIM_DMA_ID_UPDATE],DMA_InitStruct);
 

Son olarak DMA_Channel2 kesmesini aktif edip DMA ve TIM Donanımını aktif ettim.

  HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0); // enable DMA IRQ
  HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
 
  __HAL_TIM_ENABLE_DMA(&TIM_InitStruct, TIM_DMA_UPDATE);
 __HAL_TIM_ENABLE(&TIM_InitStruct);
 
 HAL_DMA_Start_IT(TIM_InitStruct.hdma[TIM_DMA_ID_UPDATE],(uint32_t)&my_buf, (uint32_t)&GPIOA->ODR, 100);

Datasheette DMA1 TIM3 Tetiklerme kanallı Channel2 ile mümkün görünüyor.

Buraya kadar normal bu şekilde yaptım. Hata olabilir henüz denemedim. Anlamadığım nokta kesmelerle ilgili. DMA1_Channel2 ile ilgili kesmeler aşağıdaki fonksiyona düşüyor. Örneklerden anladığım kadarıyla aşağıdaki gibi yaptım.

void DMA1_Channel2_IRQHandler(void)
{
    HAL_DMA_IRQHandler(TIM_InitStruct.hdma[TIM_DMA_ID_UPDATE]);
}


Hall library'de birde CallBack yapısı var. Yukarıdaki Fonksiyona DMA1 CH2 ile ilgili bütün kesmeler düşüyor. Ama örneğin TransferComplete Kesmesini istediğimiz bir fonksiyona gönderebiliyoruz anladığım kadarıyla. Bunu nasıl yapıyoruz? Örneğin XferCpltCallback Fonksiyonunu nasıl belirleyeceğim?

Ek olarak Clock Üretmek için Tim3'ün herhangi bir kanalını OC modda çalıştırmam yeterlimidir?