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功能号,运行优先级最高的任务
}