임베디드 / ex10 / 우선순위 기반 선점형 RR 스케쥴링 Prioritized Preemptive Round-Robin Scheduling

jjin·2023년 11월 15일
0

1. Exercise Objective

GOAL: Create four tasks and run tasks round robin order by changing the priority of tasks
• Task1: Blink P1 Red LED
• Task2: Blink P2 Red LED
• Task3: Blink P2 Green LED
• Task4: Blink P2 Blue LED

functions


portBASE_TYPE xTaskCreate(pdTASK_CODE pvTaskCode, const char const pcName, unsigned short usStackDepth, void pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pvCreatedTask);

• pvTaskCode: Pointer to the task entry function. Tasks must be implemented to never return (i.e. continuous loop).
• pcName: A descriptive name for the task. This is mainly used to facilitate debugging. Max length defined by tskMAX_TASK_NAME_LEN – default is 16.
• usStackDepth: The size of the task stack specified as the number of variables the stack can hold - not the number of bytes. For example, if the stack is 16 bits wide and usStackDepth is defined as 100, 200 bytes will be allocated for stack storage.
• pvParameters: Pointer that will be used as the parameter for the task being created.
• uxPriority: The priority at which the task should run. Systems that include MPU support can optionally create tasks in a privileged (system) mode by etting bit portPRIVILEGE_BIT of the priority parameter. For example, to create a rivileged task at priority 2 the uxPriority parameter should be set to ( 2 | portPRIVILEGE_BIT ).
• pvCreatedTask: Used to pass back a handle by which the created task can be referenced.
• pdPASS: If the task was successfully created and added to a ready list, otherwise an error code defined in the file errors.h

3. Discussion & Conclusion

  • Task: 태스크는 return 하지 않고 무한반복한다.
  • FreeRTOS Multitasking 의 Priority assignment: 하나 이상의 Task 가 같은 priority 를 가질 수 있으며 이 경우 1 RTOS tick 단위로 RR scheduling 에 의해 실행된다. (13p)
  • Task 우선순위가 큰 것이 우선으로 실행된다.
    전제: TaskN 의 우선순위가 M 일 때 TaskN(M)이라고 표기하고, 별다른 표기가 없이 나열된 우선순위는 각각 Task1, 2, 3, 4 의 우선순위라고 가정한다.

예시 답안

설명

이 예시 답안에서 태스크 우선순위는 항상 2, 3, 4, 5 중 하나이다.

5, 4, 3, 2의 초기 우선순위를 가지는 Task1, 2, 3, 4. Task1 실행 후 setPriority(1)이 실행된다.

high = 1
{
 i = 0
 index = (1 + 0) % 4
 vTaskPrioritySet(taskHandles[1], 5 - 0) // Task2(4) -> (5).
}
**Task1, 2 모두 5의 우선순위를 가지므로 예상과 다르게 1 Tick씩 번갈아 수행된다.**
{
 i = 1
 index = (1 + 1) % 4
 vTaskPrioritySet(taskHandles[2], 5 - 1) // Task3(3) -> (4).
}
Task2의 LED 점등과 1 Tick 씩 번갈아 수행된다.
{
 i = 2
 index = (1 + 2) % 4
 vTaskPrioritySet(taskHandles[3], 5 - 2) // Task4(2) -> (3).
}
Task2의 LED 점등과 1 Tick 씩 번갈아 수행된다.
{
 i = 3
 index = (1 + 3) % 4
 vTaskPrioritySet(taskHandles[0], 5 - 3) // Task1(5) -> (2).
}
Task2의 LED 점등과 1 Tick 씩 번갈아 수행되다 드디어 Task1가 최하순위가 되었다.

내 답안

/* Driver configuration */
#include <ti/devices/msp432p4xx/inc/msp.h>
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>
#include <ti/drivers/Board.h>

/* RTOS header files */
#include <FreeRTOS.h>
#include <task.h>
#include <semphr.h>

/* function prototypes */
void Task1( void *pvParameters );
void Task2( void *pvParameters );
void Task3( void *pvParameters );
void Task4( void *pvParameters );

/* global variables */
TaskHandle_t task1Handle, task2Handle, task3Handle, task4Handle;

