uCOS II源码详解

发布 2019-06-22 21:52:00 阅读 8240

uc/os-ii源码分析(总体思路一)

首先从main函数开始,下面是uc/os-ii main函数的大致流程:

main()

首先是调用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];

#elseoseventfreelist = 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源码分析(总体思路二)

ostaskcreate负责创建task所需的数据结构,该函数原形如下所示:

int8u ostaskcreate (void (*task)(void *pd), void *p_arg, os_stk *ptos, int8u prio)

其中task是一个函数指针,指向该task所开始的函数,当这个task第一次被调度运行时将会从task处开始运行。

p_arg是传给task的参数指针;

ptos是堆栈指针,指向栈顶(堆栈从上往下)或栈底(堆栈从下往上);

prio是进程的优先级,uc/os-ii共支持最大64个优先级,其中最低的两个优先级给idle和stat进程,并且各个task的优先级必须不同。

接下来,我们看看这个函数的执行流程:

#if os_arg_chk_en > 0

if (prio > os_lowest_prio) {

return (os_prio_invalid);

#endif

os_enter_critical();

if (osintnesting > 0) {

os_exit_critical();

ucosII详解

第1章范例1 1.00 安装 c os ii1 1.02 不依赖于编译的数据类型2 1.03 全局变量3 1.04 os enter critical 和 os exit critical5 1.05 基于pc的服务5 1.05.01 字符显示5 1.05.02 花费时间的测量6 1.05.03 其...

软件源码移交保密协议

四 生效条件与协议终止。有关协议一旦签署,立即生效 并将长期有效,除非以下条件之一成立 4.1 双方另有协议,并一致同意废止此协议 4.2 乙方不再使用现行系统 4.3 乙方主动提出终止此协议 4.4 由于乙方过错导致系统源 泄密,甲方有权解除此协议。协议终止时,乙方有责任向甲方提交或立即销毁所持有...

LVDS接口详解

1 lvds输出接口概述。液晶显示器驱动板输出的数字信号中,除了包括rgb数据信号外,还包括行同步 场同步 像素时钟等信号,其中像素时钟信号的最高频率可超过28mhz。采用ttl接口,数据传输速率不高,传输距离较短,且抗电磁干扰 emi 能力也比较差,会对rgb数据造成一定的影响 另外,ttl多路数...