现在的位置: 首页 > 综合 > 正文

UCOS-II在LPC2210上的移植--OS_CPU_c.c

2013年09月09日 ⁄ 综合 ⁄ 共 6655字 ⁄ 字号 评论关闭

UCOS-II在LPC2210上的移植--OS_CPU_c.c

CPU: Philips ARM7 LPC2210
OS: uC/OS-II 2.52
IDE: ADS 1.2

移植一个操作系统到一个CPU体系的结构上,移植者必须的要求:
1、对目标体系结构要有很深的了解 -- ARM Architecture Reference Manual
2、对OS原理要有较深入的了解 -- 嵌入式实时操作系统uC/OS-II
3、对所使用的编译器要有较深入的了解 -- ADS自带的编译器和连接器的手册
4、对需要移植的操作系统要有相当的了解 -- 嵌入式实时操作系统uC/OS-II
5、对具体使用的芯片也要有一定的了解 -- 芯片的数据手册

编写 OS_CPU_c.c

#define  OS_CPU_GLOBALS
#include "config.h"

/*********************************************************************************************************
** 函数名称: OSTaskStkInit
** 功能描述: 任务堆栈初始化代码,本函数调用失败会使系统崩溃
** 输 入: task  : 任务开始执行的地址
**         pdata :传递给任务的参数
**         ptos  :任务的堆栈开始位置
**         opt   :附加参数,当前版本对于本函数无用,具体意义参见OSTaskCreateExt()的opt参数
** 输 出: 栈顶指针位置
** 全局变量:
** 调用模块:
********************************************************************************************************/

        OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
{
    OS_STK *stk;

    opt    = opt;                           /* 'opt'  没有使用。作用是避免编译器警告    */
    stk    = ptos;                          /* 获取堆栈指针                                       */

                                            /* 建立任务环境,ADS1.2使用满递减堆栈       */
    *stk = (OS_STK) task;                   /*  PC( R15 )  */
    *--stk = (OS_STK) task;                 /*  LR( R14 )  */

    *--stk = 0;                             /*  r12  */
    *--stk = 0;                             /*  r11  */
    *--stk = 0;                             /*  r10  */
    *--stk = 0;                             /*  r9   */
    *--stk = 0;                             /*  r8   */
    *--stk = 0;                             /*  r7   */
    *--stk = 0;                             /*  r6   */
    *--stk = 0;                             /*  r5   */
    *--stk = 0;                             /*  r4   */
    *--stk = 0;                             /*  r3   */
    *--stk = 0;                             /*  r2   */
    *--stk = 0;                             /*  r1   */
    *--stk = (unsigned int) pdata;          /*  r0,第一个参数使用R0传递   */
    *--stk = (USER_USING_MODE|0x00);     /*  spsr,允许 IRQ, FIQ 中断   */
    *--stk = 0;                             /*  关中断计数器OsEnterSum;    */

    return (stk);
}

