搜索
bottom↓
回复: 2

RAW OS 基于STM32F1/F4 学习笔记 就绪队列

[复制链接]

出0入0汤圆

发表于 2014-2-5 13:57:42 | 显示全部楼层 |阅读模式
开篇先说个题外话前听取了jorya_txj的意见,有些东西的验证可以采取printf的方法,并不要都用硬件仿真。
于是楼主在F4上开启了一路DMA UART
经测试效果良好


于是初步决定和内核内部测试有关的,使用硬件仿真的方法,和内部应用有关的测试,采用UART的方法。


OK,开始这一次的任务,介绍一下硬件和软件的环境:硬件:STM32F4,软件:上一节“任务管理”中的已经创建了3个任务的工程.
我将任务分解为3步



就绪队列的数据结构:
typedef        struct RAW_RUN_QUEUE {

        RAW_U8      highest_priority;                              
        
        LIST          task_ready_list[CONFIG_RAW_PRIO_MAX];                  
        
        RAW_U32     task_bit_map[NUM_WORDS];                  
        
} RAW_RUN_QUEUE;


首先,对RAW_RUN_QUEUE 进行搜索,可以看到这个结构体只定义了一个变量 raw_ready_queue,想必它就维护者整个系统的就绪队列。

void test_task1(void * pParam)
{       
        RAW_U32  * Res;
        while(1)
        {
                Res =  (raw_get_task_user_point(&test_task_obj1, 0));
                if((*Res) == 1)
                {
                        raw_sleep(50);
                }
                UartSendNum("TASK1:now the highest_priority is\n",raw_ready_queue.highest_priority);
                raw_sleep(50);
                if(Switch)
                {
                        space = raw_get_system_global_space();
                }
                raw_task_stack_check(&test_task_obj1, &StackSpace);
        }
       
}


void test_task2(void * pParam)
{       
        RAW_U32  * Res;
        RAW_U32 Task2Tmp = 2;
        while(1)
        {
                raw_sleep(5);
                UartSendNum("TASK2:now the highest_priority is\n",raw_ready_queue.highest_priority);
                raw_sleep(40);
               
        }
}


void test_task3(void * pParam)
{       
        RAW_U32  * Res;
        while(1)
        {
                UartSendNum("TASK3:now the highest_priority is\n",raw_ready_queue.highest_priority);
                raw_sleep(30);               
        }       
}



在三个任务中都调用raw_sleep使任务等待时间信号量而阻塞,从而调度优先级的任务。再用串口发上当前最最高优先级。
经检验,这个优先级指的是当前等待序列中的任务中的最高优先级




结构中的第二项 LIST          task_ready_list[CONFIG_RAW_PRIO_MAX];        
CONFIG_RAW_PRIO_MAX是指当前系统最多支持多少个优先级,可见,为每一个优先级准备了一个链表。


结构中的第二项 LIST          RAW_U32     task_bit_map[NUM_WORDS];   
raw os 找到最高优先级的方法,实质上去查找task_bit_map第一个bit为1的位置。

楼主找到了它的定义处 #define  NUM_WORDS                                        ((CONFIG_RAW_PRIO_MAX + 31) / 32) 起初不理解,后来恍然大悟,每一个链表都需要一个链表头。


任务链表的数据结构:
typedef struct LIST {
        struct LIST        *next;
        struct LIST        *previous;
} LIST;
可见,RAW OS 中链表的结构是双向的。
研究了一番RAW OS 的这个链表的作用
首先,在进入OS后,就绪队列开始起作用,现在有任务优先级分别为11 12 13 的三个任务。


可以发现,就绪队列中的task_ready_list,除了11,12,13,其他任务的LIST 链表头next 和 previous 指向的都是本身。
楼主在思考这个LIST和任务怎么对接的时候翻到了任务控制的结构体。


可以看到,每一个任务控制结构体重都有个task_list 这样的画,对接就可行了,想必是这样的。