void main(void)
{
 /* Configuring S1 & S2 buttons / Red LED & RGB LED in mainboard */
 P1->DIR = BIT0;
 P1->DIR &= ~(BIT1|BIT4);
 P2->DIR |= 1<<2 | 1<<1 | 1<<0;
 P1->REN |= (BIT1|BIT4);
 P1->OUT |= (BIT1|BIT4);
 P2->OUT = 0x00;
 xTaskCreate( Task1, /* The function that implements the task. */
 "Task 1", /* The text name assigned to the task - for debug only as it is not 
used by the kernel. */
 configMINIMAL_STACK_SIZE,/* The size of the stack to allocate to the task. */
 ( void * ) 0, /* The parameter passed to the task - just to check the 
functionality. */
 4, /* The priority assigned to the task. */
 &task1Handle); /* The task handle is not required, so NULL is passed. */
 xTaskCreate( Task2, "Task 2", configMINIMAL_STACK_SIZE, ( void * ) 0, 3, &task2Handle);
 xTaskCreate( Task3, "Task 3", configMINIMAL_STACK_SIZE, ( void * ) 0, 2, &task3Handle);
 xTaskCreate( Task4, "Task 4", configMINIMAL_STACK_SIZE, ( void * ) 0, 1, &task4Handle);
 
 /* Start the tasks and timer running. */
 vTaskStartScheduler();
 
 while (1)
 {
 }
}

void Task1( void *pvParameters )
{
 int i;
 while (1)
 {
 P1->OUT = BIT1|BIT4 | BIT0;
 for (i=0;i<100000;i++);
 P1->OUT = BIT1|BIT4;
 for (i=0;i<100000;i++);
 vTaskPrioritySet(task1Handle, 0);
 }
}

void Task2( void *pvParameters )
{
 int i;
 while (1)
 {
 P2->OUT = BIT0;
 for (i=0;i<100000;i++);
 P2->OUT = 0;
 for (i=0;i<100000;i++);
 vTaskPrioritySet(task2Handle, 0);
 }
}

void Task3( void *pvParameters )
{
 int i;
 while (1)
 {
 P2->OUT = BIT1;
 for (i=0;i<100000;i++);
 P2->OUT = 0;
 for (i=0;i<100000;i++);
 vTaskPrioritySet(task3Handle, 0);
 }
}

void Task4( void *pvParameters )
{
 int i;
 while (1)
 {
 P2->OUT = BIT2;
 for (i=0;i<100000;i++);
 P2->OUT = 0;
 for (i=0;i<100000;i++);
 vTaskPrioritySet(task1Handle, 4);
 vTaskPrioritySet(task2Handle, 3);
 vTaskPrioritySet(task3Handle, 2);
 vTaskPrioritySet(task4Handle, 1);
 }
}

2. Implementation

요약: Task 1, 2, 3, 4 의 우선순위를 각각 4, 3, 2, 1 로 초기화하고, 방금 수행된 Task 는 최하 우선순위인 0 을 가지도록 하였다. 그리고 Task4 의 마지막 부분에 0, 0, 0, 1 이었던 우선순위를 다시 4, 3, 2, 1 로 설정해주었다.

실행: 초기 우선순위 4, 3, 2 에 따라 Task1, 2, 3 이 순서대로 실행된다. 실행 완료된 Task1, 2, 3 은 모두 0 의 우선순위를 가진 상태이다. 이후 Task4(1)가 실행된다.
Task4 의 마지막 부분에서 Task1(0)이 Task1(4)가 됨에 따라 Task4(1)의 실행을 멈추고 Task1(4)를 수행한 후 스스로 Task1(0)으로 바꾸어 다시 Task4(1)이 실행된다.
이후 Task2(3)이 되어 실행 후 Task2(0)이 되어 다시 Task4(1)이 실행된다.
이후 Task3(2)이 되어 실행 후 Task3(0)이 되어 다시 Task4(1)이 실행된다.
Task4 실행 후에는 return 하지 않고 무한 반복하는데 현재 우선순위가 0, 0, 0, 1 이므로 Task4 의 처음 부분부터 이를 반복한다.

profile
진짜

0개의 댓글