高通操作系统分析.pdf
REX 操作系统分析 System Group 1.数据定义与宏定义(Defines&Macros).5 1.1.数据结构.5 1.1.1.TCB(任务控制块).5 1.1.2.定时器(timer)数据结构.7 1.1.3.临界区(Critical Section)数据结构.7 1.1.4.上下文帧的结构.7 1.2.几个全局变量.8 1.2.1.rex_curr_task.8 1.2.2.rex_best_task.8 1.2.3.rex_task_list.8 1.2.4.rex_num_tasks.8 1.2.5.rex_kernel_tcb.8 1.2.6.rex_sched_allow.8 1.2.7.rex_nest_depth.9 1.2.8.rex_timer_list.9 1.2.9.rex_null_timer.9 1.2.10.rex_irq_vector&rex_fiq_vector.9 1.3.MACROS(几个宏定义).9 1.3.1.REX_VERSION_NUMBER.9 1.3.2.任务链表操作宏.9 1.3.3.REX_TASK_RUNNABLE(tcb).10 1.3.4.看门狗操作宏.10 2.任务(TASK).10 2.1.创建任务.11 2.1.1.rex_def_task_internal().11 2.2.任务的通用引导函数.14 2.2.1.rex_task_preamble().14 2.3.任务挂起和继续.15 2.3.1.rex_suspend_task().15 2.3.2.rex_resume_task().15 2.4.删除任务.16 2.4.1.rex_remove_task().16 2.4.2.rex_kill_task_ext().16 2.5.Others.19 2.5.1.rex_self().19 2.5.2.rex_get_pri().19 2.5.3.rex_set_pri().19 2.5.4.rex_task_pri().19 3.调度(Schedule).21 3.1.调度代码.21 3.1.1.rex_sched().21 3.2.设定rex_best_task.23 3.2.1.rex_set_best_task().24 3.3.任务调度加锁/解锁.24 3.3.1.rex_task_lock().24 3.3.2.rex_task_free().25 3.3.3.rex_tasks_are_locked().25 4.中断(Interrupts).25 4.1.设置中断向量.26 4.1.1.rex_set_interrupt_vector().26 4.2.PIC Trampoline Service(可编程控制弹簧中断服务).26 4.2.1.tramp_init().26 4.2.2.tramp_set_isr().27 4.2.3.tramp_isr().29 4.3.IRQ_handler.33 5.信号量(Signals)和定时器(Timers).37 5.1.信号量.37 5.1.1.rex_wait().38 5.1.2.rex_set_sigs().39 5.1.3.rex_get_sigs().39 5.1.4.rex_clr_sigs().40 5.2.定时器.40 5.2.1.rex_init_timer_list().41 5.2.2.rex_insert_timer().41 5.2.3.rex_def_timer().42 5.2.4.rex_set_timer().43 5.2.5.rex_timed_wait().44 5.2.6.rex_clr_timer().44 5.2.7.rex_get_timer().45 5.2.8.rex_pause_timer().46 5.2.9.rex_resume_timer().46 5.2.10.rex_delete_task_timers().47 5.2.11.rex_decrement_timers().47 5.2.12.rex_tick().49 5.3.Others.49 5.3.1.rex_sleep().49 6.临界区(Critical Section).50 6.1.rex_init_crit_sect().51 6.2.rex_enter_crit_sect().51 6.3.rex_leave_crit_sect_internals().53 7.APC&DPC.56 7.1.DPC的实现.56 7.1.1.rex_dpc_task().56 7.1.2.rex_execute_next_dpc().57 7.1.3.rex_queue_dpc().57 7.2.APC的实现.58 7.2.1.rex_queue_apc().58 7.2.2.rex_queue_apc_internal().59 7.2.3.rex_apc_prolog().60 7.2.4.rex_call_apc().62 7.2.5.rex_apc_epilog.63 8.REX操作系统的初始化与退出.63 8.1.main().64 8.2.rex_init().64 8.3.rex_exit().67 8.4.rex_get_version_number().67 9.内存管理.67 9.1.rex_mem_init().67 9.2.rex_malloc().67 9.3.rex_calloc().68 9.4.rex_realloc().68 9.5.rex_free().68 REX(Real Time Executive)是一个面向嵌入式应用的、简单高效的、抢先式、多任务实时操作系统,支持基于优先级的任务调度算法(支持优先级反转)。它提供了任务控制、任务同步、互斥、定时器和中断控制等 API。REX 所有的函数都在任务上下文环境里执行。REX 只需要少于 5k 的 ROM 空间,需要的 RAM 空间取决于运行的任务数目加上几k 字节的状态数据和堆栈空间。REX 处理了 IRQ 中断。1.数据定义与宏定义(Defines&Macros)1.1.数据结构 rex.h 中定义了 REX 中的各种数据结构。1.1.1.TCB(任务控制块)?用于描述一个 REX 任务?不能被外部直接访问?由于内核按照排列顺序对其进行访问,结构中数据的排列顺序不能更改 typedef struct rex_tcb_struct void *sp;/*堆栈指针 */void *stack_limit;/*堆栈限值 */unsigned long slices;/*任务的时间片 */rex_sigs_type sigs;/*当前持有的信号量*/rex_sigs_type wait;/*等待获得的信号量 */rex_priority_type pri;/*任务优先级*/#if defined FEATURE_REX_PROFILE unsigned long time_samples;/*Profiling information*/unsigned long max_intlock_time;/*Profiling Info*/#endif#if defined TIMETEST word leds;/*TIMETEST val */#endif#if defined FEATURE_SOFTWARE_PROFILE /*32 bits counter,30 usec/tick,35 hours*/dword numticks;#endif#ifdef FEATURE_REX_APC long num_apcs;/*APC调用数目*/#endif /*以上数据域的偏移量已在rexarm.h中定义。注意保持两者一致*/rex_tcb_link_type cs_link;/*当等待临界区时,为非空*/rex_crit_sect_type *cs_stackREX_CRIT_SECT_MAX;/*持有和等待临界区的TCB堆栈*/rex_crit_sect_type *cs_sp;/*临界区堆栈指针*/boolean suspended;/*任务是否挂起*/char task_nameREX_TASK_NAME_LEN+1;#if defined FEATURE_REX_EXTENDED_CONTEXT void *ext;#endif unsigned long thread_id;unsigned long stack_size;/检查task堆栈的使用情况,该特性没有打开#ifdef FEATURE_SI_STACK_WM unsigned long stack_wm;#endif /用于BSD socket数据服务#if defined FEATURE_DS_SOCKETS_BSD void *bsdcb_ptr;#endif int err_num;/*Error code */用于在task被阻塞时,通知Dog停止监视 int dog_report_val;/*Dog Report Id */int autodog_enabled;/*Dog Report enabled?*/#if defined FEATURE_REX_CREATE_TASK|defined FEATURE_ZREX boolean is_dynamic;#endif#ifdef FEATURE_REX_IPC rex_ipc_info_type ipc_info;#endif rex_tcb_type;1.1.2.定时器(timer)数据结构?描述 REX 使用的定时器?不能被外部直接访问 typedef struct rex_timer_struct struct struct rex_timer_struct*next_ptr;struct rex_timer_struct*prev_ptr;link;rex_timer_cnt_type cnt;/*当前计数值 */rex_tcb_type *tcb_ptr;/*指向需要信号的TCB结构*/rex_sigs_type sigs;/*关联的信号量 */#ifdef FEATURE_REX_TIMER_EX rex_timer_cb_type cb_ptr;/*Function called when timer expires*/unsigned long cb_param;/*Argument to callback function */#endif rex_timer_type;1.1.3.临界区(Critical Section)数据结构?提供互斥机制 typedef struct byte lock_count;/*0 if crit sect is taken */struct rex_tcb_struct*owner;/*持有者的TCB指针*/struct rex_tcb_struct*tcb_link;/*等待队列的头指针*/rex_priority_type orig_pri;/*原始优先级,为支持优先级反转而提供*/rex_crit_sect_type;1.1.4.上下文帧的结构?任务的上下文,记录了 ARM 的各个寄存器的数据 typedef PACKED struct rex_cpu_register_type spsr;rex_cpu_register_type r13;/*r0-r7,r8-r12*/rex_cpu_register_type lr;/*r14 */rex_cpu_register_type pc;/*r15 */rex_context_frame_type;1.2.几个全局变量 1.2.1.rex_curr_task?当前任务的控制块 TCB 指针 rex_tcb_type *rex_curr_task;1.2.2.rex_best_task?处于 ready 状态、优先级最高的 task?将想要成为 rex_curr_task 的任务设为 rex_best_task,再调用 rex_sched()进行任务的上下文切换?有些情况下,由于任务调度被加锁、或处于 ISR 中断模式,rex_sched()不会马上进行任务切换。因此,在 rex_sched()真正进行调度之前,rex_best_task 可能在不同地方被多次更改。所以在确定是否 rex_best_task 时,应该将需要切换的任务与rex_best_task 进行比较(而不是 rex_curr_task)。只有当该任务处于 ready 状态,且优先级比 rex_best_task 更高时,才允许更新 rex_best_task rex_tcb_type *rex_best_task;1.2.3.rex_task_list?任务链表的头节点 rex_tcb_type rex_task_list;1.2.4.rex_num_tasks?任务个数 int rex_num_tasks=0;1.2.5.rex_kernel_tcb?任务链表的最末尾的节点、及其堆栈?一般指向 Idle task static rex_tcb_type rex_kernel_tcb;rex_stack_word_type rex_kernel_stack REX_KERNEL_STACK_SIZE/sizeof(rex_stack_word_type);1.2.6.rex_sched_allow?任务调度是否加锁的标志位 int rex_sched_allow=TRUE;/*turns sched on/off*/1.2.7.rex_nest_depth?用于支持任务调度的嵌套加锁,记录嵌套层数 unsigned int rex_nest_depth=0;/*supports nesting of TASKLOCK/*FREE.*/1.2.8.rex_timer_list?定时器链表的头节点 static rex_timer_type rex_timer_list;1.2.9.rex_null_timer?空定时器?定时器链表的最末尾节点 static rex_timer_type rex_null_timer;1.2.10.rex_irq_vector&rex_fiq_vector?包含用户定义的 ISR 中断服务函数的入口点 void (*rex_irq_vector)(void);void (*rex_fiq_vector)(void);1.3.MACROS(几个宏定义)1.3.1.REX_VERSION_NUMBER#define REX_VERSION_NUMBER(unsigned long)403)1.3.2.任务链表操作宏?REX_TASK_LIST_FRONT()获得任务链表的头节点,多用于链表循环?REX_TASK_LIST_NEXT(tcb_ptr)获得指定任务的下一个任务?REX_TASK_LIST_PREV(tcb_ptr)获得指定任务的前一个任务?REX_TASK_LIST_POP(tcb_ptr)将指定任务从任务链表中移除#define REX_TASK_LIST_FRONT()(&rex_task_list)#define REX_TASK_LIST_NEXT(tcb_ptr)(rex_tcb_type*)tcb_ptr-link.next_ptr)#define REX_TASK_LIST_PREV(tcb_ptr)(rex_tcb_type*)tcb_ptr-link.prev_ptr)#define REX_TASK_LIST_POP(tcb_ptr)tcb_ptr-link.next_ptr-link.prev_ptr=tcb_ptr-link.prev_ptr;tcb_ptr-link.prev_ptr-link.next_ptr=tcb_ptr-link.next_ptr;1.3.3.REX_TASK_RUNNABLE(tcb)?判断指定任务是否处于 ready 状态。?判据:1、任务是否挂起;2、任务是否在等待进入临界区;3、任务是否在等待信号量;4、是否有 APC 队列需要处理。#define REX_TASK_RUNNABLE(tcb)(tcb-suspended=FALSE)&(tcb-cs_link.next_ptr=NULL)&(tcb-wait =0)|(tcb-num_apcs 0)1.3.4.看门狗操作宏?REX_PAUSE_DOG_MONITOR(tcb_ptr)通知 DOG 停止监视该任务?REX_RESUME_DOG_MONITOR(tcb_ptr)通知 DOG 恢复对该任务的监视#define REX_PAUSE_DOG_MONITOR(tcb_ptr)if(tcb_ptr-autodog_enabled)&(tcb_ptr-dog_report_val=0)dog_monitor_pause(tcb_ptr-dog_report_val);#define REX_RESUME_DOG_MONITOR(tcb_ptr)if(tcb_ptr-dog_report_val=0)dog_monitor_resume(tcb_ptr-dog_report_val);2.任务(TASK)REX 把 task 当作一个个独立的入口函数,每个 task 都拥有各自的堆栈、优先级,这些共同构成了任务的上下文。每个任务都有一个相关联的数据结构,称为 TCB(任务控制块)。REX 允许在执行任意时刻创建任意数目的 task。实际上,每增加一个任务,由于遍历更长的任务链表,REX 的性能会有轻微的下降。需要小心控制任务的数目。?任务堆栈:任务堆栈:每个任务都拥有自己的堆栈,在运行时被使用。当任务挂起时(如运行其他任务或进行中断服务),任务的寄存器会被压入任务堆栈中,并将栈顶指针保存在任务 TCB 里。等到任务被选中再次运行时,从 TCB 里获取栈顶指针,将任务的寄存器值从其堆栈中弹出,任务于是从上次被中断的位置继续运行。这些任务切换的处理对于任务来说是透明的(可以参考【第三章 调度】)。2.1.创建任务 2.1.1.rex_def_task_internal()定义和创建一个任务?定义初始的任务上下文,初始化 TCB 结构信息?将任务按优先级顺序插入到 rex_task_list 中?若是该任务优先级比 rex_best_task 更高且没有挂起,则进行任务调度 void rex_def_task_internal(rex_tcb_type *p_tcb,/*valid tcb for new task */unsigned char*p_stack,/*stack for new task */rex_stack_size_type p_stksiz,/*stack size in bytes */rex_priority_type p_pri,/*priority for new task */rex_task_func_type p_task,/*task startup function */dword p_param,/*parameter for new task */char *p_tskname,/*A/N string for task name */boolean p_susp,/*is task initially suspended?*/void *p_parent,/*opaque handle to container */boolean p_dynamic,/*stack/tcb allocd via dyna mem*/int dog_report_val /*Dog report value */)word index =0;byte *stack_ptr=NULL;rex_context_frame_type*cf_ptr =NULL;/*-*Task stack pointer points to the bottom of allocated *stack memory.p_stksiz is the number of 8-bit bytes.*-*/stack_ptr=(byte*)(unsigned long)p_stack+(unsigned long)p_stksiz-sizeof(unsigned long);/*-*Creates room for the context.*sp points to the top of the context frame.*-*/stack_ptr-=sizeof(rex_context_frame_type);/*-*Defines the initial context.*设置任务的pc、lr为通用任务入口函数rex_task_preamble(),其参数为 *p_task、p_param。*-*/cf_ptr =(rex_context_frame_type*)stack_ptr;cf_ptr-spsr.val =PSR_Supervisor|PSR_Thumb;cf_ptr-r0.task =p_task;cf_ptr-r1.arg =p_param;cf_ptr-r10.arg =(unsigned long)p_stack;cf_ptr-lr.preamble=rex_task_preamble;cf_ptr-pc.preamble=rex_task_preamble;/*-*Initialize the task control block(TCB)*-*/p_tcb-sp =stack_ptr;p_tcb-stack_limit =p_stack;p_tcb-stack_size =p_stksiz;p_tcb-slices =0;p_tcb-sigs =0;p_tcb-wait =0;p_tcb-pri =p_pri;p_tcb-cs_link.next_ptr=NULL;p_tcb-cs_link.prev_ptr=NULL;p_tcb-cs_sp =p_tcb-cs_stack;-p_tcb-cs_sp;p_tcb-suspended =p_susp;#ifdef FEATURE_SI_STACK_WM rex_swm_init(p_tcb);#endif/*FEATURE_SI_STACK_WM*/p_tcb-task_nameREX_TASK_NAME_LEN=0;if(p_tskname!=NULL)/*copy task name if one was supplied*/*copy bytes until/0 received or enough chars have been copied*/while(p_tcb-task_nameindex=p_tsknameindex)&(index+num_apcs=0;/*Number of queued APCs*/#endif#if defined FEATURE_REX_PROFILE p_tcb-time_samples=0;/*Profiling information*/#endif#if defined FEATURE_DS_SOCKETS_BSD p_tcb-bsdcb_ptr=NULL;#endif#if defined FEATURE_SOFTWARE_PROFILE p_tcb-numticks =0;#endif p_tcb-err_num=0;p_tcb-dog_report_val =dog_report_val;p_tcb-autodog_enabled=FALSE;#if defined FEATURE_REX_CREATE_TASK&!defined FEATURE_ZREX p_tcb-is_dynamic=TRUE;#endif /*-*We are done if this is the idle task(kernel task)defined.*-*/if(p_pri=0)return;/*-*Find the first task whose priority is lower than the *new task and insert the new task in front of the *lower priority task.*rex_idle_task(the kernel task)is at the end of the list *with priority 0 and therefore no need to check for null ptrs.*-*/REX_INTLOCK();rex_tcb_type*tcb_ptr;tcb_ptr=rex_task_list.link.next_ptr;while(tcb_ptr-pri p_pri)&(tcb_ptr!=&rex_kernel_tcb)tcb_ptr=tcb_ptr-link.next_ptr;p_tcb-link.prev_ptr=tcb_ptr-link.prev_ptr;p_tcb-link.next_ptr=tcb_ptr;tcb_ptr-link.prev_ptr-link.next_ptr=p_tcb;tcb_ptr-link.prev_ptr=p_tcb;#ifdef FEATURE_REX_IPC if(ipcns_node_register(p_tcb)=FALSE)return;#endif /*-*Make this task the best task if it is higher *priority than the present best task.*-*/*Always compare with REX_BEST_TASK,not REX_CURR_TASK*/if (p_pri rex_best_task-pri)&(p_tcb-suspended=FALSE)rex_best_task=p_tcb;/*swap the task in*/rex_sched();rex_num_tasks+;REX_INTFREE();return;相关的 API:?rex_def_task()、rex_def_task_ext()、rex_def_task_ext2()2.2.任务的通用引导函数 2.2.1.rex_task_preamble()?每个新创建的任务在第一次运行时,都会首先执行这个函数。这样做的好处是可以处理任务入口函数返回的情况(在这里,会将该任务直接删除)。?只能由 REX 内部调用 void rex_task_preamble(void(*func_ptr)(dword arg),dword arg)func_ptr(arg);/*if we return,kill the task*/rex_kill_task(rex_self();/*END rex_task_preamble*/2.3.任务挂起和继续 2.3.1.rex_suspend_task()?挂起一个任务,使其不再接受调度?如果挂起的是当前任务,则要进行一次任务调度 void rex_suspend_task(rex_tcb_type*p_tcb)p_tcb-suspended=TRUE;REX_INTLOCK();if(p_tcb=rex_curr_task)&!rex_is_in_irq_mode()rex_set_best_task(REX_TASK_LIST_FRONT();rex_sched();REX_INTFREE();return;/*END rex_suspend_task*/2.3.2.rex_resume_task()?使任务重新接受调度?若该任务优先级比 rex_best_task 更高,则进行任务调度 void rex_resume_task(rex_tcb_type *p_tcb)REX_INTLOCK();/*basic sanity check to see if we should even be here or not*/if(p_tcb-suspended=TRUE)p_tcb-suspended=FALSE;if(p_tcb-pri rex_best_task-pri)&REX_TASK_RUNNABLE(p_tcb)rex_best_task=p_tcb;rex_sched();REX_INTFREE();return;/*END rex_resume_task*/2.4.删除任务 2.4.1.rex_remove_task()?将一个任务控制块 TCB 从任务列表 rex_task_list 从移除 void rex_remove_task(rex_tcb_type*tcb_ptr /*pointer to tcb*/)rex_tcb_type*prev_tcb_ptr;rex_tcb_type*next_tcb_ptr;prev_tcb_ptr=REX_TASK_LIST_PREV(tcb_ptr);next_tcb_ptr=REX_TASK_LIST_NEXT(tcb_ptr);if(prev_tcb_ptr=NULL|prev_tcb_ptr-pri!=tcb_ptr-pri )&next_tcb_ptr!=NULL&next_tcb_ptr-pri=tcb_ptr-pri )/*若该任务是当前优先级别的代表(最靠前的任务),寻找下一个同一优先级别的任务,作为代表(并未使用)*/rex_tcb_type*temp_tcb_ptr=next_tcb_ptr;while(temp_tcb_ptr-pri=tcb_ptr-pri)temp_tcb_ptr-pri_rep_ptr=next_tcb_ptr;temp_tcb_ptr=REX_TASK_LIST_NEXT(temp_tcb_ptr);REX_TASK_LIST_POP(tcb_ptr);tcb_ptr-link.prev_ptr=NULL;tcb_ptr-link.next_ptr=NULL;return;/*END rex_remove_task*/2.4.2.rex_kill_task_ext()?首先将任务从 rex_task_list 从移除?移除与其相关的定时器?通知 DOG 停止对其的监视?如果持有临界区,则需要释放它?如果需要任务调度,先检查该任务是否持有任务调度锁定,若有则需释放锁定,再进行任务调度 void rex_kill_task_ext(rex_tcb_type*p_tcb,boolean schedule_new_task)REX_INTLOCK();TASKLOCK();/*Task is alive only if it is still linked into TCB list.*/if(p_tcb-link.prev_ptr!=NULL)|(p_tcb-link.next_ptr!=NULL)/*Remove TCB from the task list.*/rex_remove_task(p_tcb);/*Remove REX timers associated with the task from the timer list.*/rex_delete_task_timers(p_tcb);/*Tell Dog to stop monitoring this task.*/REX_PAUSE_DOG_MONITOR(p_tcb);/*Check if we were holding or waiting on a critical section*/while(p_tcb-cs_sp=p_tcb-cs_stack)if(p_tcb-cs_link.next_ptr=NULL)/*holding crit section*/*free the crit section,but dont call rex_sched()yet*/rex_leave_crit_sect_internals(*p_tcb-cs_sp,p_tcb,FALSE);else/*we were waiting on the list*/*if item is first on the list,fix up list head*/if(p_tcb-cs_link.prev_ptr=REX_CRIT_SECT_FLAG)(*p_tcb-cs_sp)-tcb_link=p_tcb-cs_link.next_ptr;else/*fix up previous item on list*/p_tcb-cs_link.prev_ptr-cs_link.next_ptr=p_tcb-cs_link.next_ptr;/*if item is NOT the last on the list*/if(p_tcb-cs_link.next_ptr!=REX_CRIT_SECT_FLAG)p_tcb-cs_link.next_ptr-cs_link.prev_ptr=p_tcb-cs_link.prev_ptr;-p_tcb-cs_sp;/*END we needed to deal with crit section*/rex_num_tasks-;if(schedule_new_task)/*如果任务是想杀死自身,并且持有任务锁定,则要释放任务锁定*/if(p_tcb=rex_curr_task)if(rex_nest_depth 0)rex_nest_depth=0;rex_sched_allow=TRUE;/*end-if task was killing itself*/rex_set_best_task(REX_TASK_LIST_FRONT();rex_sched();/*END needed to reschedule*/*END TCB was still in active list*/TASKFREE();REX_INTFREE();return;/*END rex_kill_task_ext*/相关的 API:?rex_kill_task()2.5.Others 2.5.1.rex_self()?获得当前任务的控制块 TCB rex_tcb_type*rex_self(void)/*-*The currently running task is in rex_curr_task *-*/return rex_curr_task;/*END rex_self*/2.5.2.rex_get_pri()?获得当前任务的优先级 rex_priority_type rex_get_pri(void)/*-*Just return the priority field of the current task *-*/return rex_curr_task-pri;/*END rex_get_pri*/2.5.3.rex_set_pri()?设置任务的优先级 rex_priority_type rex_set_pri(rex_priority_type p_pri /*the new priority*/)/*-*A wrapper function that just calls rex_task_pri with *the current task *-*/return rex_task_pri(rex_curr_task,p_pri);/*END rex_set_pri*/2.5.4.rex_task_pri(