打印
[应用相关]

大家来献策, 为STM32打造一个高效精炼的RTOS

[复制链接]
楼主: airwill
手机看帖
扫描二维码
随时随地手机跟帖
41
z755924843| | 2014-2-21 10:04 | 只看该作者 回帖奖励 |倒序浏览
学习中,正在看ucosii,看了两遍Cortex-M3 权威指南 ,说实话如果stm32不跑RTOS感觉真的是大才小用了。

使用特权

评论回复
42
天高任鸟飞| | 2014-2-21 10:07 | 只看该作者
:)

使用特权

评论回复
43
lofky| | 2014-2-21 10:28 | 只看该作者
学习   

使用特权

评论回复
44
kangxuebin| | 2014-2-21 10:52 | 只看该作者
学习学习   

使用特权

评论回复
45
anybody| | 2014-2-21 10:59 | 只看该作者
状态机加中断的效果感觉比操作系统强,就是软件编写麻烦些。

使用特权

评论回复
46
myxiaonia| | 2014-2-21 13:26 | 只看该作者
yjwpm 发表于 2014-2-20 14:55
至于OS这方面,你要自己打造的话,我先给你泼一盆冷水,如果说你的OS能超越RT-Thread的话,那你可以做,如 ...

有道理  建议对其中一个作出分析  比自己再造个轮子可能更有意义些

使用特权

评论回复
47
airwill|  楼主 | 2014-2-21 14:44 | 只看该作者
本帖最后由 airwill 于 2014-2-21 21:42 编辑
lxyppc 发表于 2014-2-20 21:29
希望能够尽最大程度的可裁剪
必要时tick中断也可以裁掉


不错的想法, 只是其实 RTOS 的核心就是 CPU 时间资源的管理, 如果 tick 中断也裁剪了, 那么任务延时功能也就没有了, 这可是任务主动释放CPU控制权的主要途径.
所以通常 OS 都不会允许裁剪 tick 中断

今天打开 freeRTOS 看看: 这是个任务控制块的结构体, 包含的内容不少.

typedef struct tskTaskControlBlock
{
volatile portSTACK_TYPE *pxTopOfStack;  /*< Points to the location of the last item placed on the tasks stack.  THIS MUST BE THE FIRST MEMBER OF THE STRUCT. */
#if ( portUSING_MPU_WRAPPERS == 1 )
  xMPU_SETTINGS xMPUSettings;    /*< The MPU settings are defined as part of the port layer.  THIS MUST BE THE SECOND MEMBER OF THE STRUCT. */
#endif

xListItem    xGenericListItem; /*< List item used to place the TCB in ready and blocked queues. */
xListItem    xEventListItem;  /*< List item used to place the TCB in event lists. */
unsigned portBASE_TYPE uxPriority;   /*< The priority of the task where 0 is the lowest priority. */
portSTACK_TYPE   *pxStack;   /*< Points to the start of the stack. */
signed char    pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created.  Facilitates debugging only. */
#if ( portSTACK_GROWTH > 0 )
  portSTACK_TYPE *pxEndOfStack;   /*< Used for stack overflow checking on architectures where the stack grows up from low memory. */
#endif
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
  unsigned portBASE_TYPE uxCriticalNesting;
#endif
#if ( configUSE_TRACE_FACILITY == 1 )
  unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */
#endif
#if ( configUSE_MUTEXES == 1 )
  unsigned portBASE_TYPE uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
#endif
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
  pdTASK_HOOK_CODE pxTaskTag;
#endif
#if ( configGENERATE_RUN_TIME_STATS == 1 )
  unsigned long ulRunTimeCounter;  /*< Used for calculating how much CPU time each task is utilising. */
#endif
} tskTCB;

使用特权

评论回复
48
airwill|  楼主 | 2014-2-21 21:52 | 只看该作者
切换代码:

void xPortPendSVHandler( void )
{
        /* This is a naked function. */

        __asm volatile
        (
        "        mrs r0, psp                                                        \n"
        "                                                                                \n"
        "        ldr        r3, pxCurrentTCBConst                        \n" /* Get the location of the current TCB. */
        "        ldr        r2, [r3]                                                \n"
        "                                                                                \n"
        "        stmdb r0!, {r4-r11}                                        \n" /* Save the remaining registers. */
        "        str r0, [r2]                                                \n" /* Save the new top of stack into the first member of the TCB. */
        "                                                                                \n"
        "        stmdb sp!, {r3, r14}                                \n"
        "        mov r0, %0                                                        \n"
        "        msr basepri, r0                                                \n"
        "        bl vTaskSwitchContext                                \n"
        "        mov r0, #0                                                        \n"
        "        msr basepri, r0                                                \n"
        "        ldmia sp!, {r3, r14}                                \n"
        "                                                                                \n"        /* Restore the context, including the critical nesting count. */
        "        ldr r1, [r3]                                                \n"
        "        ldr r0, [r1]                                                \n" /* The first item in pxCurrentTCB is the task top of stack. */
        "        ldmia r0!, {r4-r11}                                        \n" /* Pop the registers. */
        "        msr psp, r0                                                        \n"
        "        bx r14                                                                \n"
        "                                                                                \n"
        "        .align 2                                                        \n"
        "pxCurrentTCBConst: .word pxCurrentTCB        \n"
        ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY)
        );
}

见 FreeRTOS V6.0.4 port.c, 其中的 vTaskSwitchContext 函数

void vTaskSwitchContext( void )
{
        if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE )
        {
                /* The scheduler is currently suspended - do not allow a context
                switch. */
                xMissedYield = pdTRUE;
                return;
        }

        traceTASK_SWITCHED_OUT();

        #if ( configGENERATE_RUN_TIME_STATS == 1 )
        {
                unsigned long ulTempCounter = portGET_RUN_TIME_COUNTER_VALUE();

                        /* Add the amount of time the task has been running to the accumulated
                        time so far.  The time the task started running was stored in
                        ulTaskSwitchedInTime.  Note that there is no overflow protection here
                        so count values are only valid until the timer overflows.  Generally
                        this will be about 1 hour assuming a 1uS timer increment. */
                        pxCurrentTCB->ulRunTimeCounter += ( ulTempCounter - ulTaskSwitchedInTime );
                        ulTaskSwitchedInTime = ulTempCounter;
        }
        #endif

        taskFIRST_CHECK_FOR_STACK_OVERFLOW();
        taskSECOND_CHECK_FOR_STACK_OVERFLOW();

        /* Find the highest priority queue that contains ready tasks. */
        while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) )
        {
                --uxTopReadyPriority;
        }

        /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the tasks of the
        same priority get an equal share of the processor time. */
        listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) );

        traceTASK_SWITCHED_IN();
        vWriteTraceToBuffer();
}

见 FreeRTOS V6.0.4 tasks.c

使用特权

评论回复
49
john_lee| | 2014-2-22 01:05 | 只看该作者
airwill 发表于 2014-2-21 14:44
不错的想法, 只是其实 RTOS 的核心就是 CPU 时间资源的管理, 如果 tick 中断也裁剪了, 那么任务延时功能 ...

系统节拍作为调度源之一,在几乎所有的 RTOS 中都存在,但在理论上它确实不是 RTOS 的必要组成部分。绝大多数应用的事件处理中,都需要一些用时间事件来作为同步(各种延时、超时等等),而缺了系统节拍的 RTOS,对这类应用而言,它的适用性就非常差了。所以,是否把系统节拍服务也纳入 RTOS 的伸缩性设计,就见仁见智了。
freertos 的 tcb,也不能算是臃肿,刨去那些可以通过宏定义裁剪掉的部分,就只有 pcTaskName 算是多余的。
如果还想继续减肥,就要改动设计了,改动后还可以省掉 xEventListItem,和 pxStack。当然,如果改用固定优先级调度算法的话,xGenericListItem 也是可以砍掉的。

使用特权

评论回复
50
jlwg| | 2014-2-22 09:34 | 只看该作者
竟然在讨论去掉os的节拍,都是一群牛人啊,没有节拍还能叫操作系统吗?世界上存在没有节拍的操作系统吗?哪位牛人给举个例子?就像一个人,存在一个没有心脏的活人吗?都讨论出笑话来了,还在装模做样地讨论.都牛到什么程度了,屌炸天了.

使用特权

评论回复
51
明月小厨| | 2014-2-22 12:15 | 只看该作者
STM32F后续系列中有大量的定时器。如果任务不是很多的话,用定时器自己解决多任务的问题。例:
1个定时器负责扫描键盘,另一个负责显示刷新;我只是举例。不一定非要上操作系统。

