[求助] 关于FreeRTOS的应用及其在MSP430上移植的问题

witant   2012-8-17 08:32 楼主
最近想研究一下FreeRTOS,于是下载了7.1.1版本的内核。用IAR编译MSP430相关代码后再MSP430f149上运行良好(LED闪的挺欢快~其它功能还没有测试,刚刚接触FreeRTOS)。
但是由于f149的RAM太小,决定将其移植到更大RAM的单片机上,正好手头有块MSP430f5438的板子,便将程序改了改烧写到上面,但这次出现了问题,程序各种跑飞。研究了半天才发现5系列的430单片机地址是20位的(4系列是16位),而且增加了不少汇编指令。经过测试,将原来portext.s43文件中的call指令换成calla指令问题貌似就解决了,程序又可以正常运行了。示例代码里面本身就有支持20位地址的相关代码,在“FreeRTOSV7.1.1\Source\portable\IAR”目录下的MSP430X这个文件夹里面,只不过我太粗心,之后才发现。
我想把FreeRTOS移植到430上面主要是想利用其时间片轮转的工作方式。只需要最基本的内核服务即可。
现在想请教大家一下:
1.FreeRTOS在MSP430里面的应用多么,如果作为一个长期工作的设备,里面跑FreeRTOS的话稳定性如何?
2.以上我说的移植方法是否合理呢?
因为本人接触FreeRTOS时间很短,只知道它内核很精简,比较适合移植到MSP430这类RAM比较小的单片机上。望大家不吝赐教。

[ 本帖最后由 witant 于 2012-8-17 09:28 编辑 ]

回复评论 (4)

楼主是否可以共享代码呢,与UCOS与FreeRtos比较一下?目前看到比较多的是UCOS,在Micrium的官网可以下载到MSP430的UCOS ||的参考代码
点赞  2012-8-21 01:09

回复 沙发 hansonhe 的帖子

uCOS-II的测试代码在http://micrium.com/page/downloads/ports/ti/msp430下载
FreeRTOS的在http://sourceforge.net/projects/freertos/files/下载(已经更新到7.2了)

关于代码,先比较下内核中的任务调度部份,由于涉及到对堆栈指针sp的操作,该部份代码是采用汇编语言编写的。

uCOS-II的TICK ISR函数(位于os_cpu_a.s43文件):

WDT_ISR                                 ; wd timer ISR
    PUSHM.A     #12, R15
    BIC.W       #0x01, SFRIE1           ; disable wd timer interrupt
    CMP.B       #0, &OSIntNesting       ; if (OSIntNesting == 0)
    JNE         WDT_ISR_1
    MOVX.A      &OSTCBCur, R13          ;     save task stack
    MOVX.A      SP, 0(R13)
    MOVX.A      &OSISRStkPtr, SP        ;     load interrupt stack
WDT_ISR_1
    INC.B       &OSIntNesting           ; increase OSIntNesting   
    BIS.W       #0x01, SFRIE1           ; enable wd timer interrupt
    EINT                                ; enable general interrupt to allow for interrupt nesting
    CALLA       #OSTimeTick             ; call ticks routine
    DINT                                ; IMPORTANT: disable general interrupt BEFORE calling OSIntExit()
    CALLA       #OSIntExit
    CMP.B       #0, &OSIntNesting       ; if (OSIntNesting == 0)
    JNE         WDT_ISR_2
    MOVX.A      &OSTCBHighRdy, R13      ;     restore task stack SP
    MOVX.A      @R13, SP
WDT_ISR_2
    POPM.A      #12, R15
    RETI                                ; return from interrupt

FreeRTOS 7.1.1中的vPortTickISR函数(位于portext.s43文件)
vPortTickISR:
   
    /* The sr is not saved in portSAVE_CONTEXT() because vPortYield() needs
    to save it manually before it gets modified (interrupts get disabled). */
    push.w sr
    portSAVE_CONTEXT
               
    calla    #vTaskIncrementTick

    #if configUSE_PREEMPTION == 1
        calla    #vTaskSwitchContext
    #endif
        
    portRESTORE_CONTEXT

