HAL UART Recieve kesme sorunu

Başlatan Mucit23, 14 Kasım 2017, 21:52:14

Mucit23

Seamlar

STM32F103C8 çipimde uart'ı kurdum kesme ile veri almam gerekiyor. Ayarları vs yaptım uart çalışıyor veri gönderip alabiliyorum. Kesme ile ilgili bir sorum olacak.

USART1 kesme vektörü olarak stm32f1xx_it.c dosyası içerisine aşağıdaki fonksiyonu tanımladım7
void USART1_IRQHandler()
{
   HAL_UART_IRQHandler(&huart1);
}


STM32 çipime uart üzerinden bir veri gönderdiğimde kesme buraya düşüyor. Aynı zamanda aşağıdaki fonksiyonu tanımladım

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	 HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
}


aynı şekilde veri geldiği zaman bu fonksiyonada kesme düşmesi lazım ama buraya gelmiyor. Bu fonksiyon weak olarak tanımlandığı için asıl proje kodlarımın yerde tanımlayıp kesme içinde yapmam gerekenleri yapabiliyorum.Ama nedense kesme buraya gelmiyor. Sorun ne olabilir. Callback fonksiyonumu yanlış acaba?

Tagli

#1
HAL kullanmıyorum ama bir dönem biraz araştırmıştım. Bu yüzden yazacaklarım tamamen yanlış olabilir.

Hatırladığım kadarıyla kesme ile alma işlemi için önce başka bir fonksiyon çağırman gerekiyor. Kabaca "Ben kesme ile n sayıda byte almak istiyorum, ona göre kendini ayarla" diyorsun. n adet byte gelince de o tanımlanmış olan callback fonksiyonuna düşüyor.

Sistemi değiştirdiler mi bilmiyorum ama bu hali benim hiç hoşuma gitmedi. İnternette aratınca şikayet eden başkalarının da olduğunu görmek mümkün. Seri alımda genelde kaç byte geleceğini önceden bilemeyiz, o yüzden bu kullanım çok mantıksız. İnsanlar n = 1 ile kurmayı denemişler ama tabi hız artınca arada byte'lar kaçmaya başlıyor.

Belki saçma gelecek ama, sırf bu yüzden "Böyle saçmalık mı olur? Kullanmıyorum lan bu HAL mıdır nedir o şeyi!" diyerek STM32 öğrenmeye başladığım daha ilk günlerde HAL'ı reddedip doğrudan CMSIS ve register'lar ile kod yazmaya başladım.
Gökçe Tağlıoğlu

Mucit23

Hocam anlamadım bende durumu.

Bende dediğiniz gibi bir buffer ile 1 byte alacam şeklinde Uart ayarımı yaptım.

if(HAL_UART_Receive_IT(&huart1, (uint8_t *)rx_data, 1) != HAL_OK)
  {
    Error_Handler();
  }


Şimdi veri gönderdiğimde USART1_IRQHandler fonksiyonuna kesme düştüğü gibi HAL_UART_RxCpltCallback fonksiyonunada kesme düşüyor. Ama sadece bir kere düşüyor ilginç bir şekilde. Sonrasında yine veri gönderdiğimde artık kesme oluşmuyor.  Bi anlayabilsek şu hal librar'yi fena değil aslında.

Tagli

Callback'e ilk düştüğünde HAL_UART_Receive_IT görevini tamamlamış oluyor. Ondan sonra bu fonksiyonu aynı şekilde tekrar çağırman lazım, "Ben 1 byte daha almak istiyorum" anlamında.

USART1_IRQHandler zaten donanımsal (low level diyebileceğimiz) bir fonksiyon. Oraya düşmesi sanırım kaçınılmaz.
Gökçe Tağlıoğlu

Mucit23

Sanırım DMA kullanmam gerekecek. Çok şey istemiyorum aslında Boyutu belli olmayan veriler geliyor. Bunları sırayla alıp işleyeceğim diziye yerleştireceğim vs.


İşin ilginci USART1_IRQHandler fonksiyonunada sadece bir defa kesme geliyor. Anlamadım.


