uC OS II原始碼分析 總體思路一

2021-05-23 17:13:54 字數 4606 閱讀 3801

首先從main函式開始,下面是uc/os-ii main函式的大致流程:

main(){

osinit();

taskcreate(...);

osstart();

首先是呼叫osinit進行初始化,然後使用taskcreate建立幾個程序/task,最後呼叫osstart,作業系統就開始執行了。

osinit

最先看看osinit完成哪些初始化:

void osinit (void)

#if os_version >= 204

osinithookbegin();

#endif

os_initmisc();

os_initrdylist();

os_inittcblist();

os_initeventlist();

#if (os_version >= 251) && (os_flag_en > 0) && (os_max_flags > 0)

os_flaginit();

#endif

#if (os_mem_en > 0) && (os_max_mem_part > 0)

os_meminit();

#endif

#if (os_q_en > 0) && (os_max_qs > 0)

os_qinit();

#endif

os_inittaskidle();

#if os_task_stat_en > 0

os_inittaskstat();

#endif

#if os_version >= 204

osinithookend();

#endif

#if os_version >= 270 && os_debug_en > 0

osdebuginit();

#endif

os_initmisc()完成的是一些其其他他的變數的初始化:

osintnesting = 0;

oslocknesting = 0;

ostaskctr = 0;

osrunning = false;

osctxswctr = 0;

osidlectr = 0l;

其中包括:中斷巢狀標誌osintnesting,排程鎖定標誌oslocknesting,os標誌osrunning等。osrunning在這裡設定為false,在後面osstarthighrdy中會被設定為true表示os開始工作。

os_initrdylist()初始化就緒task列表:

static void os_initrdylist (void)

int8u i;

int8u *prdytbl;

osrdygrp = 0x00;

prdytbl = &osrdytbl[0];

for (i = 0; i < os_rdy_tbl_size; i++) {

*prdytbl++ = 0x00;

ospriocur = 0;

ospriohighrdy = 0;

ostcbhighrdy = (os_tcb *)0;

ostcbcur = (os_tcb *)0;

首先將osrdytbl陣列中全部初始化0,同時將ospriocur/ostcbcur初始化為0,ospriohighrdy/ostcbhighrdy也初始化為0,這幾個變數將在第乙個osschedule中被賦予正確的值。

os_inittcblist()這個函式看名稱我們就知道是初始化tcb列表。

static void os_inittcblist (void)

int8u i;

os_tcb *ptcb1;

os_tcb *ptcb2;

os_memclr((int8u *)&ostcbtbl[0], sizeof(ostcbtbl));

os_memclr((int8u *)&ostcbpriotbl[0], sizeof(ostcbpriotbl));

ptcb1 = &ostcbtbl[0];

ptcb2 = &ostcbtbl[1];

for (i = 0; i < (os_max_tasks + os_n_sys_tasks - 1); i++) {

ptcb1->ostcbnext = ptcb2;

#if os_task_name_size > 1

ptcb1->ostcbtaskname[0] = '?';

ptcb1->ostcbtaskname[1] = os_ascii_nul;

#endif

ptcb1++;

ptcb2++;

ptcb1->ostcbnext = (os_tcb *)0;

#if os_task_name_size > 1

ptcb1->ostcbtaskname[0] = '?';

ptcb1->ostcbtaskname[1] = os_ascii_nul;

#endif

ostcblist = (os_tcb *)0;

ostcbfreelist = &ostcbtbl[0];

這裡完成的工作很簡單,首先把整個陣列使用ostcbnext指標連線成煉錶鏈起來,然後將ostcblist初始化為0,也就是還沒有tcb,因為還沒有task產生,ostcbfreelist指向ostcbtbl陣列的第乙個表示所有tcb都處於free狀態。

os_initeventlist()初始化event列表。

static void os_initeventlist (void)

#if os_event_en && (os_max_events > 0)

#if (os_max_events > 1)

int16u i;

os_event *pevent1;

os_event *pevent2;

os_memclr((int8u *)&oseventtbl[0], sizeof(oseventtbl));

pevent1 = &oseventtbl[0];

pevent2 = &oseventtbl[1];

for (i = 0; i < (os_max_events - 1); i++) {

pevent1->oseventtype = os_event_type_unused;

pevent1->oseventptr = pevent2;

#if os_event_name_size > 1

pevent1->oseventname[0] = '?';

pevent1->oseventname[1] = os_ascii_nul;

#endif

pevent1++;

pevent2++;

pevent1->oseventtype = os_event_type_unused;

pevent1->oseventptr = (os_event *)0;

#if os_event_name_size > 1

pevent1->oseventname[0] = '?';

pevent1->oseventname[1] = os_ascii_nul;

#endif

oseventfreelist = &oseventtbl[0];

#else

oseventfreelist = &oseventtbl[0];

oseventfreelist->oseventtype = os_event_type_unused;

oseventfreelist->oseventptr = (os_event *)0;

#if os_event_name_size > 1

oseventfreelist->oseventname[0] = '?';

oseventfreelist->oseventname[1] = os_ascii_nul;

#endif

#endif

#endif

同樣將eventtbl陣列中的oseventtype都初始化為os_event_type_unused。

os_inittaskidle(),中間我們跳過其他的如mem等的初始化,看看idle task的初始化。

(void)ostaskcreateext(os_taskidle,

(void *)0,

&ostaskidlestk[os_task_idle_stk_size - 1],

os_idle_prio,

os_task_idle_id,

&ostaskidlestk[0],

os_task_idle_stk_size,

(void *)0,

os_task_opt_stk_chk | os_task_opt_stk_clr);

其實idle task的初始化很簡單就是呼叫ostaskcrete系列的函式建立乙個task, ostaskcreate我們後面再做進一步分析。

初始化state task也是類似呼叫ostaskcreate系列函式建立stat task。這裡只是建立了該task的各個結構還沒有真正執行該task,直到osstart中才依據優先順序排程執行。

ok,到這裡osinit算高乙個段落了,我們接著回到main往下看。

uC OS II原始碼分析 總體思路一

首先從main函式開始,下面是uc os ii main函式的大致流程 main 首先是呼叫osinit進行初始化,然後使用taskcreate建立幾個程序 task,最後呼叫osstart,作業系統就開始執行了。osinit 最先看看osinit完成哪些初始化 void osinit void o...

uC OS II原始碼分析(四)

核心結構 1,臨界區,os enter critical 和os exit critical 為了處理臨界區 必須關中斷,等處理完畢後,再開中斷。關中斷可以避免其他任務或中斷進入臨界區 uc os ii 定義了這兩個巨集來實現,但注意一條 呼叫 uc os ii 功能函式時,中斷應該總是開著的。1 ...

uC OS II原始碼分析(六)

c os 總是執行進入就緒態任務中優先順序最高的那乙個。確定哪個任務優先順序最高,下面該哪個任務執行了的工作是由排程器 scheduler 完成的。任務級的排程是由函式 ossched 完成的。中斷級的排程是由另乙個函式osintext 完成的,這個函式將在以後描 述。ossched 的 如下 vo...