FreeRTOS代码中含有宏定义且功能略少,因此显得比较精简。两内核的任务调度原理是一致的:
1.当某个任务正在运行时产生了systick中断(即某个定时器中断),此时堆栈指针(SP)是指向该任务自身堆栈区的
2.进入中断后将对状态寄存器(SR)、程序指针(PC)、以及通用寄存器(R4~R15)进行入栈操作,该任务的运行状态就被保存到自身的堆栈区了
3.进行任务调度算法。内核对系统时间进行更新,在就绪任务中选择一个作为下一个时间片要执行的任务,并将该任务的堆栈地址赋给堆栈指针(SP)
4.此时的堆栈指针已经指向需要执行的任务了,将堆栈中存储的寄存器值逐个读取到各个寄存器中,中断返回时,程序指针(PC)从堆栈中读取了当前任务的地址,单片机便开始运行该任务的代码。

个人感觉两个内核的任务调度原理是一致的,不同之处在于各自的调度算法。

关于两个系统的比较可以参考FreeRTOS 和uCOS II的简单比较

在内核的应用上两个系统的差别不大,我举个很简单的例子:建立两个任务并开始任务调度。
uCOS-II:

#include

static  OS_STK      AppTask1Stk[APP_TASK1_STK_SIZE];
static  OS_STK      AppTask2Stk[APP_TASK2_STK_SIZE];

static  void  AppTask1      (void        *p_arg);
static  void  AppTask2      (void        *p_arg);
void  main (void)
{
    OSInit();                                                           /* Initialize "uC/OS-II, The Real-Time Kernel"  */
    OSTaskCreateExt(AppTask1,                                           /* Create start task 1   */
                   (void *)0,
                   (OS_STK *)&AppTask1Stk[APP_TASK1_STK_SIZE - 1],
                    APP_START_TASK1_PRIO,
                    APP_START_TASK1_PRIO,
                   (OS_STK *)&AppTask1Stk[0],
                    APP_TASK1_STK_SIZE,
                   (void *)0,
                    OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);                    
    OSTaskCreateExt(AppTask2,                                           /* Create start task 2  */
                   (void *)0,
                   (OS_STK *)&AppTask2Stk[APP_TASK2_STK_SIZE - 1],
                    APP_START_TASK2_PRIO,
                    APP_START_TASK2_PRIO,
                   (OS_STK *)&AppTask2Stk[0],
                    APP_TASK2_STK_SIZE,
                   (void *)0,
                    OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);
    OSStart();                                                          /* Start multitasking (i.e. give control to uC/OS-II)       */
}

FreeRTOS:
#include "FreeRTOS.h"
#include "task.h"
#include "FreeRTOSConfig.h"
int main( void )
{
        /* Setup the hardware ready for the demo. */
        prvSetupHardware();

        xTaskCreate(task1, "task1", 50, NULL, 2, NULL );       
        xTaskCreate( task2, "task2", 50, NULL, 2, NULL );
        /* Start the scheduler. */
        vTaskStartScheduler();

        return 0;
}
可见两个内核在应用时都是先创建任务,然后开始任务调度的,不同之处在于uCOS-II是显示分配堆栈空间,FreeRTOS是系统自动分配。在其它内核服务(如消息队列、信号量等)的应用上只是函数名称不同,功能上是十分相似的。

个人认为uCOS和FreeRTOS在应用上各有利弊,uCOS功能强大(相对FreeRTOS),而FreeRTOS代码精简,内存占用量很小。本人就是因为想学习一下多任务系统的开发(在MSP430平台)才开始接精简的触嵌入式内核的,由于强大的uCOS为开源收费且不支持相同优先级任务(uCOS-III已经没有这个限制了),综合考虑之下还是选择了FreeRTOS,本想上来问问有没有人做过FreeRTOS的项目及其运行效果,结果没人回答。
以上是本人对两个系统内核的理解,如有不妥之处还望大家多多指正。如果有人做过FreeRTOS的项目,望不吝赐教,为小弟指点一二
点赞  2012-8-23 09:42
uCOS的中断函数在IAR中要用汇编编写,那么FreeRTOS终端函数也是用汇编编写吗?
菜鸟一枚对于汇编没什么概念,只懂皮毛,所以就想找一种可以使用C语言编写的RTOS。
点赞  2015-1-21 14:42
在CCS下有移植过么?求助
点赞  2015-9-1 15:21
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复