OpenEdv-开源电子网

标题: 希望原子哥搞个FreeRTOS的板块,这个操作系统比ucos用的多啊 [打印本页]

作者: 小竹新语    时间: 2016-7-21 16:50
标题: 希望原子哥搞个FreeRTOS的板块,这个操作系统比ucos用的多啊


作者: 八度空间    时间: 2016-7-21 17:57
我也支持一下
作者: jermy_z    时间: 2016-7-21 20:13
国内用freertos的真不是太多
作者: yyx112358    时间: 2016-7-21 22:42
不知道大家平常开发的时候一般都用什么操作系统呢?
作者: FreeRTOS    时间: 2016-7-22 09:09
2015年freertos的市场占有率已经超过了ucos,并跻身嵌入式系统领域榜首了
作者: magicoctoy    时间: 2016-7-22 09:18
可以再开个投票,罗列些主流的操作系统,看看大家都是用什么操作系统?
作者: emWin    时间: 2016-7-22 22:08
FreeRTOS市场占有率确实非常高,应该有20%

作者: Littlecar    时间: 2016-7-23 13:53
萌新表示FreeRTOS是什么
作者: openedvadmin    时间: 2016-7-23 15:02
已经开启。谢谢您的建议。。。 嵌入式操作系统 -》FreeRTOS实时系统
作者: 小竹新语    时间: 2016-7-23 23:37
我觉得好荣幸
作者: 文刀言身寸    时间: 2016-7-25 15:19
Bitcraze的Crazyflie用了FreeRTOS
作者: trochili    时间: 2016-8-1 09:14
希望大家关注一下trochili rtos,大家可以在这里在线阅读一下代码https://github.com/liuxuming/trochili
作者: 五武    时间: 2016-9-28 11:54
必须支持一下
作者: 神秘狼    时间: 2016-10-1 09:23
ucos获得了工业认证,freertos没有*(但是他的一个子系统认证过),,,如果不是追究商用,我不会选择freertos的   不管怎样ucos上过火星,上过飞机,在安全性有保证
作者: 神秘狼    时间: 2016-10-1 09:26
ucosiii是专门为了cortex核写的 用了计算前导零汇编指令,任务切换要快许多  我对free不太了解,请问free用计算前导零指令了吗?
作者: FreeRTOS    时间: 2016-10-2 19:50
本帖最后由 FreeRTOS 于 2016-10-2 19:52 编辑
神秘狼 发表于 2016-10-1 09:26
ucosiii是专门为了cortex核写的 用了计算前导零汇编指令,任务切换要快许多  我对free不太了解,请问free用 ...

不太懂你所说的计算前导零指令,Cortex的指令都是定死的,难道UCOS还能超越硬件限制自己创造出新的指令???freertos的稳定性虽然比不上UCOS,不过任务切换部分采用的的汇编几乎是一样的,把你所说的指令贴出来让大家分析下吧,反正代码就在那里
作者: 神秘狼    时间: 2016-10-2 20:30
FreeRTOS 发表于 2016-10-2 19:50
不太懂你所说的计算前导零指令,Cortex的指令都是定死的,难道UCOS还能超越硬件限制自己创造出新的指令? ...

CPU_CntLeadZeros
        CLZ     R0, R0                          ; Count leading zeros
        BX      LR

作者: FreeRTOS    时间: 2016-10-2 21:23
本帖最后由 FreeRTOS 于 2016-10-2 21:26 编辑
神秘狼 发表于 2016-10-2 20:30
CPU_CntLeadZeros
        CLZ     R0, R0                          ; Count leading zeros
        B ...

查了下权威指南,先放上CLZ的定义吧

再放上一个例子:


如果我的理解没错的话,CLZ指令是计算某个字节从左边数起的0的个数,遇到非零位就终止
我看了下UCOS-III的源码,跟任务切换相关的找到下面这个函数:
[AppleScript] 纯文本查看 复制代码
OS_PRIO  OS_PrioGetHighest (void)
{
    CPU_DATA  *p_tbl;
    OS_PRIO    prio;


    prio  = (OS_PRIO)0;
    p_tbl = &OSPrioTbl[0];
    while (*p_tbl == (CPU_DATA)0) {                         /* Search the bitmap table for the highest priority       */
        prio += DEF_INT_CPU_NBR_BITS;                       /* Compute the step of each CPU_DATA entry                */
        p_tbl++;
    }
    prio += (OS_PRIO)CPU_CntLeadZeros(*p_tbl);              /* Find the position of the first bit set at the entry    */
    return (prio);
}

