OpenEdv-开源电子网

 找回密码
 立即注册

扫一扫,访问微社区

正点原子新作:阿波罗STM32F767&F429&探索者STM32F4开发板&赶快来下载资料哦。

12
返回列表 发新帖
楼主: 小竹新语

希望原子哥搞个FreeRTOS的板块,这个操作系统比ucos用的多啊

[复制链接]

  离线 

12

主题

53

帖子

0

精华

初级会员

Rank: 2

积分
85
金钱
85
注册时间
2017-3-14
在线时间
18 小时
发表于 2017-3-14 17:39:32 | 显示全部楼层
正点原子公众号
FreeRTOS 发表于 2017-3-14 17:11
至于你贴的链接,我大概看了下,作者的意思是说通过特殊方法也是可以使用CLZ来查找最高优先级任务的,
我 ...

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

使用道具 举报

  离线 

23

主题

648

帖子

0

精华

版主

Rank: 7Rank: 7Rank: 7

积分
2958
金钱
2958
注册时间
2015-11-5
在线时间
942 小时
发表于 2017-3-14 17:41:19 | 显示全部楼层
根据坛友的指引,终于在FreeRTOS里面找到了这个传说中的CLZ了
原来FreeRTOS的任务切换是根据该宏来选择的:configUSE_PORT_OPTIMISED_TASK_SELECTION
当该宏被定义后,任务切换就会执行以下的代码来获取最高优先级: 2.PNG

其中真正实现最高优先级查找的是这条语句:
3.PNG
里面就调用了CLZ指令,当然这只支持具有CLZ指令的芯片。。。
生活不只有眼前的苟且,还有你看不懂的诗和永远到不了的远方!
回复

使用道具 举报

  离线 

12

主题

53

帖子

0

精华

初级会员

Rank: 2

积分
85
金钱
85
注册时间
2017-3-14
在线时间
18 小时
发表于 2017-3-14 17:53:18 | 显示全部楼层
本帖最后由 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:\新建文件夹

启动定时器

启动定时器

获取时钟周期个数

获取时钟周期个数
回复

使用道具 举报

  离线 

23

主题

648

帖子

0

精华

版主

Rank: 7Rank: 7Rank: 7

积分
2958
金钱
2958
注册时间
2015-11-5
在线时间
942 小时
发表于 2017-3-14 18:17:42 | 显示全部楼层
本帖最后由 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 )
而函数里面对最高优先级的变量做了处理:
4.PNG

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

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

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




生活不只有眼前的苟且,还有你看不懂的诗和永远到不了的远方!
回复

使用道具 举报

  离线 

12

主题

53

帖子

0

精华

初级会员

Rank: 2

积分
85
金钱
85
注册时间
2017-3-14
在线时间
18 小时
发表于 2017-3-14 19:06:00 | 显示全部楼层
本帖最后由 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咋变回来的????
回复

使用道具 举报

  离线 

23

主题

648

帖子

0

精华

版主

Rank: 7Rank: 7Rank: 7

积分
2958
金钱
2958
注册时间
2015-11-5
在线时间
942 小时
发表于 2017-3-14 19:59:42 | 显示全部楼层
yuer19900712 发表于 2017-3-14 19:06
这个你还是应该再看看吧,说的不全对,这还是在特殊处理方式中的,因为CLZ就是用一个bit来当做一个任务的 ...

我就是在说明在普通情况下任务阻塞时并没有更新这个变量嘛。。
这么晚了还在工作,果然是狂热者我明天上班再查看下源码,这个问题应该比较好解决
生活不只有眼前的苟且,还有你看不懂的诗和永远到不了的远方!
回复

使用道具 举报

  离线 

12

主题

53

帖子

0

精华

初级会员

Rank: 2

积分
85
金钱
85
注册时间
2017-3-14
在线时间
18 小时
发表于 2017-3-14 20:10:50 | 显示全部楼层
本帖最后由 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,找到最终的代码,会看见就绪最高优先级任务被修改了。回家再贴上详细的。下班
回复

使用道具 举报

  离线 

23

主题

648

帖子

0

精华

版主

Rank: 7Rank: 7Rank: 7

积分
2958
金钱
2958
注册时间
2015-11-5
在线时间
942 小时
发表于 2017-3-15 11:22:20 | 显示全部楼层
本帖最后由 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 );

