본문 바로가기

STM32

[STM32] RTOS

 

1. STM32에서의 RTOS 

우리가 기존 메인함수에서 프로세스를 구현하여 처리한 방식을 None-OS 방식(다양한 기능이 존재하는 운영체제에서 동작하는 것이 아닌 사용자가 직접 작성한 코드가 순차적으로 동작하는 방식)이 아닌 STM32에서 자주 사용되는 OS를 RTOS라고 한다.

None-OS방식은 순차적으로 코드가 처리된다. 함수를 적시에 사용을 해야한다면 사용자는 별도로 코드작성을 통해서 우선순위를 부여하여 구현해야 하는 번거로움이 있다.

하지만 RTOS는 Task를 이용한 작업 스케줄링을 통해서 함수의 동작을 병렬처리를 하도록(사실 직렬 처리이지만 각 Task가 이동하는 시간이 매우 짧아 병렬처럼 느껴진다.) 만들어준다.

RTOS는 실시간 시스템에서 작동하는 운영체제로, 정해진 시간 내에 정확한 결과를 산출하고 응답하는 데 중점을 둔 시스템이다.

이를 쉽게 말하면 우리가 윈도우 10이라는 OS를 사용할 때, 카카오톡으로 채팅을 하면서 음악을 듣는 멀티 테스킹 기능을 쓴다고 가정하자.

None-OS 방식이라면 카카오톡으로 채팅을 처리하고 그 다음 음악이 나오는 순차적 처리를 경험하게 될 것이다.

하지만 RTOS는 빠른 Task 처리 후 다음 Task로 이동하게 되어 우리가 평소에 사용하는 멀티테스킹 기능 구현이 되는 것이다. 

 

이를 STM32에서 사용하는 방법을 알아보자.

먼저 ioc파일에서 FREERTOS 카테고리로 들어간다.

 

해당 경로에서 ADD를 눌러 Task Name을 설정해준다. LEDTask02와 LEDTask03 총 두개를 add한다.

두개의 Task를 add하는 것을 쉽게 이해하고 싶다면, 두 개의 작업을 멀티테스킹으로 구현하는 느낌으로 받아들이면 쉬울 것이다.

 

 

Systick과 충돌이 일어나지 않게 하기위해 위 경로에서 Timebase Source를 TIM1로 설정해준다.

 

그 후 저장하여 코드를 generate시킨다.

 

코드를 genrate를 하면 방금 전 추가했던 Task들을 확인할 수 있다.

 

일반적으로 RTOS에서는 동작이 메인함수에서 진행되는 것이 아니라 각 Task에서 진행되는 것을 염두해두어야한다.

이렇게 osDleay함수를 이용하여 전달 인자로 1 값을 주면 1ms마다 각 테스크가 동작한다. 하지만 테스크에 종속된 함수의 처리 시간이 길어질수록 다음 테스크로 넘어가는 시간이 길어지게 되므로 주의하자.

 

다시 ioc파일로 돌아와서 해당 부분을 Enable시켜준다. 그리고 다시 저장하여 코드를 generate시킨다.

 

코드를 generate시켰다면 Src폴더에 위와 같은 c파일이 생성됨을 확인한다.

 

.본격적으로 실습해보자. StartTaskxx함수로 들어와서 원하는 동작을 시켜보자. 각 Task에서 동작을 수행하면 순차적으로 실행되는 것이 아니라, 병렬형태의 Multi Tasking을 구현할 수 있다.

 

Task02에는 LED1번을 500ms마다 토글, Task03에는 LED2번을 200ms마다 토글한다.

 

**[추가] 함수포인터를 이용한 RTOS 동작해보기**

 

기존 프로젝트를 이용하여 어떻게 Multi Tasking을 구현하는지 간단하게 실습해보자.

Timebase를 TIM1로 만들어준다.

스레드 3개를 만든다.

Enable로 만들어준다. 그 후 코드를 generate한다.

 

생성된 코드의 main.c에서 스레드와 관련된 이름과 stack 사이즈를 확인할 수 있다.

기존 코드에서 사용하던 TIMER10번의 타이머를 설정해준다.

 

실행하길 원하는 함수를 각각 스레드에 입력하고 딜레이를 적절하게 설정해준다. osDelay에 60을 입력하면 60ms마다 한번 씩 Task04스레드가 실행된다. 이 딜레이가 없으면 해당 Task에서 무한 루프를 돌게되므로 주의하자.

 

메인함수에서 함수 포인터를 쓸 것이므로 함수 포인터를 각각 선언한다.

메인 함수에서 함수포인터를 호출한다.

함수 포인터의 0번째 배열인 button0_status_check 함수가 실행될 때, 함수 포인터의 배열 index인 func_num을 1로 set해준다. 이유는 다음 함수의 스레드로 넘어가기 위해서 index를 무조건 바꿔주어야한다.

calculator의 함수 포인터의 다음 index는 없다(왜냐하면 함수 포언터 *fp에서는 두 개의 포인터만 선언했기 때문에). 따라서 함수 포인터의 가장 첫번째 배열(0번)button0_status_check가 있는 이전 스레드로 넘겨주어야하기 때문에   func_num을 0으로 set해준다. 

 

이러한 방식으로 짧은 시간에 계속 함수끼리 왔다갔다 하면서 Context Switching을 구현할 수 있다. 

결국 이 방식을 이용하게 되면 우리 눈에는 동시에 프로그램이 실행되는 것(Multi Tasking)처럼 느껴지게 된다.