tree 생략
책에서 10장까지 Round Robin Algorithm으로 구현했고
Priority algorithm 은 단순 소개로 넘어갔지만 개인적으로 한번 구현 해 보았다.
KernelTcb_t 구조체
typedef struct KernelTcb_t
{
uint32_t sp;
uint8_t* stack_base;
uint32_t priority;
uint32_t TaskId;
}KernelTcb_t;
우선순위 스케줄러 알고리즘을 구현 할 거기에 priority 와 TaskId를 추가한다.
Task Create 함수에 parameter로 priority를 받는다.
TaskId는 스케줄러 알고리즘을 통해 우선순위가 가장 높은 Task를 호출 하기 위해 사용한다.
(Priority 는 숫자가 가낭 낮을수록 우선순위가 높다)
Kernel_task_create
uint32_t Kernel_task_create(KernelTaskFunc_t startFunc, uint32_t priority)
{
KernelTcb_t* new_tcb = &sTask_list[sAllocated_tcb_index++]; //new_tcb의 주소값 = sTask_list의 주소값
if (sAllocated_tcb_index > MAX_TASK_NUM)
{
return NOT_ENOUGH_TASK_NUM;
}
new_tcb->priority = priority;
new_tcb->TaskId = sAllocated_tcb_index -1;
KernelTaskContext_t* ctx = (KernelTaskContext_t*)new_tcb->sp;
ctx->pc = (uint32_t)startFunc;
return (sAllocated_tcb_index - 1); //29line에서 ++해줬으므로 다시 -1 해준다.
}
Kernel_task_create 함수에서는 Priority 가 추가되었으며 생성 될때 argument로 값을 받는다.
받은 argument를 new_tcb -> priority 에 저장한다.
TaskId 는 sTask_list에서 자신이 몇번째 배열에 있는지 확인하는 변수이다.
Scheduler_priority_algorithm
//-------------------------변경 전 코드---------------------------------
static KernelTcb_t* Scheduler_priority_algorithm(void)
{
for(uint32_t i = 0; i < sAllocated_tcb_index; i++)
{
KernelTcb_t* pNextTcb = &sTask_list[i];
if (pNextTcb != pNextTcb)
{
if (pNextTcb -> priority <= sCurrent_tcb -> priority);
{
return pNextTcb;
}
}
}
return sCurrent_tcb;
}
//---------------------------------------------------------------------_
static KernelTcb_t* Scheduler_priority_algorithm(void)
{
KernelTcb_t* pCurrentTcb = &sTask_list[0];
for(uint32_t i = 1; i < sAllocated_tcb_index; i++)
{
KernelTcb_t* PrepareTcb = &sTask_list[i];
if(pCurrentTcb != PrepareTcb)
{
if(pCurrentTcb -> priority > PrepareTcb -> priority)
{
pCurrentTcb = PrepareTcb;
}
}
else
{
putstr("Task Compare fail#01");
while(true);
}
}
//--------우선순위가 같을 시 RoundRobin algorithm 처럼 동작하기 위한 코드---------
KernelTcb_t* PrepareTcb = &sTask_list[Compare_tcb_index++];
Compare_tcb_index %= sAllocated_tcb_index; //compare_tcb_index 값이 task_list의 maximum이 넘지 않게 나머지 연산을 해준다.
if(pCurrentTcb -> priority == PrepareTcb -> priority)
{
pCurrentTcb = PrepareTcb;
}
sCurrent_tcb_index = (pCurrentTcb -> TaskId); //현재 돌고 있는 Task의 Tcb는 PrepareTcb로 바꿨으므로 TaskId도 수정한다.
return pCurrentTcb;
}
변경전 코드를 보면 for 문을 통해 sTask_list 0번째 Task를 호출 한 다음 현재 실행하고 있는 Task의 우선순위와 비교해서 priority 가 같거나 낮으면 비교한 Task를 return 하여 실행한다.
이 같은 경우 sTask_list 의 전체 Task를 비교를 못하고 priority가 실행하고 있는 priority 보다 낮기만 하면 즉시 return 하기 때문에 Task가 많고 프로그램이 실행 중 우선순위가 변경 되었을 때 catch 하기 힘들 수 있어 알고리즘을 조금 변경하였다.
변경 후 코드를 보면
pCurrentTcb를 sTask_list에 가장 첫번째 Task를 불러 온다.
for 문에서 다음 Task(PrepareTcb)를 호출한 다음, priority가 pCurrentTcb 보다 낮으면 pCurrentTcb를 PrepareTcb로 업데이트, 그렇지 않으면 pCurrentTcb는 유지하고 다음 Task(PrepareTcb)를 호출하여 또 비교한다.
이렇게 모든 Task를 비교하여 priority가 가장 낮은 task를 불러온 다음 priority 가 같은 Task가 있는지 Check 하여
있으면 Task가 다음 scheduler를 호출 할때마다 순서대로 Switching을 하게 된다.
-> (모든 Task 순위가 똑같으면 Round Robin algorithm 으로 동작한다,)
Kernel_init
static void Kernel_init(void)
{
uint32_t taskId;
taskId = Kernel_task_create(User_task0,4);
if (NOT_ENOUGH_TASK_NUM == taskId)
{
putstr("Task0 creation fail\n");
}
taskId = Kernel_task_create(User_task1,1);
if (NOT_ENOUGH_TASK_NUM == taskId)
{
putstr("Task1 creation fail\n");
}
taskId = Kernel_task_create(User_task2,2); //우선순위가 가장 낮음 Task#2
if (NOT_ENOUGH_TASK_NUM == taskId)
{
putstr("Task2 creation fail\n");
}
taskId = Kernel_task_create(User_task3,2); //우선순위가 가장 낮음 Task#3
if (NOT_ENOUGH_TASK_NUM == taskId)
{
putstr("Task3 creation fail\n");
}
taskId = Kernel_task_create(User_task4,3);
if (NOT_ENOUGH_TASK_NUM == taskId)
{
putstr("Task4 creation fail\n");
}
Kernel_start();
}
이전 글 Kernel_init에서 Task를 2개 더 추가하였다.
Task의 우선순위는 Task3이 가장 낮으므로 Scheduler를 위한 Task0이 처음에 실행 되고 Task 3만 계속 실행 된다.
만약 우선순위가 모두 같은 경우 RoundRobin 처럼 Task가 실행 된다.
'Firmware > RTOS' 카테고리의 다른 글
임베디드 OS 개발 프로젝트 15(메시징) (0) | 2020.03.15 |
---|---|
임베디드 OS 개발 프로젝트 14(Event 처리) (0) | 2020.03.11 |
임베디드 OS 개발 프로젝트 12(Context Switching - 2) (3) | 2020.03.09 |
임베디드 OS 개발 프로젝트 11(Context Switching - 1) (0) | 2020.03.08 |
임베디드 OS 개발 프로젝트 11(Scheduler) (0) | 2020.03.08 |