使用特权

评论回复
52
dong_abc| | 2014-2-22 14:06 | 只看该作者
本帖最后由 dong_abc 于 2014-2-22 14:14 编辑


null

使用特权

评论回复
53
airwill|  楼主 | 2014-2-22 15:58 | 只看该作者
jlwg 发表于 2014-2-22 09:34
竟然在讨论去掉os的节拍,都是一群牛人啊,没有节拍还能叫操作系统吗?世界上存在没有节拍的操作系统吗?哪位牛 ...

是啊, 真是一个新奇的想法. 也是我从来都没有想到过的.

再有: to 51 楼.
键盘扫描放在定时中断里, 其实并不是一个好办法.通常对于复杂一些的系统, 我们还是希望把中断服务尽量做得简单一些. 中断的优先级有限, 所以全部采用复杂的中断服务往往反而不能满足系统实时要求

使用特权

评论回复
54
呆板书生| | 2014-2-22 19:54 | 只看该作者
mark

使用特权

评论回复
55
lxyppc| | 2014-2-23 00:03 | 只看该作者
jlwg 发表于 2014-2-22 09:34
竟然在讨论去掉os的节拍,都是一群牛人啊,没有节拍还能叫操作系统吗?世界上存在没有节拍的操作系统吗?哪位牛 ...

呵呵,只是提供一个想法而已,大家讨论讨论
如果能去掉tick,那么在做低功耗的时候
可以不用以tick周期的方式唤醒mcu,让功耗更低

使用特权

评论回复
评论
john_lee 2014-2-23 00:27 回复TA
同意 
56
jlwg| | 2014-2-23 09:55 | 只看该作者
lxyppc 发表于 2014-2-23 00:03
呵呵,只是提供一个想法而已,大家讨论讨论
如果能去掉tick,那么在做低功耗的时候
可以不用以tick周期的 ...

不要继续这么顽固地在这个问题上扯淡了.刚才都说了,正常的软件系统,提供两级实时性,一个是操作系统的任务切换,一个就是中断, 操作系统也可以把全部中断纳入管理,也并不妨碍省电模式.您可以参考keil 的mdk5中的rtos的tick_less模式.那个也不是去掉tick ,而是在tick和tick_less模式间切换,即享受操作系统的好处,也可以不影响待机功耗.


使用特权

评论回复
57
呆板书生| | 2014-2-23 10:57 | 只看该作者
有人批评我只写一个mark,那我就谈谈我的看法

我个人认为,与其争论如何写操作系统好,不如大家把现有的os都用一下,把例程发上来,看看有什么好处。

有人说,不用OS也行,可以用状态机+时钟中断,但不用os,就要全部用非阻塞函数,

简单说,状态机的状态枚举,和非阻塞函数,代码都不如os那么直观

使用特权

评论回复
58
lxyppc| | 2014-2-23 11:20 | 只看该作者
用不用tick是由应用决定,而非操作系统
没有用到超时之类的东西,完全可以不要tick
在不需要超时的应用中,由tick导致的任务切换,带来并非是实时性
只是同级任务间的一种交替执行方式

实时性,是由其他中断产生的任务切换来保证的
并且这种切换是抢占性质的

ps
tick也会导致抢占的发生,比如一个高优先级的任务的超时时间到了。
这种情况的产生,是由应用决定的

使用特权

评论回复
评论
rtgchym 2014-2-24 09:17 回复TA
这个说的很有道理 
59
jlwg| | 2014-2-23 11:38 | 只看该作者
lxyppc 发表于 2014-2-23 11:20
用不用tick是由应用决定,而非操作系统
没有用到超时之类的东西,完全可以不要tick
在不需要超时的应用中, ...

不是什么决定不决定,,无论你想不想用,只要用操作系统,就会有tick这么简单的道理还需要辩来辩去,真是无聊.

使用特权

评论回复
60
jlwg| | 2014-2-23 11:41 | 只看该作者
呆板书生 发表于 2014-2-23 10:57
有人批评我只写一个mark,那我就谈谈我的看法

我个人认为,与其争论如何写操作系统好,不如大家把现有的os ...

其实,认真讨论什么用不用os的,甚至什么需不需要tick 的  ,基本上都是水平不高的初学者.有点经验经历的人,都会觉得这个话题有些无聊.

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则