본문 바로가기
DSP, MCU/STM32 (ARM Cortex-M)

STM32 ] FreeRTOS 사용해보기

by eteo 2022. 8. 8.

정의

RTOS는 실시간 시스템을 위해 개발된 운영체제로, 멀티태스킹 환경에서 Task 처리시간을 일관되게 유지하기 위한 용도로 사용한다. RTOS는 시분할 시스템 하에서 우선순위 기반 스케줄링을 통해 우선순위가 높은 task가 먼저 작업을 처리할 수 있게 함으로써 구현한다.

 

참고. 스케줄링 : 프로세스들에게 CPU 등 자원을 배정하는 것을 말함.

 

 

설정

 

Interface는 CMSIS_V2로 선택한다.

 

CMSIS는 Cortex Microcontroller Software Interface Standard의 약자로 ARM Cortex 시리즈끼리의 호환성 및 이식성 증대를 위해 ARM사에서 정한 소프트웨어를 말한다.

 

그리고 CMSIS_RTOS 는 ARM사에서 RTOS의 API를 추상화해서 RTOS의 종류가 달라져도 동일한 API로 사용할 수 있도록 제공되는 인터페이스이다.

 

 

 

나머지 Configuration은 그대로 두고 Code Generation을 누르면 다음과 같은 경고창이 뜬다.

 

 

나와있는 내용대로 수정해 주자.

 

 



SYS에서 Timbase Source를 Systick이 아닌 TIM4로 설정했다.

 

 

FreeRTOS Advanced Setting에서 USE_NEWLIB_REENTRANT를 Enable 한다.

 

 

 

다음 Code Generation을 누르면 프로젝트 내에 Middlewares -  Third_Party - FreeRTOS 의 소스파일이 들어간 것을 확인할 수 있다.

 

 

Main.c

 osKernelInitialize() 라는 스케줄러를 초기화하는 함수가 있고 그아래 MX_FREERTOS_Init() 를 따라 들어가보면

 

 

아래와 같이 default Task 가 샘플로 생성된 것을 확인할수 있다.

 

/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
  .name = "defaultTask",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};

/* Private function prototypes -----------------------------------------------*/

//...

void MX_FREERTOS_Init(void) {

  defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);

}

//...

/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN StartDefaultTask */
  /* Infinite loop */
  for(;;)
  {
    osDelay(1);
  }
  /* USER CODE END StartDefaultTask */
}

/* Private application code --------------------------------------------------*/

 

 

이 Task는 CubeMX툴에서 디폴트로 만들어져있던 것이다.

 

 

이 아래 default Task 와 같은 속성으로 Task를 두 개 더 만들어 준다.

 

 

 

Code Generation 하면 다음과 같이 코드가 생성된 것을 알 수 있다.

 

 

위에서 Task 핸들러를 만들고 Task_attributes 를 통해 속성을 설정해둔다.

 

 

osThreadNew 함수를 통해 Task를 위에서 설정한 attributes 대로 생성하며 반환값을 핸들러에 넘긴다.

 

 

 

Task02와 Task03의 내용 수정

void StartTask02(void *argument)
{
  /* USER CODE BEGIN StartTask02 */
  /* Infinite loop */
  for(;;)
  {
	  HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7);
	  osDelay(500);
  }
  /* USER CODE END StartTask02 */
}

//...

void StartTask03(void *argument)
{
  /* USER CODE BEGIN StartTask03 */
  /* Infinite loop */
  for(;;)
  {
	  HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_14);
	  osDelay(200);
  }
  /* USER CODE END StartTask03 */
}

LED와 연결된 PB0, PB7, PB14 를 GPIO Output으로 잡았다.

 

 

 

 

 

 

참고 : https://www.youtube.com/watch?v=N-dZEJGsA6A 

https://blog.naver.com/0ljy0