/*********************************************************************************************************
** 函数名称: SWI_Exception
** 功能描述: 软中断异常处理程序,提供一些系统服务
**          
** 输 入:  SWI_Num:功能号
**          Regs[0] 为第一个参数,也是返回值
**          Regs[1] 为第二个参数
**          Regs[2] 为第三个参数
**          Regs[3] 为第四个参数
** 输 出: 根据功能而定
**        
** 全局变量: 无
** 调用模块: 无
**
********************************************************************************************************/
#if OS_SELF_EN > 0
extern int const _OSFunctionAddr[];
extern int const _UsrFunctionAddr[];
#endif
        void SWI_Exception(int SWI_Num, int *Regs)
{
    OS_TCB   *ptcb;
   
    switch(SWI_Num)
    {
        //case 0x00:                    /* 任务切换函数OS_TASK_SW,参考os_cpu_s.s文件     */
        //    break;
        //case 0x01:                    /* 启动任务函数OSStartHighRdy,参考os_cpu_s.s文件 */
        //    break;
/* 在ARM处理器核中断和开中断时,通过改变CPSR中的相应位实现。由于使用了软件中断,程序状态寄存器CPSR
   保存到SPSR中,软件中断退出时会将SPSR恢复到CPSR中,所以程序只需要改变SPSR中的相应控制位就可以了 */
        case 0x02:                      /* 关中断函数OS_ENTER_CRITICAL(),参考os_cpu.h文件 */
            __asm
            {
                MRS     R0, SPSR
                ORR     R0, R0, #NoInt  /* 禁止IRQ中断 */
                MSR     SPSR_c, R0
            }
            OsEnterSum++;               /* 中断嵌套计数器增加一 */
            break;
        case 0x03:                      /* 开中断函数OS_EXIT_CRITICAL(),参考os_cpu.h文件 */
            if (--OsEnterSum == 0)      /* 判断是否中断嵌套已经完了 */
            {
                __asm
                {
                    MRS     R0, SPSR
                    BIC     R0, R0, #NoInt /* 清楚IRQ标志,允许中断 */
                    MSR     SPSR_c, R0
                }
            }
            break;
#if OS_SELF_EN > 0
        case 0x40:
                                        /* 返回指定系统服务函数的地址       */
                                        /* 函数地址存于数组_OSFunctionAddr中*/
                                        /* 数组_OSFunctionAddr需要另外定义  */
                                        /* Regs[0] 为第一个参数,也是返回值 */
                                        /* Regs[1] 为第二个参数             */
                                        /* Regs[2] 为第三个参数             */
                                        /* Regs[3] 为第四个参数             */
                                        /* 仅有一个参数为系统服务函数的索引 */
            Regs[0] =  _OSFunctionAddr[Regs[0]];
            break;
        case 0x41:
                                        /* 返回指定用户的服务函数的地址     */
                                        /* 函数地址存于数组_UsrFunctionAddr中*/
                                        /* 数组_UsrFunctionAddr需要另外定义 */
                                        /* Regs[0] 为第一个参数,也是返回值 */
                                        /* Regs[1] 为第二个参数             */
                                        /* Regs[2] 为第三个参数             */
                                        /* Regs[3] 为第四个参数             */
                                        /* 仅有一个参数为用户服务函数的索引 */
            Regs[0] =  _UsrFunctionAddr[Regs[0]];
            break;
        case 0x42:                      /* 中断开始处理 */
            OSIntNesting++;
            break;
        case 0x43:                      /*  判断中断是否需要切换             */
            if (OSTCBHighRdy == OSTCBCur)
            {
                Regs[0] = 0;
            }
            else
            {
                Regs[0] = 1;
            }
            break;
#endif
        case 0x80:                      /* 任务切换到系统模式 */
            __asm
            {
                MRS     R0, SPSR
                BIC     R0, R0, #0x1f      /* 先清再赋值      */
                ORR     R0, R0, #SYS32Mode /* 设置为系统模式  */  
                MSR     SPSR_c, R0
            }
            break;
        case 0x81:                      /* 任务切换到用户模式 */
            __asm
            {
                MRS     R0, SPSR
                BIC     R0, R0, #0x1f
                ORR     R0, R0, #USR32Mode   
                MSR     SPSR_c, R0
            }
            break;
      // 0x82和0x83功能用于指定任务以ARM的那种指令集运行
        case 0x82:                      /* 任务是ARM代码 */
            if (Regs[0] <= OS_LOWEST_PRIO)     // 先确定任务有效
            {
                ptcb = OSTCBPrioTbl[Regs[0]];  // 获取任务控制块
                if (ptcb != NULL)
                {
                    ptcb -> OSTCBStkPtr[1] &= ~(1 << 5);  // 指向堆栈栈顶的指针
                }
            }
            break;
        case 0x83:                     /* 任务是THUMB代码 */
            if (Regs[0] <= OS_LOWEST_PRIO)
            {
                ptcb = OSTCBPrioTbl[Regs[0]];
                if (ptcb != NULL)
                {
                    ptcb -> OSTCBStkPtr[1] |= (1 << 5);
                }
            }
            break;
        default:
            break;
    }
}

/*********************************************************************************************************
** 函数名称: OSStartHighRdy
** 功能描述: uC/OS-II启动时使用OSStartHighRdy运行第一个任务,
**           实质是产生swi 1指令
** 输 入:   无
** 输 出 :  无
** 全局变量: 无
** 调用模块: 无
********************************************************************************************************/

        void OSStartHighRdy(void)
{
    _OSStartHighRdy();       // swi的0x01功能号,运行优先级最高的任务
}

抱歉!评论已关闭.