找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5589|回复: 3
打印 上一主题 下一主题
收起左侧

UCOS移植代码之LAMMY分析--OS_CPU_C.C

[复制链接]
跳转到指定楼层
楼主
ID:72519 发表于 2015-1-23 20:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 liuda 于 2015-1-23 20:53 编辑

还限制字数;只能分割拉。
昨天我简要的把移植UCOS要增加的几个文件作了简要概述,今天开始,一个一个文件的进行分析,首先来说说OS_CPU.H
#ifdef OS_CPU_GLOBALS //这个宏名在OS_CPU_C.C中已定义,那么本文中的OS_CPU_EXT会被extern代替
#define OS_CPU_EXT
#else
#define OS_CPU_EXT extern
#endif
//定义与编译器无关的数据类型
typedef unsigned char BOOLEAN; //布尔变量
typedef unsigned char INT8U; // 无符号8位整型变量
typedef signed char INT8S; //有符号8位整型变量
typedef unsigned short INT16U; //无符号16位整型变量
typedef signed short INT16S; //有符号16位整型变量
typedef unsigned int INT32U; //无符号32位整型变量
typedef signed int INT32S; //有符号32位整型变量
typedef float FP32; //单精度浮点数(32位长度)
typedef double FP64; //双精度浮点数(64位长度)
typedef INT32U OS_STK; //堆栈是32位宽度
注: 这里为什么用typedef,因为如果用#define,那么代码中的每一个相应的类型都会被替代,很有可能会出现问题,毕竟他只是一个替代的关系,且编 译时间会增加,而用typedef则不会,它就相当于我们C++里面的引用,一样的思维,在这里面就是说多了一个名称。还有要注意的是我们怎么知道 unsigned char 就是无符号8位整型变量,可以ARM公司里面下载ADS_CompilerGuide_D.PDF文件,或者在你所装的ADS1.2目录里面有一个文件夹 叫PDF,打开它就可以找到,具体页在259页。
//与ARM7体系结构相关的一些定义
#define OS_CRITICAL_METHOD 2 //选择开、关中断的方式
__swi(0x00) void OS_TASK_SW(void); //任务级任务切换函数
__swi(0x01) void _OSStartHighRdy(void); //运行优先级最高的任务
__swi(0x02) void OS_ENTER_CRITICAL(void); //关中断
__swi(0x03) void OS_EXIT_CRITICAL(void); //开中断
__swi(0x40) void *GetOSFunctionAddr(int Index); //获取系统服务函数入口[自己还未明白]
__swi(0x41) void *GetUsrFunctionAddr(int Index);//获取自定义服务函数入口[自己还未明白]
__swi(0x42) void OSISRBegin(void); //中断开始处理
__swi(0x43) int OSISRNeedSwap(void); //判断中断是否需要切换
__swi(0x80) void ChangeToSYSMode(void); //任务切换到系统模式
__swi(0x81) void ChangeToUSRMode(void); //任务切换到用户模式
__swi(0x82) void TaskIsARM(INT8U prio); //任务代码是ARM代码
__swi(0x83) void TaskIsTHUMB(INT8U prio); //任务代码是THUMB
#define OS_STK_GROWTH 1 //堆栈是从上往下长的
#define USR32Mode 0x10 //用户模式
#define SYS32Mode 0x1f //系统模式
#define NoInt 0x80
#ifndef USER_USING_MODE
#define USER_USING_MODE USR32Mode //任务缺省模式
#endif
#ifndef OS_SELF_EN
#define OS_SELF_EN 0 //允许返回OS与任务分别编译、固化
#endif
OS_CPU_EXT INT32U OsEnterSum; //关中断计数器(开关中断的信号量)




#define OS_CPU_GLOBALS
#include "config.h"
OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
{//这个函数是一个指针函数,里面的形参void (*task)(void *pd)也是一个指针函数,就是一个函数的地址,其中task实际上就是我们的用户任务函数名;pdata是任务开始执行时,传递给任务的参数的指针;ptos是分配给任务的堆栈的栈顶指针。
OS_STK *stk; //OS_STK实际就是unsigned int
opt = opt; // 'opt' 没有使用。作用是避免编译器警告
stk = ptos; //获取堆栈指针
//建立任务环境,ADS1.2使用满递减堆栈
//注意下面并没有对SP进行分配空间,因为这个空间本来就是栈,所以没必要再对SP进行分配
*stk = (OS_STK) task; /* pc */任务的首地址
*--stk = (OS_STK) task; /* lr */任务的首地址
*--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);
}
#if OS_SELF_EN > 0
extern int const _OSFunctionAddr[];
extern int const _UsrFunctionAddr[];
#endif
//关于SWI的使用,最好看下ADS1.2目录下PDF文件夹下的ADS_DeveloperGuide_D.PDF文件的5.4我在这里稍微简述一下,SWI是一个软中断,即由软件实现的中断,它的中断号可从LR中获得,不同指令状态的取法不一样,至于哪不一样,看下面的代码或PDF文件就可以发现答案;还有它的第一操作数是放在r0中,也就是中断号是从r0取出,但是中断号必须从LR中经过变换后再load in r0。。
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;
case 0x02: /* 关中断函数OS_ENTER_CRITICAL(),参考os_cpu.h文件 */
__asm
{
MRS R0, SPSR
ORR R0, R0, #NoInt
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
MSR SPSR_c, R0
}
}
break;
//上面两个切换状态的汇编函数是对SPSR进行操作呢?因为使用的是软中断,程序状态寄存器CPRS保存在软中断对应的SPRS中,软中断退出后会把软中断对应的SPSR【即管理模式的SPRS】恢复到原来状态的CPRS中,所以我们只要对SPSR进行操作就可以了。


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:72519 发表于 2015-1-23 20:51 | 只看该作者


#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;

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;

}

//上面几个应该好理解,就不再嗷述啦。

}

void OSStartHighRdy(void)

{

_OSStartHighRdy();

}

/* 以下为一些钩子函数,全部为空函数。具体说明请看相关资料 */我自也未往深入的研究,只是知道它们功能不能忽视,可以把邵贝贝翻译的那本书相关内容好好看看

#if OS_CPU_HOOKS_EN

#if OS_VERSION > 203

void OSInitHookBegin (void)

{

}

#endif

#if OS_VERSION > 203

void OSInitHookEnd (void)

{

}

#endif

void OSTaskCreateHook (OS_TCB *ptcb)

{

ptcb = ptcb; /* Prevent compiler warning */

}

void OSTaskDelHook (OS_TCB *ptcb)

{

ptcb = ptcb; /* Prevent compiler warning */

}

void OSTaskSwHook (void)

{

}

void OSTaskStatHook (void)

{

}

#if OS_VERSION > 203

void OSTCBInitHook (OS_TCB *ptcb)

{

ptcb = ptcb; /* Prevent Compiler warning */

}

#endif

void OSTimeTickHook (void)

{

}

#if OS_VERSION >= 251

void OSTaskIdleHook (void)

{

}

#endif

#endif
回复

使用道具 举报

板凳
ID:68804 发表于 2015-2-9 15:03 | 只看该作者
学习了
回复

使用道具 举报

地板
ID:72966 发表于 2015-3-19 08:50 | 只看该作者
学习了。
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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