📄 core.c
字号:
/** * core.c - Task management. * * Copyright (C) 2008 ZhangHu * All rights reserved. * E-MAIL: anmnmnly@gmail.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */#include "include/types.h"#include "include/list.h"#include "include/core.h"#include "include/mem.h"#include "include/sem.h"#include "include/irq.h"extern void device_init(void);/* Initialize all devices */extern void Main(void); /* A routine where users start to write their codes */extern uword_t int_cnt; /* The number of interruption nesting */extern word_t int_flag; /* Interruption flag */static tcb_t idle_tcb; /* TCB space of idle task */static stk_t idle_stk[IDLE_TASK_STACK_SIZE]; /* Stack space of idle task */static tcb_t init_tcb; /* TCB space of initial task */static stk_t init_stk[INIT_TASK_STACK_SIZE]; /* Stack space of initial task */static lword_t idle_cnt; /* Records the number of times of idle task */static list_t ptask[MAX_PRIO]; /* Ready queue */static list_t psleep; /* Sleep queue */static list_t pdelay; /* Delay queue */static list_t *pglobal; /* A temporary pointer used by scheduler() */static uword_t highprio; /* The hightest priority */static list_t task; /* The head of all tasks chain */static uword_t sysclock; /* System clock count */tcb_t *pnewtcb; /* Pointer to the TCB of the next running task */tcb_t *pcurtcb; /* Pointer to the TCB of running task *//* The following variables and arrays used to find out * the highest priority in all tasks. */static uword_t prio_rdy_grup;static uword_t prio_rdy[READY_NUM];const uword_t prio_mask[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};const uword_t prio_decision[] = { 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00-0x0F */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00-0x1F */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00-0x2F */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00-0x3F */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00-0x4F */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00-0x5F */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00-0x6F */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00-0x7F */ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00-0x8F */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00-0x9F */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00-0xAF */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00-0xBF */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00-0xCF */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00-0xDF */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00-0xEF */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /* 0x00-0xFF */};/** * chk_task_id - Check the existence of a task ID. * @task_id: A task ID. * @return: return FALSE if task id is exist. * * @notes: just traversal the task list, and Comparing the two task IDs. */static word_t chk_task_id(uword_t task_id) { tcb_t *ptcb; list_t *plist = task.next; if(plist == &task) { return TRUE; } do { ptcb = mac_find_entry(plist, tcb_t, task_link); if(ptcb->id == task_id) { return FALSE; } plist = plist->next; } while(plist != task.next); return TRUE;}/** * get_max_prio - Get the max priority in ready queue. * @return: The hightest priority in ready queue. * * @notes: */static uword_t get_max_prio(void) { uword_t high; uword_t low; uword_t prio; high = prio_decision[prio_rdy_grup]; low = prio_decision[prio_rdy[high]]; prio = (high << 3) + low; return prio;}/** * add_tcb_ready - Insert a TCB into ready queue according to it's priority. * @ptcb: pointer to the TCB that will be inserted to ready queue. * @return: * * @notes: */void add_tcb_rdy(tcb_t *ptcb) { uword_t prio = ptcb->prio; if((prio_rdy[prio >> 3] &prio_mask[prio &0x07]) == 0) { prio_rdy_grup |= prio_mask[prio >> 3]; prio_rdy[prio >> 3] |= prio_mask[prio &0x07]; } add_node_list_rear(&ptask[prio], &ptcb->link);}/** * del_tcb_rdy: Delete a TCB in ready queue according to it's start address. * @ptcb: Pointer to the TCB that will be deleted from ready queue. * @return: The link list address of deleted TCB. * * @notes: */list_t *del_tcb_rdy(tcb_t *ptcb) { uword_t prio = ptcb->prio; list_t *renode = &ptcb->link; if(ptcb->id == IDLE_TASK_ID && ptcb->prio == IDLE_TASK_PRIO) { return NULL; } else { /* TCBs have existed in ready queue */ if(ptask[prio].next != &ptask[prio] && ptask[prio].prev != &ptask[prio]) { /* There is only one TCB in ready queue currently */ if((ptask[prio].next == renode) && (ptask[prio].prev == renode)) if(!(prio_rdy[prio >> 3] &= ~prio_mask[prio &0x07])) { prio_rdy_grup &= ~prio_mask[prio >> 3]; } return (del_node_list(&ptask[prio], renode)); } } return NULL;}/** * add_tcb_sleep: Inserte a TCB to sleep queue. * @ptcb: Pointer to the TCB that will be inserted to sleep queue. * @return: * * @notes: */void add_tcb_sleep(tcb_t *ptcb) { add_node_list_rear(&psleep, &ptcb->link);}/** * del_tcb_sleep: Delete a TCB from sleep queue. * @ptcb: Pointer to the TCB that will be deleted from sleep queue. * @return: * * @notes: */list_t *del_tcb_sleep(tcb_t *ptcb) { return (del_node_list(&psleep, &ptcb->link));}/** * add_tcb_delay: Inserte a TCB to delay queue. * @ptcb: Pointer to the TCB that will be inserted to delay queue. * @return: * * @notes: */void add_tcb_delay(tcb_t *ptcb) { add_node_list_rear(&psleep, &ptcb->link);}/** * del_tcb_delay: Delete a TCB from delay queue. * @ptcb: Pointer to the TCB that will be deleted from delay queue. * @return: * * @notes: */list_t *del_tcb_delay(tcb_t *ptcb) { return (del_node_list(&psleep, &ptcb->link));}/** * scheduler - Estimate whether higher task has ready, and decide * which task will be excuted. * @return: * * @notes: */void scheduler(void) { mac_disable_irq(); if(int_flag == TRUE) { int_cnt--; } if(int_cnt != 0) { mac_enable_irq(); return ; } highprio = get_max_prio(); /* get the hightest priority */ if((pcurtcb != NULL) && (pcurtcb->prio <= highprio) && \ (pcurtcb->status == T_READY)) { pglobal = &pcurtcb->link; } else { pglobal = ptask[highprio].next; } do { if((pnewtcb = mac_find_entry(pglobal, tcb_t, link)) != NULL) { if(pnewtcb->exe_time >= pnewtcb->slice_time) { pnewtcb->exe_time = 0; pglobal = pglobal->next; } else { break; } } } while(1); if(pnewtcb != pcurtcb) { ptask[pnewtcb->prio].next = &pnewtcb->link; if(ptask[pnewtcb->prio].prev == &pnewtcb->link) { ptask[pnewtcb->prio].prev = (ptask[pnewtcb->prio].prev)->prev; } if(int_flag == FALSE) { if(pcurtcb == NULL) { TaskStart(); } else { TaskSwitch(); } } else if(int_flag == TRUE) { int_flag = FALSE; if(pcurtcb == NULL) { TaskIntStart(); } else { TaskIntSw(); } } } else if(int_flag == TRUE) { int_flag = FALSE; TaskContinue(); }}/** * idle_task - This task runs when there are no task ready. * @return: * * @note: This task is at ready status forever. */static void idle_task(void) { while(1) { mac_disable_irq(); idle_cnt++; mac_enable_irq(); }}/** * idle_task - Initial task. * @return: * * @note: This task is the first application task in Bycore. */static void Init(void){ device_init(); Main(); osSleep();}/** * cre_sys_task - Crate a TCB for new task. * @ptask: Pointer to start addrees of task. * @taskid: Task ID. * @prio: The priority of task. * @time: Slice time. * @pstk: Stack size that the task ask for. * @return: * * @notes: */static word_t create_task(void(*pTask)(), tcb_t *pTcb, uword_t TaskID, uword_t Prio, uword_t Time, word_t *pSpace, uword_t StkSize) { word_t *space = pSpace; tcb_t *tcb = pTcb; tcb->pstart = pSpace; if(chk_task_id(TaskID) == FALSE) { return FALSE; } /* Initialize the TCB space */ if((tcb == NULL) || (space == NULL) || (Prio >= MAX_PRIO) || (Time == 0)) { return FALSE; }#if STACK == DOWN space += StkSize - 1;#endif *space = (word_t)pTask; /* Store the entry address of task */ tcb->context = space;#if STACK == DOWN space--;#else space++;#endif /* Initialize task stack */ init_context(space); tcb->id = TaskID; tcb->prio = Prio; tcb->slice_time = Time; tcb->exe_time = 0; tcb->delay_time = 0; tcb->status = T_READY; tcb->sem_link.next = NULL; tcb->fd_node.next = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -