分析的内核版本截止到2014-04-15,基于1.05正式版,blogs会及时跟进最新版本的内核开发进度,若源码注释出现”???”字样,则是未深究理解部分。
Raw-OS官方网站:http://www.raw-os.org/
Raw-OS托管地址:https://github.com/jorya/raw-os/
1.双向链表定义
首先关注Raw-OS源码中的/include/list.h,这个文件描述系统使用的关于双向链表的定义和操作,学SW的数据结构都接触过,无奈骚年我学的是电子专业,出来之后混的是软件方面,所以现在各种纠结。
下面就对这些关于链表的操作抽象出来理解
Raw-OS使用的双向链表是这样定义的
- /*
- * 双向链表
- */
- typedef struct LIST {
- /* 链表后向指针 */
- struct LIST *next;
- /* 链表后继指针 */
- struct LIST *previous;
- } LIST;
关于链表的初始化,插入,删除的常规操作都有定义,非常简单
初始化:
- /*
- * 链表初始化,链表头前向和后继指针均指向链表头
- */
- RAW_INLINE void list_init(LIST *list_head)
- {
- list_head->next = list_head;
- list_head->previous = list_head;
- }
双向链表插入:
- /*
- * 在链表头前向增加element,从图里面观察得到,其实在head之前插入,
- * 就是插入到以head为头的双向链表的末端
- *
- * 那么head->next会是双向链表的第一个元素,head->previous则是最后一个元素
- */
- RAW_INLINE void list_insert(LIST *head, LIST *element)
- {
-
- element->previous = head->previous;
- element->next = head;
-
- head->previous->next = element;
- head->previous = element;
- }
简化之后:
删除操作简单得多:
- RAW_INLINE void list_delete(LIST *element)
- {
-
- element->previous->next = element->next;
- element->next->previous = element->previous;
-
- }
2.系统任务创建
raw_task_create(......)函数是Raw-OS系统API级的函数,目的是创建任务控制块
例如创建一个autorun的任务:
创建任务时创建任务控制块,然后初始化TCB内容,然后加入到就绪队列中,就绪队列类似hash表,具体形式如下:
就绪队列的表大小系统默认是256项,而每一项是一个双向List表头,由此可见就绪队列是有256项的双向链表。
那么,加入现在创建一个优先级是2的任务,创建任务的时候,就会在raw_ready_queue[2]中添加对应的element,如果再创建一个优先级是2的任务时,又会在raw_ready_queue[2]中添加一项
至于具体的任务建立的代码如下,添加了注释:
- RAW_U16 raw_task_create(RAW_TASK_OBJ *task_obj, RAW_U8 *task_name, RAW_VOID *task_arg,
- RAW_U8 task_prio, RAW_U32 time_slice, PORT_STACK *task_stack_base,
- RAW_U32 stack_size, RAW_TASK_ENTRY task_entry, RAW_U8 auto_start)
-
- {
- PORT_STACK *p_stack;
- RAW_U32 i;
-
- /* 移植相关,定义存放一个CPU状态寄存器的临时变量,一般是unsigned int */
- RAW_SR_ALLOC();
-
- #if (RAW_TASK_FUNCTION_CHECK > 0)
- /* 检查任务obj,未定义任务控制块时返回 */
- if (task_obj == 0) {
- return RAW_NULL_OBJECT;
- }
- /* 检查任务优先级范围大小,越界返回 */
- if (task_prio >= CONFIG_RAW_PRIO_MAX) {
- return RAW_BYOND_MAX_PRIORITY;
- }
- /* 检查任务堆栈地址,未定义堆栈时返回 */
- if (task_stack_base == 0) {
- return RAW_NULL_POINTER;
- }
- /* 检查任务函数实体,未定义任务入口函数时返回 */
- if (task_entry == 0) {
- return RAW_NULL_POINTER;
- }
- /* 检查是否在中断嵌套中,不能在中断中创建任务??? */
- if (raw_int_nesting) {
- return RAW_NOT_CALLED_BY_ISR;
- }
- #endif
-
- /* 禁止系统中断,作用??? */
- RAW_CRITICAL_ENTER();
- /* 检查是否创建系统IDLE任务,如果IDLE任务已创建,返回,只允许一个IDLE任务存在 */
- if (task_prio == IDLE_PRIORITY) {
- if (idle_task_exit) {
- /* 使能系统中断 */
- RAW_CRITICAL_EXIT();
- return RAW_IDLE_EXIT;
- }
- idle_task_exit = 1u;
- }
-
- /* 同IDLE任务,系统只允许一个task 0存在 */
- #if (CONFIG_RAW_TASK_0 > 0)
- if (task_prio == 0) {
- if (task_0_exit) {
- RAW_CRITICAL_EXIT();
- return RAW_TASK_0_EXIT;
- }
- task_0_exit = 1u;
- }
- #endif
-
- /* 使能系统中断 */
- RAW_CRITICAL_EXIT();
-
- /* 对分配的任务控制块的内存空间初始化为全0 */
- raw_memset(task_obj, 0, sizeof(RAW_TASK_OBJ));
-
- /* 系统调度方式FIFO无时间片???RR方式按时间片??? */
- #if (CONFIG_SCHED_FIFO_RR > 0)
- /* 如果创建任务提供有time_slice参数,则初始化任务时间片为自定义时间片,否则系统默认50 */
- if (time_slice) {
- task_obj->time_total = time_slice;
- }
- else {
- task_obj->time_total = TIME_SLICE_DEFAULT;
- }
- task_obj->time_slice = task_obj->time_total;
- /* 设置任务调度方式 */
- task_obj->sched_way = SCHED_RR;
- #endif
-
- /* 如果定义任务时设置autorun为1,任务状态设为就绪态,否则设为挂起态,在应用层要手动唤醒任务 */
- if (auto_start) {
- task_obj->task_state = RAW_RDY;
- }
- else {
- task_obj->task_state = RAW_SUSPENDED;
- /* 挂起时任务挂起计数+1 */
- task_obj->suspend_count = 1u;
- }
-
- /* 初始化任务堆栈内存空间为0 */
- task_obj->task_stack_base = task_stack_base;
- p_stack = task_stack_base;
- for (i = 0; i < stack_size; i++) {
- *p_stack++ = 0;
- }
-
- /* 调用创建任务的hook函数 */
- #if (CONFIG_RAW_USER_HOOK > 0)
- task_create_hook(task_obj);
- #endif
-
- /* 移植相关,任务创建时的手动模拟堆栈初始化 */
- task_obj->task_stack = port_stack_init(task_stack_base, stack_size, task_arg, task_entry);
- /* 设置TCB中任务名称、优先级、堆栈大小信息 */
- task_obj->task_name = task_name;
- task_obj->priority = task_prio;
- task_obj->bpriority = task_prio;
- task_obj->stack_size = stack_size;
-
- /* 向trace系统加入当前任务调试代码??? */
- TRACE_TASK_CREATE(task_obj);
-
- /* 又禁止系统中断,作用??? */
- RAW_CRITICAL_ENTER();
-
- /* 将任务堆栈检查list加入系统监控??? */
- #if (RAW_SYSTEM_CHECK > 0)
- list_insert(&(system_debug.task_head), &task_obj->stack_check_list);
- #endif
-
- /* 如果创建任务时选择任务自动运行,立即添加到系统就绪链表的末端等待系统调度 */
- if (auto_start) {
- add_ready_list_end(&raw_ready_queue, task_obj);
- }
-
- /* 如果此时系统状态为stopped,即未运行时,返回 */
- if (raw_os_active != RAW_OS_RUNNING) {
- RAW_CRITICAL_EXIT();
- return RAW_OS_STOPPED;
- }
-
- RAW_CRITICAL_EXIT();
-
- /* 如果系统状态为RAW_OS_RUNNING,则马上进行系统调度,即系统运行时创建任务会马上执行调度 */
- if (auto_start) {
- raw_sched();
- }
-
- return RAW_SUCCESS;
- }
3.系统初始化
好,有上两步的基础,接下来看看系统初始化做了哪些工作
看来做了相当多的工作啊啊啊啊啊......直接看代码注释吧,说多也无益,这里tick list和就绪队列的形式是相似的,不过系统默认大小为8,这个tick list和任务超时有关,后续分析会分析到
![](//pubimage.360doc.com/wz/default.gif)
- RAW_U16 raw_os_init(void)
- {
- /* trace系统初始化,还不知道作用在哪??? */
- TRACE_INIT();
-
- /* 此时系统未运行,设置系统运行状态为stopped */
- raw_os_active = RAW_OS_STOPPED;
- /* 初始化就绪队列 */
- run_queue_init(&raw_ready_queue);
-
- /* 初始化tick链表 */
- tick_list_init();
-
- /* 初始化系统调试XX表,这是神马东西?有毛作用??? */
- #if (RAW_SYSTEM_CHECK > 0)
- list_init(&(system_debug.task_head));
- #endif
-
- /* 调用自定义系统初始化hook函数 */
- #if (CONFIG_RAW_USER_HOOK > 0)
- raw_os_init_hook();
- #endif
-
- /* 创建系统空闲任务,IDLE任务是最低优先级任务,必须存在IDLE任务??? */
- raw_task_create(&raw_idle_obj, (RAW_U8 *)"idle_task", 0,
- IDLE_PRIORITY, 0, idle_stack,
- IDLE_STACK_SIZE, raw_idle_task, 1);
-
- /* 系统软件定时器初始化??? */
- #if (CONFIG_RAW_TIMER > 0)
- raw_timer_init();
- #endif
-
- /* 系统最高优先级任务task 0初始化???这又有毛用??? */
- #if (CONFIG_RAW_TASK_0 > 0)
- raw_task_0_init();
- #endif
-
- /* 系统时钟任务(tick任务)初始化,tick任务优先级为1,单独封装tick任务好处??? */
- #if (CONFIG_RAW_TICK_TASK > 0)
- tick_task_start();
- #endif
-
- /* CPU统计任务初始化??? */
- #if (RAW_CONFIG_CPU_TASK > 0)
- cpu_task_start();
- #endif
-
- return RAW_SUCCESS;
- }
4.系统启动
最后就是启动系统,寻找第一个最高优先级任务,开始任务调度,这里说说list_entry这个宏,稍微看过linux代码的同学们就知道container_of这个宏,目的是通过某个结构体中的成员逆运算得出成员所属结构的地址,在Raw-OS中的list_entry作用是类似的
例如,注意到就绪队列中链表的元素是List,也就是说,创建自动运行任务时不是直接吧任务控制块直接添加到就绪队列中,而是把TCB中的tasklist成员添加到就绪队列,那么当从就绪队列中找到最高优先级任务的TCB时,就需要通过tasklist成员逆运算找到TCB的入口地址,所以整个过程如下:
那么在系统启动时就有这样的过程
具体看系统启动的代码
- RAW_U16 raw_os_start(void)
- {
- /* 如果当前系统处于stopped状态,开始任务调度 */
- if (raw_os_active == RAW_OS_STOPPED) {
- /* 从就绪队列取出队列中的最高优先级任务 */
- get_ready_task(&raw_ready_queue);
-
- /* 移植部分相关,当前活动任务设为最高优先级任务,系统状态为running */
- raw_task_active = high_ready_obj;
- raw_os_active = RAW_OS_RUNNING;
- /* 移植部分相关,执行第一个最高优先级任务调度 */
- raw_start_first_task();
- }
-
- else {
- /* 如果系统处于运行状态,调用此函数时,返回running标志 */
- return RAW_OS_RUNNING;
-
- }
-
- /* 永不执行返回? */
- return RAW_SYSTEM_ERROR;
-
- }
那么,整个系统初始化过程就可以这样理解
而在应用层代码中,必要的初始化代码就这样写:
- int main(void){
- /* 硬件初始化代码 */
- ......
-
- /* Raw-OS系统初始化 */
- raw_os_init();
-
- /* 建立自定义任务 */
- ......
-
- /* Raw-OS系统启动 */
- raw_os_start();
-
- /* 永不执行返回操作 */
- return 0;
- }
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。