ARM Interruptlarda CallBack olayı nedir?

Başlatan Eren Eraslan, 30 Aralık 2016, 17:10:36

Eren Eraslan

Merhaba hocamlar

STM32L4 Nucleo ile cubeMX kullanarak birşeyler karalamaya çalışıyorum. Amacım uart intterupt dan verileri okuyup eko yapmak. Uart interrupt için 2 yöntem mi var yoksa ben mi tam anlayamadım.
Tutoriallarda bazıları alttaki gibi uygulamış

void USART3_IRQHandler(void)
{

  HAL_UART_IRQHandler(&huart3);
  Datayi_bufferla
 ...

}


ama kimisi de HAL_UART_RxCpltCallback fonksiyonu yaratıp onun içinde bufferlama yapmış

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	uint8_t i;
	if(huart->Instance == USART3)
	{
		if(Rx_Index == 0)
		{
			for (i=0;i<100;i++)
				Rx_Buffer[i]=0;																//clear Rx_Buffer before receiving new data	
		}
		if(Rx_data[0] != 13 && Rx_Index <50)							// CR degilse datayi al
		{
			Rx_Buffer[Rx_Index++] = Rx_data[0];
		}
		else
		{
			Rx_Index = 0;
			Transfer_Cplt = 1;
		}
		HAL_UART_Receive_IT(&huart3,(uint8_t*)Rx_data,1);
	}
}



Bu callback mantığı nedir? Hal dokümanında bufferlama işlemi bittiğinde verilen interrupt deniyor benmi yanlış anladım bilmiyorum
ama normalde data geldiğinde yani RX pini GND ye çekildiğinde girmez mi?

insanın içine işleyen şarkılar ;  https://soundcloud.com/reeraslan

MC_Skywalker

ADC örenklerinde de gördüm bu Callback olayını

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	if (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOC))
		{
		ADC_raw = HAL_ADC_GetValue(hadc);
		Vdd = 3300 * (*VREFINT_CAL_ADDR)/ADC_raw;
		}
}

Eren Eraslan

hocam normalde interruptın bir adresi olur ve o adresteki fonksiyona dallanıp işlemi yapıp çıkmaz mıyız?
Ben alttaki koddan birşey anlamadım açıkcası.

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	uint8_t i;
	if(huart->Instance == USART3)
	{
		if(Rx_Index == 0)
		{
			for (i=0;i<100;i++)
				Rx_Buffer[i]=0;																//clear Rx_Buffer before receiving new data	
		}
		if(Rx_data[0] != 13 && Rx_Index <50)							// CR degilse datayi al
		{
			Rx_Buffer[Rx_Index++] = Rx_data[0];
		}
		else
		{
			Rx_Index = 0;
			Transfer_Cplt = 1;
		}
		HAL_UART_Receive_IT(&huart3,(uint8_t*)Rx_data,1);
	}
}
/* USER CODE END 0 */

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART3_UART_Init();

  /* USER CODE BEGIN 2 */
		HAL_UART_Receive_IT(&huart3,(uint8_t*)Rx_data,1);		//activate the interrupt
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
		printf("HELLO FUCKIN WORLD \n");
		if(Transfer_Cplt == 1)
		{
			printf("This is %s \n",Rx_Buffer);
			Transfer_Cplt = 0;
		}
		HAL_Delay(500);

  }
  /* USER CODE END 3 */

}



bu HAL_UART_RxCpltCallback fonksiyonuna vektörde vermedim. Bu, kardeşim ben uarttan gelen datayı senin mainde beni aktifleştirdiğin ve Rx_data diye isimlendirdiğin buffera doldurdum. Sen istersen okursun aha buraya bırakıyorum mu demek? Çünkü debugda baktığımda if(Rx_data[0] != 13) satırına gelirken daha datayı bufferlamış içeriğine bakıyordu. Sana ben datayı oku demedim ki henüz, bak fonksiyonun en altında HAL_UART_Receive_IT() duruyor daha

Mainde HAL_UART_Receive_IT(&huart3,(uint8_t*)Rx_data,1); aktifleştirmek için yazdığım andan itibaren mi başlıyor ?

insanın içine işleyen şarkılar ;  https://soundcloud.com/reeraslan

MC_Skywalker

Hocam  şuaryı okursan belki fikir verir. http://letanphuc.net/2015/09/stm32f0-uart-tutorial-5/
Ben PWM için bu adamın yaptıklarını denemiştim.

şimdiler SPI öğrenmeye çalışıyorum.

Eren Eraslan

Bende bu arkadaşı takip ediyorum, bunla ilgili ona yazdım.