先说明下,我没研究过UCOS-III的源码,如有错误的地方请指出哈。
按照我以前对UCOS-II的内核的理解,UCOS有一个任务就绪表,并且这个表每个字节都被对应的任务独占
UCOS在任务切换时会查询这个表是否有任务就绪,按照上面的代码应该就是在查找到已就绪的更高优先级的任务后调用了CPU_CntLeadZeros
来计算前导0的个数,我不知道统计这个对内核有何意义,不过可以肯定的告诉你freertos没有用这条指令,并且内核跟UCOS完全不一样,获取
高优先级的就绪任务时的方式也完全不一样,换句话说吧freertos并不需要计算前导0,因为对内核没啥用
这里提供下UCOS-III的PendSV中断手动切换任务的汇编代码
[AppleScript] 纯文本查看 复制代码
PendSVHandler_nosave
    PUSH    {R14}                                               ; Save LR exc_return value
    LDR     R0, =OSTaskSwHook                                   ; OSTaskSwHook();
    BLX     R0
    POP     {R14}

    LDR     R0, =OSPrioCur                                      ; OSPrioCur   = OSPrioHighRdy;
    LDR     R1, =OSPrioHighRdy
    LDRB    R2, [R1]
    STRB    R2, [R0]

    LDR     R0, =OSTCBCurPtr                                    ; OSTCBCurPtr = OSTCBHighRdyPtr;
    LDR     R1, =OSTCBHighRdyPtr
    LDR     R2, [R1]
    STR     R2, [R0]

    LDR     R0, [R2]                                            ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr;
    LDM     R0, {R4-R11}                                        ; Restore r4-11 from new process stack
    ADDS    R0, R0, #0x20
    MSR     PSP, R0                                             ; Load PSP with new process SP
    ORR     LR, LR, #0x04                                       ; Ensure exception return uses process stack
    CPSIE   I
    BX      LR                                                  ; Exception return will restore remaining context

这部分代码跟freertos没太大差别,其实嵌入式操作系统的任务切换原理也基本一致的,也就是利用中断来修改中断返回地址以实现一个人为可控的跳转
个人认为这部分代码也不能完全体现一个系统内核调度,因为在这部分汇编代码里也会调用C函数来执行任务切换的工作,个人认为没多大可比性

最后一点,如果单独从一条汇编指令来断定某个系统的任务调度的快慢,那未免太肤浅了吧。。。
之前有数据对比过,freertos的任务调度速度是比UCOS快一点的,因为freertos内核比较简单,并不像UCOS那么复杂,当然内核越复杂功能和稳定性
也就越强,这也是为何从来没有人质疑过UCOS的地位。
个人愚见,并没有任何冒犯的意思,希望有机会可以多交流,呵呵!

作者: 神秘狼    时间: 2016-10-3 09:56
请问测试是对ucosiii经过裁剪后测试的吗?
作者: 神秘狼    时间: 2016-10-3 09:56
FreeRTOS 发表于 2016-10-2 21:23
查了下权威指南,先放上CLZ的定义吧

再放上一个例子:


请问测试是对ucosiii经过裁剪后测试的吗?
作者: FreeRTOS    时间: 2016-10-3 12:01
神秘狼 发表于 2016-10-3 09:56
请问测试是对ucosiii经过裁剪后测试的吗?

并不是对UCOS-III做的测试,要找到准确的测试资料也不容易,可以根据任务切换时的代码量来做大概估算对比,否则只能对比反汇编
作者: 神秘狼    时间: 2016-10-3 16:53
FreeRTOS 发表于 2016-10-3 12:01
并不是对UCOS-III做的测试,要找到准确的测试资料也不容易,可以根据任务切换时的代码量来做大概估算对比 ...

请问freertos是怎么查找已就绪优先级最高的任务的呢?
作者: FreeRTOS    时间: 2016-10-3 18:32
本帖最后由 FreeRTOS 于 2016-10-3 18:34 编辑
神秘狼 发表于 2016-10-3 16:53
请问freertos是怎么查找已就绪优先级最高的任务的呢?

freertos使用一个结构体数组 PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];
[AppleScript] 纯文本查看 复制代码
typedef struct xLIST
{
        listFIRST_LIST_INTEGRITY_CHECK_VALUE
        configLIST_VOLATILE UBaseType_t uxNumberOfItems;    // 列表长度,0表示列表为空
        ListItem_t* configLIST_VOLATILE pxIndex;            // 指向链表当前结点的指针
        MiniListItem_t xListEnd;                                    // 链表尾结点(非指针)
        listSECOND_LIST_INTEGRITY_CHECK_VALUE
} List_t;

每个数组单元管理对应的优先级的任务,例如数组单元1的结构体管理着优先级为1的所有任务(freertos支持任务使用相同优先级)
使用freertos时一定要由用户定义最大的优先级数量 configMAX_PRIORITIES,例如 #define configMAX_PRIORITIES    5
那么用户可以使用的优先级为0~4或1~4(优先级0固定为空闲任务使用,若用户需要与空闲任务共享优先级0,则需要额外配置某个宏)
那么数组 pxReadyTasksLists[] 就只有 pxReadyTasksLists[0] ~ pxReadyTasksLists[4]
freertos规定优先级的数值越大,优先级越高,而且结构体List_t的其中一个单元uxNumberOfItems记录着当前链表长度(同等优先级就绪任务的数量)
因此操作系统只需要检查 pxReadyTasksLists[4].uxNumberOfItems是否为0便知道最高优先级是否有就绪任务
若pxReadyTasksLists[4].uxNumberOfItems == 0,接下来则检查 pxReadyTasksLists[3].uxNumberOfItems,以此类推。。。
当检查到某个优先级n有就绪任务时,pxReadyTasksLists[n].uxNumberOfItems就为非零,接下来直接取出该优先级的任务就绪链表的链表项(就绪任务)执行即可
归纳来讲,如果有10个任务优先级,则freertos每次最多查找10次结构体成员pxReadyTasksLists[].uxNumberOfItems便能按照优先级顺序执行所有任务