最后是相关内核函数:
这里复制一下jorya_txj的原话
1 void add_ready_list_head(RAW_RUN_QUEUE *rq, RAW_TASK_OBJ *task_ptr)

函数功能:
往就绪队列rq里面加入一个任务。也就是说该任务已经处于就绪状态。需要注意的是加入的任务加到就绪队列头部去。

此函数的参数有4个,含义如下:
rq 为指针指向raw os 系统维护的一个优先级队列实体raw_ready_queue。
task_ptr是要准备被加入的任务。

函数的返回值:


2 void add_ready_list_end(RAW_RUN_QUEUE *rq, RAW_TASK_OBJ *task_ptr)

函数功能:
往就绪队列rq里面加入一个任务。也就是说该任务已经处于就绪状态。需要注意的是加入的任务加到就绪队列尾部去。

此函数的参数有4个,含义如下:
rq 为指针指向raw os 系统维护的一个优先级队列实体raw_ready_queue。
task_ptr是要准备被加入的任务。

函数的返回值:


3 void remove_ready_list(RAW_RUN_QUEUE *rq, RAW_TASK_OBJ *task_ptr)

函数功能:
往就绪队列rq里面移除一个任务。也就是说该任务已经处于非就绪状态。非就绪状态有很多任务状态,具体请参阅任务状态一章。需要注意的是此函数内部可能会更新系统的rq->highest_priority, rq->highest_priority永远维护着整个系统最高的优先级。

此函数的参数有2个,含义如下:
rq 为指针指向raw os 系统维护的一个优先级队列实体raw_ready_queue。
task_ptr是要准备被从就绪态移除出去的任务。

函数的返回值:


4 void move_to_ready_list_end(RAW_RUN_QUEUE *rq, RAW_TASK_OBJ *task_ptr)

函数功能:
把任务task_ptr放到就绪队列最后面去。

此函数的参数有2个,含义如下:
rq 为指针指向raw os 系统维护的一个优先级队列实体raw_ready_queue。
task_ptr是要准备放到就绪队列最后面去的任务。

函数的返回值:


5 void get_ready_task(RAW_RUN_QUEUE *rq)

函数功能:
更新就绪队列里面优先级最高的任务, 此函数的算法效率相当重要,对实时性有举足轻重的影响,此函数必须要运行时间是恒定的,因为此函数是在关了系统中断情况下使用的需要越快越好,raw os的实现只有3句C语言,具体的请参照相关代码。

此函数的参数有1个,含义如下:
rq为指针指向raw os系统维护的一个优先级队列实体raw_ready_queue。
前4个函数可顾名思义,重点研究get_ready_task函数,因为这个函数在临界区内实现,所以它的速度关乎系统的响应性。
代码如下


void get_ready_task(RAW_RUN_QUEUE *rq)
{
        LIST *node;
        RAW_U8 highest_pri;
       
        if (task_0_events) {

                high_ready_obj = &raw_task_0_obj;
                return;
        }

        highest_pri = rq->highest_priority;
        node = rq->task_ready_list[highest_pri].next;

       
        high_ready_obj = list_entry(node, RAW_TASK_OBJ, task_list);
       
}
list_entry是一个宏定义
#define list_entry(node, type, member)    ((type *)((RAW_U8 *)(node) - (RAW_U32)(&((type *)0)->member)))

通过这句话,(RAW_U8 *)(node)取出最高优先级等待序列中第一个任务tasklist的偏移地址,再减去 (RAW_U32)(&((type *)0)->member)即tasklist 相对于一个结构的偏移地址。取出一个任务控制模块结构的地址。
楼主经仿真,确实如此。图就不贴啦 :)


于是,“就绪队列”结束。



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2014-2-5 16:07:23 | 显示全部楼层

出0入0汤圆

发表于 2014-6-10 22:31:43 | 显示全部楼层
楼主不知可否拿出整个代码看看,光这么看,很难理解意思
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-20 09:29

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表