질문&답변
섹션7에서 개념적 궁금증
Task Notification 예를 들어 아래처럼 Notification이 4번 발생했다고 가정하겠습니다. xTaskNotifyGive(receiveHandler); xTaskNotifyGive(receiveHandler); xTaskNotifyGive(receiveHandler); xTaskNotifyGive(receiveHandler); xTaskNotifyGive는 대상 Task의 notification Value를 1씩 증가시킵니다. 따라서 대상 Task가 중간에 실행되지 않았다면 내부 값은 다음처럼 변합니다. 초기 값 : Notification count = 0; 첫 번째 xTaskNotifyGive count 0 -> 1; 두 번째 xTaskNotifyGive count 1 -> 2; 세 번째 xTaskNotifyGive count 2 -> 3; 네 번째 xTaskNotifyGive count 3 -> 4; 즉, 4번의 Notification이 발생했다는 것을 FreeRTOS가 별도의 이벤트 4개로 저장하는 것이 아니라, Notifcation count = 4라는 카운터 하나로 저장합니다. 여기서 출력을 하면 아래와 같습니다. int count = ulTaskNotifyTake(pdFALSE, portMAX_DELAY); printf("received notification %d times\n", count); 여기서 pdFALSE의 의미는 Notifcation count를 하나 감소시키는 것입니다. 그렇기 때문에 출력은 4->3->2->1로 진행이 됩니다. 1->2->3->4로 생각하기 쉬운것은 xTaskNotifyGive()가 실행되는 시점만 보면 실제로 내부 값이 0->1->2->3->4로 증가하기 때문입니다. 하지만 ulTaskNotifyTake()가 호출될 때는 이미 4까지 누적된 상태이고, pdFALSE는 이 값을 하나씩 소비하는 동작입니다. xTaskNotifyGive()는 카운터 증가를, ulTaskNotifyTake(pdFALSE)는 카운터를 하나씩 소비한다고 생각하면 이해하기 쉽습니다. xSemaphoreGive / Context switching 결론부터 말씀드리면 xSemaphoreGive()로 Block 상태의 더 높은 우선순위 Task가 준비되면, preemptive scheduling이 활성화된 ESP-IDF 환경에서는 더 높은 우선순위 Task로 전환될 수 있습니다. ESP-IDF의 기본 FreeRTOS 설정은 configUSE_PREMMPTION = 1이고 time slicing도 활성화되어 있습니다. 다만 이에 대한 조건이 중요합니다. 예를 들어 Task 2개가 있다고 가정하겠습니다. Task_A / Priority = 1 Task_B / Priority = 2 Task B가 semaphore를 기다리고 있습니다. void Task_B(void *arg) { while (true) { xSemaphoreTake(sem, portMAX_DELAY); printf("B\n"); } } 현재 상태는 아래와 같습니다. Task_A : Running / Priority = 1 Task_B : Blocked / Priority = 2 이 때 TASK A 아래를 실행하고 있습니다. void Task_A (void *arg) { while (true) { printf("A1\n"); xSemaphoreGive(sem); printf("A2\n"); } } xSemaphoreGive가 호출되면 semaphore를 기다리던 Task B가 Blocked에서 Ready상태가 됩니다. 그 순간 Ready Task를 비교하면 아래와 같습니다. 현재 실행 중 Task A : Priority 1 새로 Ready Task B : Priority 2 FreeRTOS는 preemptive scheduler이므로 높은 Prioirty 2 Task가 Priority 1 Task를 선점할 수 있습니다. FreeRTOS 스케쥴링 설명에서도 높은 우선순위 Task가 Ready가 되면 현재 Task를 preempt할 수 있다고 나와있습니다. FreeRTOS scheduling (single-core, AMP and SMP) - FreeRTOS™ 따라서 실행 순서는 아래와 같이 됩니다. 1. Task A : printf("A1"); // A1 출력 2. xSemaphoreGive() 3. Task B : Blocked -> Ready 4. Priority 비교 // Task_B(2) > Task_A(1) 5. Context Switch 발생 6. Task B Run : printf("B"); 7. B가 다시 Blocked // 또는 Yield 8. Task A : printf("A2"); 즉 출력이 A1, B, A2가 나오면서 Task_A에 있던 xSemaphoreGive의 다음 줄의 printf("A2")보다 B가 먼저 실행되는 상황이 발생할 수 있습니다.
- 좋아요수
- 0
- 댓글수
- 1
- 조회수
- 40