UCOS-III的内核听说改了,我记得UCOS-II的内核是必须查找就绪列表的所有单元,例如用户只使用了5个优先级,但操作系统每次必须查找整个就绪列表的64个优先级




作者: hhdjz13813    时间: 2016-10-3 19:39
FreeRTOS 发表于 2016-10-3 18:32
freertos使用一个结构体数组 PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ] ...

神呐,请收下我的膝盖吧,我用FreeRTOS 1年了,也对这玩意的了解也只停留在函数调用层面,没有深究过里面的具体原理,而大神你却对里面内核运作原理什么什么的了如指掌,真想给你跪舔了。
作者: FreeRTOS    时间: 2016-10-3 19:53
hhdjz13813 发表于 2016-10-3 19:39
神呐,请收下我的膝盖吧,我用FreeRTOS 1年了,也对这玩意的了解也只停留在函数调用层面,没有深究过里面 ...

本人跑灯的水平,灯渣一枚,呵呵~
作者: 神秘狼    时间: 2016-10-3 22:21
FreeRTOS 发表于 2016-10-3 18:32
freertos使用一个结构体数组 PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ] ...

谢谢你写了这么多字 让我基本明白了freertos内核中任务切换
是的ucosiii不是对ucosii的继承 而是一套全新的内核

作者: laxsystem01    时间: 2016-10-8 10:21
技术人员就是容易扯淡, 在下多数使用 MDK - RTX , 一个工具而已····  
作者: unsv29    时间: 2016-10-8 10:49
FreeRTOS 发表于 2016-10-3 18:32
freertos使用一个结构体数组 PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ] ...

讲的很清晰
作者: unsv29    时间: 2016-10-8 10:51
FreeRTOS 发表于 2016-10-2 19:50
不太懂你所说的计算前导零指令,Cortex的指令都是定死的,难道UCOS还能超越硬件限制自己创造出新的指令? ...

freertos稳定性不好?
我觉得freertos稳定性很好的。
作者: cjt518    时间: 2016-12-19 21:05
提示: 作者被禁止或删除 内容自动屏蔽
作者: 无名氏    时间: 2017-1-3 10:29
再加上emwin
作者: charlefu    时间: 2017-1-22 13:02
提示: 作者被禁止或删除 内容自动屏蔽
作者: FreeRTOS    时间: 2017-1-22 15:24
charlefu 发表于 2017-1-22 13:02
扯啥呢,ucosII的任务切换只会比freertos快而且可预测。bitmap式的查找最高优先级任务复杂度是o(1),天然 ...

如果没记错的话,UCOSII每次都必须查完整个表,freertos虽然是链表式查询,理论上速度肯定比查表慢,但不妨考虑只有2个任务的情况,UCOSII要查询整个表的64个任务,而freertos只查询2个链表项,这个时间又怎么算?
还有你所说的可预测是什么个意思,还请指教,最好举例详细说明,别像教科书那样说一堆连自己都不懂的知识就好
作者: charlefu    时间: 2017-1-22 15:31
提示: 作者被禁止或删除 内容自动屏蔽
作者: charlefu    时间: 2017-1-22 15:35
提示: 作者被禁止或删除 内容自动屏蔽
作者: FreeRTOS    时间: 2017-1-22 15:43
charlefu 发表于 2017-1-22 15:31
我觉得你下这句话之前去读读ucosii和freertos的调度代码或者百度一下两者的算法说明文章就不会得出这样的 ...

我就是不懂才请教你啊,你还让我自己去找。。。
UCOSII是我研究的第一个RTOS,内核是看过的,没记错的话UCOSII每次TICK中断都会查找整个表的64个任务是否有就绪的,如果你认为不是的话请贴出源码解释下吧,大家也好理解,说教什么的太扯淡了
作者: FreeRTOS    时间: 2017-1-22 15:47
charlefu 发表于 2017-1-22 15:35
另外可预测很简单,比如切换一个任务,从任务就绪到完成切换的延迟时间是多少?ucosII可以预估出最坏的情 ...

关于这个可预测还得请教下你,任务就绪到完成任务切换的延时时间,你说UCOSII可以预估最坏的情况,还得问下你这个最坏的情况到底指的是什么?是时间太长么?如果是的话请问内核如何解决这个问题?
作者: charlefu    时间: 2017-1-22 15:55
提示: 作者被禁止或删除 内容自动屏蔽
作者: charlefu    时间: 2017-1-22 16:05
提示: 作者被禁止或删除 内容自动屏蔽
作者: charlefu    时间: 2017-1-22 16:13
提示: 作者被禁止或删除 内容自动屏蔽
作者: FreeRTOS    时间: 2017-1-22 16:18
charlefu 发表于 2017-1-22 15:55
UCOSII查询task就绪算法就3句话
Y=OSUnMapTbl[OSRdyGrp];
X=OSUnMapTbl[OSRdyTbl[y]];