Bu arada bu tarz tutorial ları ya da C ile ilgili detaylı anlatımları hem hitlilerden öğreniyorum. İlginç bir şekilde youtube da filan aşırı paylaşımcılar
insanın içine işleyen şarkılar ;  https://soundcloud.com/reeraslan

ecunnu

Merhaba bildigim kadari ile bu callback fonksiyonları interupt icinden cagrılan fonksiyonlardır. Soyleki; islemci interrupt geldiginde once interrupt fonksiyonuna gider ve orda rutin yapmasi gereken komutlari yurutur, daha sonrada bu callback fonksiyonuna dallanir. Peki bu ne isimize yarar derseniz rutin islerle main dosyamızı doldurmayiz hemde islemler birazdaha kolaylastrılmıtır. Ama illede interrupt fonksiyonunu kullanacam derseniz karar yine sizin.

Eren Eraslan

Alıntı yapılan: ecunnu - 30 Aralık 2016, 21:50:55
Merhaba bildigim kadari ile bu callback fonksiyonları interupt icinden cagrılan fonksiyonlardır. Soyleki; islemci interrupt geldiginde once interrupt fonksiyonuna gider ve orda rutin yapmasi gereken komutlari yurutur, daha sonrada bu callback fonksiyonuna dallanir. Peki bu ne isimize yarar derseniz rutin islerle main dosyamızı doldurmayiz hemde islemler birazdaha kolaylastrılmıtır. Ama illede interrupt fonksiyonunu kullanacam derseniz karar yine sizin.

main dosyamızı doldurmayız derken?

zaten interrupt dosyasındasın hocam. İşi gerçekten handle edeceğin yer?
insanın içine işleyen şarkılar ;  https://soundcloud.com/reeraslan

Tagli

HAL'ın kesme tabanlı UART'ından benim anladığım şu: HAL_UART_Receive_IT fonksiyonu ile bellekte bir alana doldurmak üzere belli bir miktar byte'ı kesme ile almak istediğimizi bildiriyoruz. Bu fonksiyon UART kesmesini uygun şekilde ayarlıyor, bir byte sayacı kuruyor. Veri geldikçe arka planda çalışan kesme, tampon belleği dolduruyor. Tahminimce gelen son byte ile birlikte (sayaç sıfırlanınca) alım kesmesi kendi kendini devre dışı bırakıyor ve "tamam, benim işim bitti" demek için HAL_UART_RxCpltCallback fonksiyonunu çağırıyor. Yani bir çeşit üst seviye yapay kesme rutini gibi. Orada da kullanıcı ne yapmak isterse yapıyor.

Bunun bir benzerini PIC'te veri gönderme kesmesi için callback kullanmadan kendim elle yazıyordum.

Ama alım işlemi için bu yöntem hiç hoşuma gitmedi. Pek çok uygulamada, ne kadar byte beklediğimizi baştan bilemeyiz. Zaten internette araştırırsanız insanların HAL ile ilgili olarak bu durumdan şikayetçi olduklarını görebilirsiniz. Önerilen çözümlerden biri, HAL_UART_Receive_IT fonksiyonunu 1 byte alacak şekilde tekrar tekrar çağırmak ancak bu durumda gerçek UART kesmesi de sürekli aç - kapa yapılıyor ve arada kaçan byte'lar olabiliyor.

HAL içindeki UART alım kesmesini doğrudan müdahale edilerek belki bu sorunun etrafından dolaşılabilir ama biraz kirli bir çözüm olur bence. ARM öğrenmeye yeni başladığım şu günlerde HAL'a zaten "öğrensem mi, öğrenmesem mi?" diye şüpheyle bakarken, bu durum benim için ciddi bir caydırıcı oldu ve ek kütüphane kullanmadan CMSIS ile devam etmeye karar verdim.
Gökçe Tağlıoğlu

Zoroaster

Çok karmaşık donanımlar için yazılmış hazır program yada kütüphanelerde (mesela USB) interrupt rutininde donanımla ilgili kodlar adamlar tarafından zaten yazmışlar.
Adamlar al yemeği pişirdik burada yiyin diye de Callback fonksiyonları hazırlamışlar.

Böylece katman katman hazırlanan yazılım yapısı korunmuş.

Seytan deliginden kacti.

ecunnu

Hocam " stm32f0xx_hal_uart.c " incelerdeniz HAL_UART_RxCpltCallback(huart) fonksiyonunun iki yerden cagrıldıgını gorursunuz birinci fonksiyon

UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
/**
  * @brief DMA UART receive process complete callback.
  * @param hdma: DMA handle.
  * @retval None
  */
