STM32/STM32_RTOS

STM32 RTOS 알아보기 3편(xQueueSendFromISR,xQueueReceiveFromISR)

원원 2024. 10. 4. 21:49

안녕하세요. 오늘은 저번 2편에서 Queue에서 task끼리 send/receive를 했었는데 이번에는 ISR이랑 해보겠습니다.
ISR에서 send/receive를 할때는 함수명이 다르고 기존의 함수명에 FromISR이 붙습니다. 다른 이유는 ISR은 짧은시간안에 실행되어야 하며 다른 태스크나 ISR에 의해 중단되지 않아야 합니다. 이로 인해 ISR에서 사용하는 함수들은 블로킹이 없고 간단하고 빠르게  동작됩니다.

 

*xQueueSendFromISR함수
*xQueueSendFromISR함수BaseType_t xQueueSend( QueueHandle_t xQueue, const void BaseType_t *pxHigherPriorityTaskWoken );
ISR함수에서 호출되어 큐에 데이터를 저장하는 함수입니다.
xQueue : 큐 핸들
pvItemToQueue : 큐에 보낼 아이템
pxHigherPriorityTaskWoken  : ISR에서 사용되는 테스크 전환 여부를 결정하는 변수

#include <stdio.h>
#include "cmsis_os.h"
#include "main.h"
#include "FreeRTOS.h"
#include "task.h"

void task1(void *pvParameters);
void task2(void *pvParameters);
QueueHandle_t xQueue;

void myTask()
{
  xQueue = xQueueCreate(5, sizeof(uint16_t));
  xTaskCreate(task2, "Task2", 256, NULL, 1, NULL);
}



void task2(void *pvParameters)
{
  uint16_t i=0;
  while(1)
  {
    if(xQueueReceive(xQueue, &i, 2000) == pdPASS)
    {
      printf("Queue received : 0x%x \n",i);
    }
    else
    {
      printf("Queue received FAIL\n");
    }
    vTaskDelay(10);
  }
}


void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  if(GPIO_Pin == BTN1_Pin)
  {
    printf("BTN1 clicked\n");
    xQueueSendFromISR(xQueue, &GPIO_Pin, &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
  }
  else if(GPIO_Pin == BTN2_Pin)
  {
    printf("BTN2 clicked\n");
    xQueueSendFromISR(xQueue, &GPIO_Pin, &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
  }
}

BTN1,BTN2은 인터럽트이고 버튼을 클릭하면 Queue에 데이터를 보내게되고 Queue를 받아서 표시해줍니다



*xQueueReceiveFromISR함수
BaseType_t xQueueReceiveFromISR(QueueHandle_t xQueue, BaseType_t *pxHigherPriorityTaskWoken);
xQueue :큐 핸들
pvBuffer: 큐에서 읽어서 저장될 변수
pxHigherPriorityTaskWoken  : ISR에서 사용되는 테스크 전환 여부를 결정하는 변수

#include <stdio.h>
#include "cmsis_os.h"
#include "main.h"
#include "FreeRTOS.h"
#include "task.h"

void task1(void *pvParameters);
void task2(void *pvParameters);
QueueHandle_t xQueue;

void myTask()
{
  xQueue = xQueueCreate(5, sizeof(uint16_t));
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  uint16_t i=0;
  if(GPIO_Pin == BTN1_Pin)
  {
    printf("BTN1 clicked\n");
    xQueueSendFromISR(xQueue, &GPIO_Pin, &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
  }
  else if(GPIO_Pin == BTN2_Pin)
  {
    printf("BTN2 clicked\n");
    printf("Queue count %u \n",uxQueueMessagesWaitingFromISR(xQueue));
    if(xQueueReceiveFromISR(xQueue, &i, &xHigherPriorityTaskWoken))
    {
      printf("Queue received : 0x%x \n",i);
    }
    else
    {
      printf("Queue received FAIL\n");
    }
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
  }
  printf("\n");
}

BTN1을 클릭하면 큐에 데이터를 보내고 BTN2를 클릭하면 큐에서 데이터를 받습니다. 만약 데이터가 있다면 Qeue received를 출력하고, 데이터가 없다면 Qeue received FAIL을 출력합니다.
다음 글 에서는 portYIELD_FROM_ISR(xHigherPriorityTaskWoken); 관련된 내용과 우선순위에 대해 알아보겠습니다.


소스코드(Commits: Queue TEST2(ISR))
https://github.com/yhunterr/STM32_RTOS_STUDY/commits/main/