这位大兄弟你贴的只是查找最高优先级的算法代码而已,我刚才也说了查表肯定比链表查询要快,但UCOSII的任务切换可不是单纯的“查找最高优先级”那么简单啊下面给你贴出TICK中断的代码吧
[AppleScript] 纯文本查看 复制代码
void  OSTimeTick (void)
{
    ...略

    ptcb = OSTCBList;                                                                                                                /* 指向TCB链表的第一个TCB */
        while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO)                                                        /* 遍历整个TCB链表 */
                {
            OS_ENTER_CRITICAL();
            if (ptcb->OSTCBDly != 0u)                                                                                        /* 确保任务当前节拍数不为0 */
                        {
                ptcb->OSTCBDly--;                                                                                                /* 任务节拍数-1 */
                if (ptcb->OSTCBDly == 0u)                                                                                /* 判断此时任务节拍数是否为0,若是则任务就绪 */
                                {

                    if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY)
                                        {
                        ptcb->OSTCBStat  &= (INT8U)~(INT8U)OS_STAT_PEND_ANY;        /* Yes, Clear status flag   */
                        ptcb->OSTCBStatPend = OS_STAT_PEND_TO;                                        /* Indicate PEND timeout    */
                    }
                                        else
                                        {
                        ptcb->OSTCBStatPend = OS_STAT_PEND_OK;
                    }

                    if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY)                /* 检测任务是否被挂起 */
                                        {
                        OSRdyGrp               |= ptcb->OSTCBBitY;                                /* 任务没被挂起,使其就绪 */
                        OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
                    }
                }
            }
            ptcb = ptcb->OSTCBNext;                                                                                                /* 指向TCB链表的下一个TCB */
            OS_EXIT_CRITICAL();
        }
}

在TICK中断里面UCOSII内核必须对64个TCB的延时进行TICK COUNT,也就是说查找最高优先级只不过是任务调度的其中一环,还有最重要的一环就是TICK COUNT!!!
不知你有没有看这部分源码,有问题可以再交流

作者: FreeRTOS    时间: 2017-1-22 16:28
charlefu 发表于 2017-1-22 16:05
简单的说吧,ucos的操作系统函数很多都是o(1)的算法复杂度,换言之这个过程时间是固定的,不管开了多少线 ...

UCOSII的优先级获取确实是固定的,时间可以估算,freertos这个方面是无法估算的,这一点你说的很对。只不过从调度时间来看,UCOSII也没办法保证自己的调度时间比freertos短,最主要的原因就是上面我贴的代码说明,TICK COUNT占用的时间看起来也不少
姑且不对比freertos与UCOSII的任务切换时间,要跟你说明的一点就是freertos将任务延时插入延时链表时进行了排序,延时最少的放在链表前面,最长的放在后面,这样在TICK COUNT时肯定是延时项排在最前面的任务首先被切换,貌似UCOSII并不是以这种方式来获取就绪任务吧
作者: FreeRTOS    时间: 2017-1-22 16:29
charlefu 发表于 2017-1-22 16:13
基本上ucosii的目标客户和freertos不一样,重视系统硬实时性的客户会选择ucosii,而注重易用性免费的客户会 ...

UCOSIII我没研究过,就不讨论了,免得出丑
作者: charlefu    时间: 2017-1-22 16:48
提示: 作者被禁止或删除 内容自动屏蔽
作者: charlefu    时间: 2017-1-22 16:52
提示: 作者被禁止或删除 内容自动屏蔽
作者: FreeRTOS    时间: 2017-1-22 17:07
charlefu 发表于 2017-1-22 16:48
实时性并不完全体现在time_tick,time_tick只是最基本都功能而已。更重要的情景是比如一个重要的中断来了 ...

是的呢,对于事件而言只需要找到最高优先级就绪任务即可,我也是据我经验来考虑,比如在串口中断里面立刻通过一个信号量来激活串口接收处理任务,这时候UCOS肯定是占据了绝对的优势。
可能是我在项目当中碰到的情况跟你的不太一样,我碰到比较多的是任务延时结束后由系统切换,虽然也有上面的手动切换任务的情况,但占的比例相对少很多。
UCOSII是以牺牲空间来换取时间,占用的RAM资源比freertos多,这也是为何很多人想尝试在SRAM资源不足4KB的MCU上使用freertos而不考虑UCOS,互有优势吧
作者: Edwardwei    时间: 2017-2-3 22:35
神秘狼 发表于 2016-10-2 20:30
CPU_CntLeadZeros
        CLZ     R0, R0                          ; Count leading zeros
        B ...

#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) )

之前把ucosii的源代码全部研究过一遍后,这几天也开始研究FreeRTOS了,首先,FreeRTOS是用到了CLZ指令的,就在这一行里。反而ucosii里没有用到,ucosiii我还没研究过。但是用没用到又不代表这个系统好与不好。ucos与FreeRTOS各有所长,各有特色,不要带有有色眼光去研究代码。
作者: yuer19900712    时间: 2017-3-14 15:31
FreeRTOS 发表于 2016-10-2 19:50
不太懂你所说的计算前导零指令,Cortex的指令都是定死的,难道UCOS还能超越硬件限制自己创造出新的指令? ...

看见这个帖子,虽然时间很久了 还是注册了账号来评论两句。FreeRTOS怎么会没有CLZ,这就是它的特色啊。http://blog.csdn.net/zhzht198610 ... s/51418383#comments这个帖子写的很好,可以参考。Coretex-M3和Cortex-M4中提供了这个指令。FreeRTOS任务切换的时候,设置一个宏就能会使用CLZ的方式查找最高优先级。另外,对于普通方式的话(就是你说的那种方式),想请教一下,FreeRTOS就是在遍历的搜寻最高优先级的吗?假如有一种极端情况,我设置三个任务1,2,3,对应的优先级分别是1,2,255,任务3被阻塞了,那么寻找最高优先级是不是就要从255找到2呢?还是被阻塞了之后,uxTopReadyPriority就被更新成2了呢?那会不会出现我说的这种类似情况呢?就是搜寻最高优先级要从255搜寻到1呢?