static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
{
  UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
  
  /* DMA Normal mode */
  if ( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) )
  {
    huart->RxXferCount = 0;

    /* Disable the DMA transfer for the receiver request by resetting the DMAR bit
       in the UART CR3 register */
    huart->Instance->CR3 &= (uint32_t)~((uint32_t)USART_CR3_DMAR);

    /* Check if a transmit Process is ongoing or not */
    if(huart->State == HAL_UART_STATE_BUSY_TX_RX)
    {
      huart->State = HAL_UART_STATE_BUSY_TX;
    }
    else
    {
      huart->State = HAL_UART_STATE_READY;
    }
  }
  
  HAL_UART_RxCpltCallback(huart);
}


ikincisi  HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart) fonksiyonu eklemedim biraz uzun:D bulent hocanın dedigi gibi adamlar herseyi arka planda yaparak size zahmet vermemeye calismıslar. Bu kutuphaneyi incelersen bence sorularının hepsine cevap bulabilirsin. Bu arada __weak keywordunu bilmiyorsan eger arastirmanı oneririm.

M_B

@Taglı Hocam;
CMSIS le ilgili calışmalarınız da bizlere de yol gösterecek örnekler paylaşırmısınız.
İmkanın sınırlarını görmek için imkansızı denemek lazım.                                                             Fatih Sultan Mehmet

Tagli

CMSIS aslında tam bir kütüphane değil, genel olarak register'ların isimlerinin ve erişimlerinin nasıl olacağını gösteren bir standart. Doğrudan işlemci register'larına değer yazarak programlama gerçekleşiyor. Onun dışında, bazı temel çekirdek fonksiyonları ile de ilgili birkaç fonksiyon sunuyor.

Forumda z'nin hazırladığı ARM eğitimleri aslında bu konuda oldukça yeterli ve bu şekilde kodlamayı anlatıyor. Bunun üstüne benim ekleyecek bir şeyim yok. Ancak bir ara, SW4STM32 ile sıfırdan proje oluşturma ve içine CMSIS + gerekli diğer dosyaların eklenmesi ile ilgili bir yazı hazırlamayı düşünüyorum.
Gökçe Tağlıoğlu

Cemre.

Alıntı yapılan: Tagli - 31 Aralık 2016, 12:22:40
CMSIS aslında tam bir kütüphane değil, genel olarak register'ların isimlerinin ve erişimlerinin nasıl olacağını gösteren bir standart. Doğrudan işlemci register'larına değer yazarak programlama gerçekleşiyor. Onun dışında, bazı temel çekirdek fonksiyonları ile de ilgili birkaç fonksiyon sunuyor.

Forumda z'nin hazırladığı ARM eğitimleri aslında bu konuda oldukça yeterli ve bu şekilde kodlamayı anlatıyor. Bunun üstüne benim ekleyecek bir şeyim yok. Ancak bir ara, SW4STM32 ile sıfırdan proje oluşturma ve içine CMSIS + gerekli diğer dosyaların eklenmesi ile ilgili bir yazı hazırlamayı düşünüyorum.
http://www.keil.com/pack/doc/CMSIS/Core/html/using_CMSIS.html

Burada basit bir örnekle açıklanmış. Benim asıl merak ettiğim şey ise CMSIS-DSP bölümü. Buradaki matematik fonksiyonların (özellikle PID, park-clarke dönüşümleri) performansları nasıldır? Bunları projelerinde kullanan var mı? CMSIS-DSP kullanabilmek için ille de FPU-DSP birimli MCU (misal STM32F429ZI) mu kullanmak gerekir?

Anlatımı forumda da paylaşırsanız sevinirim @Tagli

Tagli

Alıntı yapılan: Cemre. - 31 Aralık 2016, 16:00:42
CMSIS-DSP kullanabilmek için ille de FPU-DSP birimli MCU (misal STM32F429ZI) mu kullanmak gerekir?
Henüz DSP fonksiyonlarını kullanmayı denemedim ama donanım desteğinin gerekli olmadığını okumuştum bir yerlerde. Ama elbette donanım desteği olması performansı ciddi olarak arttıracaktır.
Gökçe Tağlıoğlu

Cemre.

Alıntı yapılan: Tagli - 31 Aralık 2016, 16:15:01
Henüz DSP fonksiyonlarını kullanmayı denemedim ama donanım desteğinin gerekli olmadığını okumuştum bir yerlerde. Ama elbette donanım desteği olması performansı ciddi olarak arttıracaktır.

Evet incelemek belki DWT ile deneyimlemek cycle saydırmak gerekebilir. Teşekkürler.