Emin olmak için __HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE); fonksiyonu ile RX kesmesini aktif ettim. Ama
HAL_UART_Receive_IT(&huart1, (uint8_t *)rx_data, 1) fonksiyonunu kullanmadım Dolayısıyla USART1_IRQHandler fonksiyonuna her veri geldiğinde kesme düşmesi lazım. Ama olmuyor. Acaba Uart-DR registerinden veriyi okumamımı bekliyor?

Gereksiz olacak ama DMA kullanıp 1 byte veri aktarıp kesme oluşturması için uğraşacağım.



yldzelektronik

Bir kez callback fonksiyonuna giriyor bir daha girmiyorsa callback içinde interruptı tekrar açın. hall lib kullandığınızda handler içinde kesmeyi kapatıyor.
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

Mucit23

Ne diye kapatıyor anlamış değilim. Biraz alt seviyelere inip kod takibi yapayım.

Evet HAL_UART_RxCpltCallback içinde tekrar kesme yi açınca düzeldi. Sürekli kesme oluşuyor

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if(HAL_UART_Receive_IT(&huart1, (uint8_t *)rx_data, 1) != HAL_OK)
  {
    Error_Handler();
  }
}


Fakat aklıma yatmadı. Bu şekilde yapınca arka planda gelen verileri alıp buffere vs yerleştirmek için bir sürü kod çalışacak. Halbuki benim verim sadece 1 byte. Hal library beni DMA kullanmaya teşvik ediyor gibi.

Mucit23

Evet DMA ile sorunu çözdüm. 1 Byte veri aktarımı yapılıyor. Belkide DMA kullanımı gereksiz ama benim DMA Kanal 5 zaten boştaydı. Şimdi HAL_UART_RxCpltCallback fonksiyonunu DMA çağırıyor. UART kesmelerini tamamen kapattım. DMA TC kesmesi aktif sadece.

Init kodlarımı buraya ekleyeyimde belki birine lazım olur.

/**
  ******************************************************************************
  * File Name          : USART.c
  * Description        : This file provides code for the configuration
  *                      of the USART instances.
  ******************************************************************************
  *
  * COPYRIGHT(c) 2016 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "usart.h"
#include "stm32f1xx_hal.h"

UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_rx;

char rx_data[1];
char rx[10];
/* USART1 init function */

void MX_USART1_UART_Init(void)
{

  huart1.Instance = USART1;
  huart1.Init.BaudRate = 9600;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  HAL_UART_Init(&huart1);
	
  if (HAL_UART_Receive_DMA(&huart1, (uint8_t *)rx_data, 1) != HAL_OK)
  {
    /* Transfer error in reception process */
    Error_Handler();
  }
}


void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(huart->Instance==USART1)
  {
    /* Peripheral clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();
    __HAL_RCC_DMA1_CLK_ENABLE();
    /**USART1 GPIO Configuration    
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
		
		/* Configure the DMA handler for reception process */
		hdma_rx.Instance                 = DMA1_Channel5;
		hdma_rx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
		hdma_rx.Init.PeriphInc           = DMA_PINC_DISABLE;
		hdma_rx.Init.MemInc              = DMA_MINC_DISABLE;
		hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
		hdma_rx.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
		hdma_rx.Init.Mode                = DMA_CIRCULAR;
		hdma_rx.Init.Priority            = DMA_PRIORITY_HIGH;

		HAL_DMA_Init(&hdma_rx);

		/* Associate the initialized DMA handle to the the UART handle */
		__HAL_LINKDMA(huart,hdmarx, hdma_rx);
	
		/* NVIC configuration for DMA transfer complete interrupt (USARTx_RX) */
		HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0);
		HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
		
  }
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
}

/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/


stm32f1xx_it.c dosyasınada aşağıdaki DMA kanal 5 kesme vektörü eklenecek.
void DMA1_Channel5_IRQHandler(void)
{
    HAL_DMA_IRQHandler(huart1.hdmarx);
}


Biraz inceleyince HAL library'nin çalışması anlaşılabiliyor. DMA Circular modda çalıştığı zaman kesme sürekli aktif tutuluyor.