作者: FreeRTOS    时间: 2017-3-14 17:11
本帖最后由 FreeRTOS 于 2017-3-14 17:17 编辑

至于你贴的链接,我大概看了下,作者的意思是说通过特殊方法也是可以使用CLZ来查找最高优先级任务的,
我之前一直看FreeRTOS的源码都没留意过有这个,是我孤陋寡闻了,呵呵
另外一个你举例说的有3个任务的优先级分别是1,2,255的情况,根据我之前看FreeRTOS的内核源码,确实是要遍历整个链表数组
但根据你上面提到的可以使用CLZ来查找,这个我就没研究过了,应该是有更快的查找方法吧
下面贴出FreeRTOS V8.2.2查找最高优先级的源码:



作者: FreeRTOS    时间: 2017-3-14 17:20
Edwardwei 发表于 2017-2-3 22:35
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ...

群里的高手还是很多呵,都研究得很深入,有机会多多交流
作者: yuer19900712    时间: 2017-3-14 17:39
FreeRTOS 发表于 2017-3-14 17:11
至于你贴的链接,我大概看了下,作者的意思是说通过特殊方法也是可以使用CLZ来查找最高优先级任务的,
我 ...

1、对于CLZ这种特殊方法,只能最多32个任务。并且需要硬件支持,但是用这种方法肯定会快一些,毕竟是利用单个汇编指令去完成这个工作的。
2、对于普通方法还有不明白的地方,uxTopReadyPriority这应该是就绪态最高优先级吧,是不是在高优先级任务阻塞的时候,这个值就会被更新成低优先级的任务了呢?但没有找到有这个过程。为什么这么考虑的呢?是因为我想的既然Free是遍历来查找最高优先级任务的,那我改变一下优先级,那么任务的切换时间应该会不同,比如从200优先级的任务切换到1优先级的任务 和10切换到1是不一样的,10切到1应该短一些(当前有个比200优先级任务还高优先级的任务被阻塞了,比如201)。但是没什么效果,时间居然是一样的。让我不理解了。也不知道是不是我的代码放置的地方不对。工位上电脑上不了外网,只能来公用机上网,贴不了代码了 dayede
作者: FreeRTOS    时间: 2017-3-14 17:41
根据坛友的指引,终于在FreeRTOS里面找到了这个传说中的CLZ了
原来FreeRTOS的任务切换是根据该宏来选择的:configUSE_PORT_OPTIMISED_TASK_SELECTION
当该宏被定义后,任务切换就会执行以下的代码来获取最高优先级:

其中真正实现最高优先级查找的是这条语句:

里面就调用了CLZ指令,当然这只支持具有CLZ指令的芯片。。。

作者: yuer19900712    时间: 2017-3-14 17:53
本帖最后由 yuer19900712 于 2017-3-14 17:55 编辑
FreeRTOS 发表于 2017-3-14 17:11
至于你贴的链接,我大概看了下,作者的意思是说通过特殊方法也是可以使用CLZ来查找最高优先级任务的,
我 ...

我是设定三个任务  任务1、2、3 对应优先级 1、2、255.任务3进去就去获取一个信号量,然后阻塞了。任务2获取另一个信号量同样阻塞,进入任务1,任务1中会释放任务2的信号量,我在释放信号量里边加了个启动定时器的程序。D:\新建文件夹

webwxgetmsgimg.jpg (102.49 KB, 下载次数: 0)

启动定时器

启动定时器

webwxgetmsgimg(1).jpg (76.44 KB, 下载次数: 1)

获取时钟周期个数

获取时钟周期个数

作者: FreeRTOS    时间: 2017-3-14 18:17
本帖最后由 FreeRTOS 于 2017-3-14 18:56 编辑
yuer19900712 发表于 2017-3-14 17:53
我是设定三个任务  任务1、2、3 对应优先级 1、2、255.任务3进去就去获取一个信号量,然后阻塞了。任务2 ...

刚查了下系统延时的源码,当一个高优先级任务进行延时或者阻塞时,会将自身插入到延时链表里调用
static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely )
而函数里面对最高优先级的变量做了处理:



而uxTopReadyPriority是一个unsigned long类型的变量,每一个位表示一个就绪优先级
当最高优先级任务延时或者阻塞时,对应bit清零

比如你的任务200延时阻塞,那么bit200就会清零,但这仅限于使用CLZ指令的时候,在普通的情况下是不使用这方法的:


至于你的测试方法我还没研究,理论上10-1会比200-1的时间短,还有一个宏需要注意下:configMAX_PRIORITIES
你如果想要更大的优先级,这个宏要做修改





作者: yuer19900712    时间: 2017-3-14 19:06
本帖最后由 yuer19900712 于 2017-3-14 19:15 编辑
FreeRTOS 发表于 2017-3-14 18:17
刚查了下系统延时的源码,当一个高优先级任务进行延时或者阻塞时,会将自身插入到延时链表里调用
static ...