这里才是关键,下面是这个宏的展开:
1.PNG
里面有我们最最熟悉的重新记录最高的优先级:
[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的值的修改过程已清晰了




生活不只有眼前的苟且,还有你看不懂的诗和永远到不了的远方!
回复

使用道具 举报

  离线 

23

主题

648

帖子

0

精华

版主

Rank: 7Rank: 7Rank: 7

积分
2958
金钱
2958
注册时间
2015-11-5
在线时间
942 小时
发表于 2017-3-15 11:29:08 | 显示全部楼层
yuer19900712 发表于 2017-3-14 20:10
这个代码已经找到了,举一个简单例子。比如释放信号量的过程
[mw_shl_code=c,true]#definexSemaphoreGi ...

至于你昨天说的200-1和10-1的测试,应该是测试的方法不对吧,否则10-1的时间应该会更短
生活不只有眼前的苟且,还有你看不懂的诗和永远到不了的远方!
回复

使用道具 举报

  离线 

3

主题

6

帖子

0

精华

新手上路

Rank: 1

积分
15
金钱
15
注册时间
2017-3-7
在线时间
1 小时
发表于 2017-5-18 17:57:25 | 显示全部楼层
我学的嵌入式怎么和你们的不太一样。程序不都是WHILE(1)循环查看标志位+中断程序吗
回复

使用道具 举报

  离线 

0

主题

1

帖子

0

精华

初级会员

Rank: 2

积分
62
金钱
62
注册时间
2017-6-9
在线时间
5 小时
发表于 2017-6-9 13:48:31 | 显示全部楼层
@FreeRTOS @yuer19900712 @charlefu 膜拜几位大神
回复

使用道具 举报

  离线 

6

主题

154

帖子

0

精华

高级会员

Rank: 4

积分
631
金钱
631
注册时间
2015-5-8
在线时间
112 小时
发表于 2017-7-25 19:23:10 | 显示全部楼层
支持一下
回复

使用道具 举报

  离线 

2

主题

210

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
320
金钱
320
注册时间
2017-6-18
在线时间
65 小时
发表于 2017-8-7 02:03:39 来自手机 | 显示全部楼层
做推广的么?这战打的很有意思,目的性很强
回复

使用道具 举报

  离线 

2

主题

210

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
320
金钱
320
注册时间
2017-6-18
在线时间
65 小时
发表于 2017-8-7 02:08:12 来自手机 | 显示全部楼层
FreeRTOS 发表于 2016-7-22 09:09
2015年freertos的市场占有率已经超过了ucos,并跻身嵌入式系统领域榜首了

有意思没有呢?
回复

使用道具 举报

  离线 

2

主题

210

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
320
金钱
320
注册时间
2017-6-18
在线时间
65 小时
发表于 2017-8-7 02:10:47 来自手机 | 显示全部楼层
FreeRTOS 发表于 2017-3-15 11:29
至于你昨天说的200-1和10-1的测试,应该是测试的方法不对吧,否则10-1的时间应该会更短

做好你的推广就是了,非要带着火药味
回复

使用道具 举报

  离线 

23

主题

648

帖子

0

精华

版主

Rank: 7Rank: 7Rank: 7

积分
2958
金钱
2958
注册时间
2015-11-5
在线时间
942 小时
发表于 2017-8-7 08:13:45 | 显示全部楼层
wlq19911021 发表于 2017-8-7 02:10
做好你的推广就是了,非要带着火药味

你说这话就明显带着火药味了,还有资格喷别人?
想教训我请拿出你的实力,本人不接受无脑喷,抱歉!
生活不只有眼前的苟且,还有你看不懂的诗和永远到不了的远方!
回复

使用道具 举报

  离线 

0

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
115
金钱
115
注册时间
2017-7-22
在线时间
13 小时
发表于 2017-8-13 09:04:59 来自手机 | 显示全部楼层
萌新弱弱问一句,嵌入式linux操作系统现在还是主流吗
回复

使用道具 举报

  离线 

0

主题

10

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
252
金钱
252
注册时间
2016-11-16
在线时间
25 小时
发表于 2017-8-25 18:30:15 | 显示全部楼层
mark!:lol:lol:lol:lol
回复

使用道具 举报

  离线 

0

主题

1

帖子

0

精华

新手上路

Rank: 1

积分
40
金钱
40
注册时间
2017-7-10
在线时间
8 小时
发表于 2017-9-1 11:33:03 | 显示全部楼层
现在freertos越来越成熟,今后用的肯定越来越多的
回复

使用道具 举报

  离线 

0

主题

1

帖子

0

精华

新手上路

Rank: 1

积分
2
金钱
2
注册时间
2017-9-1
在线时间
0 小时
发表于 2017-9-1 14:56:22 | 显示全部楼层
chenjiabao1994 发表于 2017-5-18 17:57
我学的嵌入式怎么和你们的不太一样。程序不都是WHILE(1)循环查看标志位+中断程序吗

你说的是裸奔,这个是跑系统
回复

使用道具 举报

  离线 

0

主题

2

帖子

0

精华

初级会员

Rank: 2

积分
100
金钱
100
注册时间
2017-9-1
在线时间
9 小时
发表于 2017-9-1 16:52:28 | 显示全部楼层
FreeRTOS 发表于 2016-7-22 09:09
2015年freertos的市场占有率已经超过了ucos,并跻身嵌入式系统领域榜首了

支持!
回复

使用道具 举报

  离线 

1

主题

9

帖子

0

精华

新手上路

Rank: 1

积分
43
金钱
43
注册时间
2017-10-6
在线时间
4 小时
发表于 2017-10-10 16:19:50 | 显示全部楼层
我没有操作系统的概念 怎么弄   看内核 看不懂 ?
回复

使用道具 举报

  离线 

1

主题

9

帖子

0

精华

新手上路

Rank: 1

积分
43
金钱
43
注册时间
2017-10-6
在线时间
4 小时
发表于 2017-10-10 16:22:41 | 显示全部楼层
学习FreeRTOS 前期需要看什么书籍  现在看代码怎么看不懂
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则




QQ|联系我们|手机版|官方淘宝店|新浪微博|微信公众平台|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2017-11-18 22:12

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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