inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

FreeRTOS 프로그래밍

소스코드 분석-부트의 원리

taskr간 context switching 관련하여 질문이 있습니다.

해결된 질문

442

research

작성한 질문수 3

2

안녕하세요 강사님.

 

컨텍트 스위칭 관련하여 궁금한점이 있어 질문드립니다.

아래와 같은 상황에서 우선 순위사 제일 높은 task를 컨텍트 스위칭 전에 cpu 자원을 사용하게 하고 싶습니다.

  1. task1 : 우선 순위 5 (suspend 상태)

  2. task2 : 우선 순위 4

  3. task3 : 우선 선위 4

우선 task2가 실행하던 도중 task1을 resume 하고 바로 portyield를 실행하게 되면 우선 순위가 동일한 task3번이 cpu를 점유하여 일을 처리하다가 컨텍트 스위칭이 발생하게 되면 task1이 cpu를 점유가게 될텐데

 

제가 궁금한건 task2에서 task1을 resume 한 후 컨택트 스위칭이 발생하기 전에 cpu를 task1이 점유하게 하는 방법이 없는지 궁금합니다.

 

감사합니다.

운영체제 임베디드 FreeRTOS

답변 1

0

홍영기

안녕하세요. research님!

요청하신 질문 내용을 세심히 읽어보고, 제 생각을 샘플코드를 작성으로 표현해 보았습니다. 자세한 내용은 이 프로젝트 파일(다운로드)과 아래 그림을 함께 참고해주세요.

TaskMain's PRIO=5, Task1's PRIO=4, Task2's PRIO=4

Task1 이나 Task2 중 어떤 태스크가 임의의 시간에 휴면하고 있는 TaskMain 을 깨웁니다(90라인, 102라인 참고). TaskMain 은 깨어나서 콘솔 화면에 printf("[TaskMain:prio 5]I'm here\n"); 출력 후 정지합니다.

image

아래와 같이 예상된 결과가 나옵니다.

image

질문하신 내용을 다음과 같이 정리해드립니다.

첫째,

우선 순위사 제일 높은 task를 컨텍트 스위칭 전에 cpu 자원을 사용하게 하고 싶습니다

이것은 실현 가능하지 않습니다. 컨텍스트 전환은 태스크가 CPU 를 테이크하기 위한 필수 요소입니다. 그렇기 때문에 HPT(highest priority task) 가 컨텍스트 전환을 생략하고 CPU 를 사용하는 것은 가능하지 않습니다.

둘째,

portyield() 는 단순히 문맥전환을 실행하라는 기능으로만 작동하는 함수인데요. 흔히 사용하는 함수는 아니며, 어플리케이션에서 사용해도 되는 함수이기는 하지만 질문하신 목적으로는 효과를 보실 수가 없습니다. 그리고, 태스크의 운용 원리를 잘못 이해하고 계신 부분이 있는 것 같습니다. 75번 라인에서처럼 휴면하고 있는 HIGHEST PRIO TASK(TaskMain) 은 90라인이나 103라인에서의 vTaskResume() 함수의 효과에 의하여 즉각 다음과 같이 상태 전환이 연쇄적으로 일어납니다. BLOCK -> READY -> RUN. 즉 바로 실행된다는 뜻입니다. 다른 태스크(TASK3)가 TASK2 와 TASK1 사이를 비집고 들어올 수가 없다는 뜻이죠.

질문하신 문장을 교정해보면,

'우선 task2가 실행하던 도중 task1을 resume 하고 바로 portyield를 실행하게 되면 우선 순위가 동일한 task3번이 cpu를 점유하여 일을 처리하다가 컨텍트 스위칭이 발생하게 되면 task1이 cpu를 점유가게 될텐데'

이 문장 표현을 이렇게 바꾸어 봅니다

"우선 task2가 실행하던 도중 task1을 resume 하면 굳이 portyield() 실행 없이도 즉각 task1 이 task2 을 선점하여 실행을 시작한다"

 

0

홍영기

혹시 제가 질문을 잘못 이해하고 답변드린 부분이 있다면 지적해주세요.

0

research

아.. 제가 잘못 생각하고 있었던거 같습니다.

GPIO를 이용하여 오실로스코프로 task간 전환 테스트를 진행하고 있었는데

HAL_Delay(); 함수를 이용하는 바람에 타이밍이 맞지 않아서 잘못 생각하고 있었습니다.

 

RTOS를 설정하면 HAL_Delay(1) 함수가 1ms로 동작하지 않고 1.5~ 2ms 정도로 동작을 하는 바람에 잘못 생각하고 있었습니다.

 

HAL_Delay()를 삭제하고 테스트를 해보니 강사님 말씀대로 task2에서 task1을 resume시키니12us 정도 후에 task1이 실행되는걸 확인하였습니다.

12us 는 강의에서 말씀해주신 task간 전환 비용으로 생각됩니다.

 