这个你还是应该再看看吧,说的不全对,这还是在特殊处理方式中的,因为CLZ就是用一个bit来当做一个任务的优先级是否被置位的。也就是还是跟硬件有关系。在M0对应文件中是没有portRESET_READY_PRIORITY的实现的。利用CLZ的方式是最多只有32个任务,因为一个字32bit,CLZ指令最多操作一个字
我的程序还是逻辑上的问题。程序写的有点繁琐了。普通方式确实就是在遍历。255优先级任务因为阻塞,执行2优先级的任务,进入2优先级的任务后,uxTopReadyPriority已经被写成2了,所以这个时候改变优先级没什么用处的。可以直接用两个任务来做就行了,高优先级的阻塞,低优先级的测时间就行了。那个宏肯定得修改,不修改程序直接就挂了
还有一个问题,高优先级的任务因为阻塞,uxTopReadyPriority一直在自减,然后变成了低优先级的值,低优先级任务释放信号量之后,高优先级任务再次就绪后,uxTopReadyPriority咋变回来的????
作者: FreeRTOS    时间: 2017-3-14 19:59
yuer19900712 发表于 2017-3-14 19:06
这个你还是应该再看看吧,说的不全对,这还是在特殊处理方式中的,因为CLZ就是用一个bit来当做一个任务的 ...

我就是在说明在普通情况下任务阻塞时并没有更新这个变量嘛。。
这么晚了还在工作,果然是狂热者我明天上班再查看下源码,这个问题应该比较好解决
作者: yuer19900712    时间: 2017-3-14 20:10
本帖最后由 yuer19900712 于 2017-3-14 20:13 编辑
FreeRTOS 发表于 2017-3-14 19:59
我就是在说明在普通情况下任务阻塞时并没有更新这个变量嘛。。
这么晚了还在工作,果然是狂热者我明 ...

这个代码已经找到了,举一个简单例子。比如释放信号量的过程
[C] 纯文本查看 复制代码
#definexSemaphoreGive( xSemaphore )                    \  
                  xQueueGenericSend(                       \  
                                                 ( QueueHandle_t ) ( xSemaphore ), \  
                                                 NULL,                \  
                                                semGIVE_BLOCK_TIME,  \  
                                                queueSEND_TO_BACK )  

对应的是使用了消息队列的函数
源码如下
[C] 纯文本查看 复制代码
BaseType_t xQueueGenericSend(   
                QueueHandle_t xQueue,   
                const voidvoid * const pvItemToQueue,   
                TickType_t xTicksToWait,   
                const BaseType_t xCopyPosition )  
{  
BaseType_t xEntryTimeSet = pdFALSE, xYieldRequired;  
TimeOut_t xTimeOut;  
Queue_t * const pxQueue = ( Queue_t * ) xQueue;  
  
  
    for( ;; )  
    {  
        taskENTER_CRITICAL();  
        {  
            /* 队列还有空闲?正在运行的任务一定要比等待访问队列的任务优先级高.如果使用覆盖式入队,则不需要关注队列是否满*/  
            if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )  
            {  
                /*完成数据拷贝工作,分为从队列尾入队,从队列首入队和覆盖式入队*/  
                xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );  
                  
                /* 如果有任务在此等待队列数据到来,则将该任务解除阻塞*/  
                if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )  
                {  
                    /*有任务因等待出队而阻塞,则将任务从队列等待接收列表中删除,然后加入到就绪列表*/  
                    if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )  
                    {  
                        /* 解除阻塞的任务有更高的优先级,则当前任务要让出CPU,因此触发一个上下文切换.又因为现在还在临界区,要等退出临界区后,才会执行上下文切换.*/  
                        queueYIELD_IF_USING_PREEMPTION();  
                    }  
                }  
                else if( xYieldRequired != pdFALSE )  
                {  
                    /* 这个分支处理特殊情况*/  
                    queueYIELD_IF_USING_PREEMPTION();  
                }  
  
  
                taskEXIT_CRITICAL();  
                return pdPASS;  
            }  
            else  
            {  
                if( xTicksToWait == ( TickType_t ) 0 )  
                {  
                    /* 如果队列满并且没有设置超时,则直接退出 */  
                    taskEXIT_CRITICAL();  
  
  
                    /* 返回队列满错误码 */  
                    return errQUEUE_FULL;  
                }  
                else if( xEntryTimeSet == pdFALSE )  
                {  
                    /* 队列满并且规定了阻塞时间,因此需要配置超时结构体对象 */  
                    vTaskSetTimeOutState( &xTimeOut );  
                    xEntryTimeSet = pdTRUE;  
                }  
            }  
        }  
        taskEXIT_CRITICAL();  
  
  
        /* 退出临界区,至此,中断和其它任务可以向这个队列执行入队(投递)或出队(读取)操作.因为队列满,任务无法入队,下面的代码将当前任务将阻塞在这个队列上,在这段代码执行过程中我们需要挂起调度器,防止其它任务操作队列事件列表;挂起调度器虽然可以禁止其它任务操作这个队列,但并不能阻止中断服务程序操作这个队列,因此还需要将队列上锁,防止中断程序读取队列后,使阻塞在出队操作其它任务解除阻塞,执行上下文切换(因为调度器挂起后,不允许执行上下文切换) */  
        vTaskSuspendAll();  
        prvLockQueue( pxQueue );  
  
  
        /* 查看任务的超时时间是否到期 */  
        if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )  
        {  
            if( prvIsQueueFull( pxQueue ) != pdFALSE )  
            {  
                /*超时时间未到期,并且队列仍然满*/  
                vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );  
  
  
                /* 解除队列锁,如果有任务要解除阻塞,则将任务移到挂起就绪列表中(因为当前调度器挂起,所以不能移到就绪列表)*/  
                prvUnlockQueue( pxQueue );  
  
  
                /* 恢复调度器,将任务从挂起就绪列表移到就绪列表中*/  
                if( xTaskResumeAll() == pdFALSE )  
                {  
                    portYIELD_WITHIN_API();  
                }  
            }  
            else  
            {  
                /* 队列有空闲,重试 */  
                prvUnlockQueue( pxQueue );  
                ( void ) xTaskResumeAll();  
            }  
        }  
        else  
        {  
            /* 超时时间到期,返回队列满错误码*/  
            prvUnlockQueue( pxQueue );  
            ( void ) xTaskResumeAll();  
  
  
            traceQUEUE_SEND_FAILED( pxQueue );  
            return errQUEUE_FULL;  
        }  
    }  
}

在26行的函数是个关键,一直goto,找到最终的代码,会看见就绪最高优先级任务被修改了。回家再贴上详细的。下班
作者: FreeRTOS    时间: 2017-3-15 11:22
本帖最后由 FreeRTOS 于 2017-3-15 11:27 编辑

@yuer19900712
这位大兄弟你貌似找错了位置。。。你贴的是被触发的事件是否比当前任务优先级更高,如果是就返回一个pdTRUE
[AppleScript] 纯文本查看 复制代码
if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
        {
                /* Return true if the task removed from the event list has a higher
                priority than the calling task.  This allows the calling task to know if
                it should force a context switch now. */
                xReturn = pdTRUE

                /* Mark that a yield is pending in case the user is not using the
                "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
                xYieldPending = pdTRUE;
        }
        else
        {
                xReturn = pdFALSE;
        }

这段代码跟你问的貌似不大有关系啊。。。

其实对于普通情况(也就是不使用CLZ指令)而言,挂起的任务重新就绪时会重新插入到就绪链表,此时会更新uxTopReadyPriority的值

举个例子吧,在系统时钟中断里会对所有延时的任务进行tick的修正(调用xTaskIncrementTick()函数)
当某个任务延时结束时会重新插入到就绪链表:
[AppleScript] 纯文本查看 复制代码
/* Place the unblocked task into the appropriate readylist. */
prvAddTaskToReadyList( pxTCB );

这里才是关键,下面是这个宏的展开:

里面有我们最最熟悉的重新记录最高的优先级:
[AppleScript] 纯文本查看 复制代码
taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority );

接着继续展开这个宏:
[AppleScript] 纯文本查看 复制代码
/* uxTopReadyPriority holds the priority of the highest priority ready
        state task. */
        #define taskRECORD_READY_PRIORITY( uxPriority )                                                                                                                \
        {                                                                                                                                                                                                        \
                if( ( uxPriority ) > uxTopReadyPriority )                                                                                                                \
                {                                                                                                                                                                                                \
                        uxTopReadyPriority = ( uxPriority );                                                                                                                \
                }                                                                                                                                                                                                \
        } /* taskRECORD_READY_PRIORITY */


任务就绪流程是:操作系统轮询延时链表 ->
                        有任务就绪 ->
                        比较就绪任务与当前的最高优先级并修正uxTopReadyPriority的值 ->
                        将就绪任务插入到就绪链表 ->
                        返回第一步
任务阻塞流程是:当前任务(最高优先级)进入阻塞 ->
                        调用vTaskSwitchContext交出CPU使用权 ->
                        vTaskSwitchContext遍历就绪任务链表数组,从当前优先级开始往下查找下一个就绪任务 ->
                        查找到就绪任务,修正uxTopReadyPriority的值 ->
                        切换到就绪任务

由于我手头上的F0单片机资源有限(只有4KB的SRAM),因此我只用了2个任务做测试,优先级分别为2、9
当优先级为9的任务进入阻塞时,uxTopReadyPriority的值并不会立刻改变,而是先遍历就绪任务链表数组,直到数组元素为2才停止
到此整个任务最高优先级uxTopReadyPriority的值的修改过程已清晰了





作者: FreeRTOS    时间: 2017-3-15 11:29
yuer19900712 发表于 2017-3-14 20:10
这个代码已经找到了,举一个简单例子。比如释放信号量的过程
[mw_shl_code=c,true]#definexSemaphoreGi ...

至于你昨天说的200-1和10-1的测试,应该是测试的方法不对吧,否则10-1的时间应该会更短
作者: chenjiabao1994    时间: 2017-5-18 17:57
我学的嵌入式怎么和你们的不太一样。程序不都是WHILE(1)循环查看标志位+中断程序吗
作者: 一介    时间: 2017-6-9 13:48
@FreeRTOS @yuer19900712 @charlefu 膜拜几位大神
作者: 炫色康康    时间: 2017-7-25 19:23
支持一下
作者: wlq19911021    时间: 2017-8-7 02:03
做推广的么?这战打的很有意思,目的性很强
作者: wlq19911021    时间: 2017-8-7 02:08
FreeRTOS 发表于 2016-7-22 09:09
2015年freertos的市场占有率已经超过了ucos,并跻身嵌入式系统领域榜首了