#define TASK_MAIN_PRIO   5
#define TASK_TASK1_PRIO  4
#define TASK_TASK2_PRIO  4
#define TASK_TASK3_PRIO  2

TaskHandle_t xHandleMain, xTask1Handle, xTask2Handle;

void TaskMain(void const *pvParameters)
{
  while(1)
  {
    for(uint8_t i=0; i<5; i++)
    {
      HAL_GPIO_TogglePin(GPIO5_BEAD_GPIO_Port, GPIO5_BEAD_Pin);
    }

    vTaskSuspend(xHandleMain);
  }
}

void vTask1(void const *pvParameters)
{
  while(1)
  {
    for(uint8_t i=0; i<5; i++)
    {
      HAL_GPIO_TogglePin(GPIO4_BEAD_GPIO_Port, GPIO4_BEAD_Pin);
    }
    vTaskResume(xHandleMain);
    for(uint8_t i=0; i<5; i++)
    {
      HAL_GPIO_TogglePin(GPIO2_BEAD_GPIO_Port, GPIO2_BEAD_Pin);
    }
  }
}

void vTask2(void const *pvParameters)
{
  while(1)
  {
    HAL_GPIO_TogglePin(GPIO3_BEAD_GPIO_Port, GPIO3_BEAD_Pin);
  }
}


extern "C" {

void vApplicationIdleHook(void)
{
  while(1)
  {
    HAL_GPIO_TogglePin(GPIO2_BEAD_GPIO_Port, GPIO2_BEAD_Pin);
  }
}

}


void userThread(void)
{
 xTaskCreate((TaskFunction_t)TaskMain,
             "TaskMain",
             128,
             NULL,
             TASK_MAIN_PRIO,
             &xHandleMain);

 xTaskCreate((TaskFunction_t)vTask1,
              "vTask1",
              128,
              NULL,
              TASK_TASK1_PRIO,
              &xTask1Handle);

 xTaskCreate((TaskFunction_t)vTask2,
               "vTask2",
               128,
               NULL,
               TASK_TASK2_PRIO,
               &xTask2Handle);

}
  1. 최초 TaskMain이 실행

    • GPIO5 5번 토굴

    • suspend 상태로 진입

  2. TaskMain이 suspend 상태로 진입하였기 때문에 Task1 , Taks2 2개중 1개가 실행되어야함 이때 xtaskCreate()함수에서 task1을 먼저 생성하였기 때문에 task1이 실행됨

  3. task1에서 TaskMain을 resume 하였기 때문에 GPIO4번을 5번 토굴 후 TaskMain 실행

    1. 전환 비용 12us 정도 소요

  4. TaskMain에서 GPIO5번 토굴 후 suspend

  5. Task1이 한번 실행되었기 때문에 다음 순서인 Task2가 실행

  6. Task2 1ms 실행

    1. #define configTICK_RATE_HZ ((TickType_t)1000)

  7. Task1이 resume 작업 후인 GPIO2번 토굴 부터 다시 진행

이렇게 실행이 됩니다.

 

답변 감사합니다.

만약에 포팅을 할때 1년에 한번 잡는 치명적인 문제를 해결하는 코드가 들어갔다고 가정하면

0

57

2

STM32 포팅할 때 STM32 Project가 없음

0

166

2

FreeRTOS 멀티코어 지원안됨?

0

87

2

[소스코드 분석-configUSE_TIME_SLICING] TASK1,2의 우선순위가 동일할 때, configUSE_TIME_SLICING값 변경에 따른 출력 변화

0

85

2

포팅 부탁드립니다!

0

60

1

포팅 부탁드립니다. <NUCLEO-G071RB>

0

67

2

상호배제 후 되지를 않아서 질문드립니다.

0

62

1

수료증 발급 기준 수정 요청

1

72

1

재진입가능여부에 관한 질문

1

67

1

01_TASKMAN프로젝트 디버깅 모드 실패

1

77

2

그러면 malloc/free가 아닌 동적할당자를 써서 메모리를 할당했기떄문에

1

71

2

실행순서

1

77

2

uart 전송중에는 스위칭이 금지되나요?

1

74

2

스택오버플로우 실습 중 stack size 설정 질문

0

81

2

포팅 원합니다.

2

77

2

코루틴 실습질문

1

100

2

TODO 2번 문제

1

141

4

10. 선점형 커널 그림 설명중 우선순위가 반대인 경우에도 Task B가 먼저 수행되나요?

1

82

2

디버거모드에 진입이 안됩니다.

0

176

2

prvExampleTaskHook 함수 호출 부분에 대해 문의드립니다.

0

120

2

보드 STM32H735IG와 강의 호환 여부 문의

1

153

3

[ L152RE ] 원샷 소프트타이머 실행 잘 되시나요?

1

159

2

Deferred Interrupt Processing 샘플 예제 문의 드립니다.

1

121

2

포팅 서비스 부탁드립니다

1

125

2