有意思没有呢?
作者: wlq19911021    时间: 2017-8-7 02:10
FreeRTOS 发表于 2017-3-15 11:29
至于你昨天说的200-1和10-1的测试,应该是测试的方法不对吧,否则10-1的时间应该会更短

做好你的推广就是了,非要带着火药味
作者: FreeRTOS    时间: 2017-8-7 08:13
wlq19911021 发表于 2017-8-7 02:10
做好你的推广就是了,非要带着火药味

你说这话就明显带着火药味了,还有资格喷别人?
想教训我请拿出你的实力,本人不接受无脑喷,抱歉!
作者: 想你ing    时间: 2017-8-13 09:04
萌新弱弱问一句,嵌入式linux操作系统现在还是主流吗
作者: Morton    时间: 2017-8-25 18:30
mark!:lol:lol:lol:lol
作者: 三生有幸    时间: 2017-9-1 11:33
现在freertos越来越成熟,今后用的肯定越来越多的
作者: zym1010    时间: 2017-9-1 14:56
chenjiabao1994 发表于 2017-5-18 17:57
我学的嵌入式怎么和你们的不太一样。程序不都是WHILE(1)循环查看标志位+中断程序吗

你说的是裸奔,这个是跑系统
作者: richishion    时间: 2017-9-1 16:52
FreeRTOS 发表于 2016-7-22 09:09
2015年freertos的市场占有率已经超过了ucos,并跻身嵌入式系统领域榜首了

支持!
作者: 领悟    时间: 2017-10-10 16:19
我没有操作系统的概念 怎么弄   看内核 看不懂 ?
作者: 领悟    时间: 2017-10-10 16:22
学习FreeRTOS 前期需要看什么书籍  现在看代码怎么看不懂
作者: 炫色康康    时间: 2017-11-19 10:07
现在一直用Freertos
作者: 1547674987    时间: 2017-12-12 17:34
神秘狼 发表于 2016-10-1 09:26
ucosiii是专门为了cortex核写的 用了计算前导零汇编指令,任务切换要快许多  我对free不太了解,请问free用 ...

我刚了看源码,我可以肯定的告诉你FreeRTOS在找最高优先级任务的时候既可以用通用的方法,也可以用CLZ快速定位,用CLZ优点是速度快很多,缺点是优先级只能有32级。
作者: 炫色康康    时间: 2018-2-27 21:13
支持,最近使用freertos感觉问题多多啊,最好有些具体项目可以学习
作者: pryprypry    时间: 2018-3-22 03:23
FreeRTOS 发表于 2016-7-22 09:09
2015年freertos的市场占有率已经超过了ucos,并跻身嵌入式系统领域榜首了

FreeRTOS好像在市占率上早就秒杀了其他OS。内核基本上没槽点,速度很快,基本上是最快的。
作者: wen619    时间: 2018-3-22 08:54
帮顶这样的帖子
作者: wen619    时间: 2018-3-25 19:07
FreeRTOS 发表于 2016-10-3 18:32
freertos使用一个结构体数组 PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ] ...

首先谢谢楼主无私奉献对内核的讲解。如你本帖举例,那么五个就绪列表元素pxReadyTasksLists[4]到pxReadyTasksLists[0]就永远要么有0个列表项(我理解xListEnd这个列表项不计入这个列表含有的列表项数目),要么就只有一个:本优先级就绪的那个任务对应的列表项。对吧 这样理解?我的第一个问题是内核什么时候把这个列表项插入这个优先级对应的列表的?我第二个问题是本优先级的其它非就绪任务(好像有阻塞,挂起等?)所对应的列表项也是放在某些列表中的吗?这些列表有哪些?在哪里啊?内核又是如何管理这些不同优先级不同状态的任务呢?靠列表管理吗?列表插入与删除这些代表不同优先级不同状态任务的列表项体现在代码何处? 谢谢了先!
作者: wen619    时间: 2018-3-26 19:22
1547674987 发表于 2017-12-12 17:34
我刚了看源码,我可以肯定的告诉你FreeRTOS在找最高优先级任务的时候既可以用通用的方法,也可以用CLZ快 ...

是的 任务创建 函数里面 有个子函数里面用到了前导0指令
作者: wen619    时间: 2018-3-30 10:19
FreeRTOS 发表于 2017-3-14 17:41
根据坛友的指引,终于在FreeRTOS里面找到了这个传说中的CLZ了
原来FreeRTOS的任务切换是根据该宏来选择的 ...

嗯我也看到了 这段使用硬件方法寻找下一个最高优先级的任务,在任务切换那节视频3里讲到过
作者: haozhengnaxi    时间: 2018-7-12 15:13
FreeRTOS 发表于 2016-10-2 21:23
查了下权威指南,先放上CLZ的定义吧

再放上一个例子:

虽然没全部看懂,但还是要顶一下
作者: 32shixisheng    时间: 2018-7-27 17:25
FreeRTOS 发表于 2017-3-14 17:20
群里的高手还是很多呵,都研究得很深入,有机会多多交流

你们知道吗,我一个小白,把这个帖子从头看到尾,还看的特别带劲,虽然不知道你们说啥,就有种特别崇拜的感觉,果然都是大神级别的。上小生,好生羡慕!!!




欢迎光临 OpenEdv-开源电子网 (http://www.openedv.com/) Powered by Discuz! X3.2
/* */