一步步开发自己的OS操作系统

我在MSP430单片机上调试的控制4个灯闪烁, 把原理搞清楚了一通则百通,可以举一返三;注:以下所讲的堆栈即栈,因为堆栈说习惯了 ,堆是堆栈是栈;

下面简单的介绍一下我的系统,其实还不能叫系统,因为太简单了,只有心脏在跳动,还没长大发育;

大家都知道切换任务时要保存现场,那现场到底要保存什么呢?

首先介绍一下我的任务栈怎么用的,在创建任务时先定义一个全局数组,如TASK1_TACK_SIZE[128];

|-------------------------------------------------------------------|

|func |   .....  |  ......  | .......  |   task stack......                           |

|-------------------------------------------------------------------|

高地址   ---->                                                                低地址

栈从高地址往低地址增长。

(1)创建任务时要传入 任务的入口地址 和 任务栈底地址。

任务入口地址(func)会存放在栈底部,任务创建好之后从第一个任务开始运行,第一个任务就是从任务栈里面取出func并调用,第一个任务就开始跑起来了。

(2)第二个任务怎么调用呢,当发生定时器中断时:

第一:首先自动把PC和SR压进当前的任务栈里;

|-------------------------------------------------------------------|

|func| ...|....|pc|sr | .......  |   task stack......                                 |

|---------------- ---  |----------------------------------------------|

高地址              |                                   -------->      低地址

|

|

|SP (此时栈指针可能指向这里)

第二:进入中断子函数,手动保存所有工作寄存器,除了中断会自动保存的PC和SR不需要保存其他都要保存,当然有人会问局部变量哪去了,需要保存吗,答应是不需要保存,因为局部变量就在栈里,在压入pc之前的就是局部变量或调用的子程序还没返回时被压栈的信息;

|-----------------------------------------------------------------------|

|func| ...|....|pc|sr |r4|r5|r6|r7|r8|r9| ...r14|r15|....  |   task stack.....  |

|---------------- -------------------------------- |---------------------|

高地址 -------->                                         |                       低地址

|

|

|SP (此时栈指针指向这里)

此时需要保存当前的SP指针,把它指向的地址保存到任务块里的pTaskStk,下次恢复时只要把pTaskStk恢复到SP,我的任务描述是一个结构体;

//任务结构体

typedef struct

{

OSELK_STK *pTaskStk;// 任务栈指针

volatile TaskSysTime   runTmr;//定时

volatile TaskSysTime   runTmr_bak;//定时备份

unsigned char taskId;

unsigned char taskMode;//任务模式

unsigned char taskState;//任务状态

E_Task_func * func;//任务入口

}TaskFuncType, *PTaskFuncType;

第三:保存好当前任务现场时,取下一个任务块,把pTaskStk恢复给SP,sp指向哪里了呢, 怎么进入下一个任务入口呢,恢复下一个任务首先要POPALL 寄存器,任务初始化时要先初始化任务栈,pTaskStk要保存栈底地址+13,要预留12个寄存器的位置,因为切换任务时会POPALL 寄存器,栈会往高地址增长,最后POP PC时,即把PC 指向了func任务入口地址,下一个任务就被切换过来了,以此类推,每个任务切换都是这个过程,这样分时复用就开始跑起来了。

下面是中断代码:

/*<RBHead>

*************************************************************************

*                                                                                                                      *

*                                                                                           *

*                          STUTTGART                                                                            *

*                                                                                                                      *

*          Alle Rechte vorbehalten - All rights reserved                                               *

*                                                                                                                      *

*************************************************************************

*************************************************************************

*

*************************************************************************

*

* $Filename__:main.c$

*

* $Author____:rao jun$

*

* $Function__:TME ISR SW task  $

*

*************************************************************************

* $User______:jun.rao$

* $Date______:31.08.2015$

* $Class_____:$

* $Name______:

* $Variant___:1.0.0$

* $Revision__:0$

* $Type______:asm$

* $State_____:debug$

* $Generated_:$

*************************************************************************

*

*

*************************************************************************

* List Of Changes

*

* $History

*

*

* $

*

*************************************************************************

</RBHead>*/

#include <msp430f5247.h>

;********************************************************************************************************

;********************************************************************************************************

extern LKOS_TaskProcISR

extern pTaskStk

;********************************************************************************************************

;********************************************************************************************************

RSEG    CODE            ; Program code

;********************************************************************************************************

;Interrupt ISR

;********************************************************************************************************

TIMER1_ISR

dint;关闭中断

push.w r4;保存工作寄存器

push.w r5

push.w r6

push.w r7

push.w r8

push.w r9

push.w r10

push.w r11

push.w r12

push.w r13

push.w r14

push.w r15

mov.w  sp,pTaskStk;保存当前的任务栈指针

calla #LKOS_TaskProcISR;调用c语言 取一下任务栈指针

mov.w pTaskStk,sp;恢复任务栈指针

pop.w r15

pop.w r14

pop.w r13

pop.w r12

pop.w r11

pop.w r10

pop.w r9

pop.w r8

pop.w r7

pop.w r6

pop.w r5

pop.w r4

eint;开中断

reti;这条指令中断返回指令,会自动执行 POP SR  ,POP PC,当POP PC时即任务被切换到下一个断点了

;********************************************************************************************************

;

;

;  Interrupt vectors

;********************************************************************************************************

COMMON  INTVEC

ORG     TIMER1_A0_VECTOR

WDT_VEC     DW      TIMER1_ISR

END

/**

***************************************************************************************************

* create_task

*

* \param          func fun \ uint8 mode  \  uint32 tmr_ms  \  uint8 priority

* \return          void

*

***************************************************************************************************

*/

int create_task(E_Task_func* fun , unsigned int taskId , unsigned int *pStk , unsigned char mode , TaskSysTime tmr)

{

PTaskFuncType  ptask_fun;

if ((NULL == fun ) || (NULL == pStk))

return (-1);

ptask_fun = &Task_funcTab[taskId];//依次往数组里放

if (taskId < MAX_TASK)

{

if (ptask_fun->taskMode == 0)

{

ptask_fun->func = fun;

ptask_fun->taskMode = mode;

ptask_fun->runTmr = tmr;

ptask_fun->runTmr_bak =tmr;

ptask_fun->pTaskStk = LKOS_TaskStackInit(fun,pStk,taskId); //初始化堆栈

ptask_fun->taskId = taskId;

Task_Ctrl.CurTaskLens = taskId;

return (ptask_fun->taskId);

}

}

return (-1);

}

OSELK_STK * LKOS_TaskStackInit(E_Task_func* fun , OSELK_STK*stk,unsigned int taskId)

{

memset(stk,0,strlen((char const*)stk));//栈清0,调用库比较慢

*stk = (unsigned int)fun;//初始化时先把每个任务的入口地址存在栈底,切换任务的时候才能知道下一个任务在哪里

return (stk-13);//初始化完栈让SP 跳过13个字节(sr 和r4-r15) ,因为在调用下一个任务时要POP 13个字节

}

/**

***************************************************************************************************

* LKOS_TaskProcISR 中断调用的函数

*                      轮询调度

* \param

* \return          next_taskStk

*

***************************************************************************************************

*/

void  LKOS_TaskProcISR(void)

{

PTaskFuncType next_task=NULL;

*Task_Ctrl.ppTaskStk = pTaskStk;//保存当前任务的SP

if(Task_Ctrl.task_cnt < Task_Ctrl.CurTaskLens)

Task_Ctrl.task_cnt++;

else

Task_Ctrl.task_cnt = 0;

next_task = LKOS_GetTaskTCBPtr(Task_Ctrl.task_cnt);

Task_Ctrl.ppTaskStk = &next_task->pTaskStk;//一下个任务栈

pTaskStk = next_task->pTaskStk;

ConfigureTimerA();

}

/*----------------------------------------------------------------------------------------

* TASK

*----------------------------------------------------------------------------------------

*/

unsigned int  TASK1_STACK_SIZE[200]={0,0,};

unsigned int  TASK2_STACK_SIZE[200]={0,0,};

unsigned int  TASK3_STACK_SIZE[200]={0,0,};

unsigned int  TASK4_STACK_SIZE[200]={0,0,};

void LKOS_Task1(void);

void LKOS_Task2(void);

void LKOS_Task3(void);

void LKOS_Task4(void);

/*----------------------------------------------------------------------------------------

* MAIN

*----------------------------------------------------------------------------------------

*/

int main( void )

{

TaskSysTime taskTmr;

sys_BspInit();

LKOS_TaskInit();

taskTmr.ms = 15;

create_task(LKOS_Task1,LKOS_Task1_ID,&TASK1_STACK_SIZE[200-1],TMR_MODE,taskTmr);

taskTmr.ms = 25;

create_task(LKOS_Task2,LKOS_Task2_ID,&TASK2_STACK_SIZE[200-1],TMR_MODE,taskTmr);

taskTmr.ms = 25;

create_task(LKOS_Task3,LKOS_Task3_ID,&TASK3_STACK_SIZE[200-1],TMR_MODE,taskTmr);

taskTmr.ms = 15;

create_task(LKOS_Task4,LKOS_Task4_ID,&TASK4_STACK_SIZE[200-1],TMR_MODE,taskTmr);

LKOS_FirstTaskInit();

while(1);

return 0;

}

/**

***************************************************************************************************

* LKOS_Task1

*

* \param          void

* \return          void

*

***************************************************************************************************

*/

void LKOS_Task1(void)

{

int b = 6;

int c = 1;

int buf[10]={1,2,3,4,5,6,7,8,9};

while(1)

{

if(b++<20)

led1_on();

Delayms(500);

led1_off();

Delayms(500);

}

}

/**

***************************************************************************************************

* LKOS_Task2

*

* \param          void

* \return          void

*

***************************************************************************************************

*/

void LKOS_Task2(void)

{

int a = 6;

int c =  9;

int tmp[10]={1,2,3,4,5,6,7,8,9};

_EINT();

while(1)

{

a++;

led2_on();

Delayms(100);

a++;

led2_off();

Delayms(100);

}

}

时间: 2024-08-07 13:17:20

一步步开发自己的OS操作系统的相关文章

一步步开发自己的OS操作系统(二)

注:以下所讲的堆栈即栈,因为堆栈说习惯了 ,堆是堆栈是栈: 下面简单的介绍一下我的系统,其实还不能叫系统,因为太简单了,只有心脏在跳动,还没发育长大: 大家都知道切换任务时要保存现场,那现场到底要保存什么呢?今天我主要讲讲任务切换需要保存哪些寄存器,当然我阐述的是最简单的系统,从0开始构建系统,任务切换最重要的一步就是发生定时器中断时保存当前任务的堆栈指针,任务切换时保存现场PUSH / 恢复现场POP,寄存器的弹入弹出都和堆栈指针有关,堆栈指针指向哪就PUSH到哪,堆栈指针指向哪就从那POP,

Windows 7, VMware Workstation10部署IOS开发环境[Mac OS X Server10.6系统安装]

Windows 7, VMware Workstation10部署IOS开发环境 Mac OS X Server10.6系统安装 基本情况是Windows7 专业版32位系统,VMware Workstation10.0虚拟机,Mac OS X Server10.6操作系统.Mac OS是一套运行于苹果Macintosh系列电脑上的操作系统.Mac OS是首个在商用领域成功的图形用户界面.现行的最新的系统版本是OS X 10.10 Yosemite,本文介绍的是Mac OS X Server10

Android灭亡论之Firefox OS操作系统出现

今天是2014年7月1日,过几天就要到深圳实训去了,实训核心内容是Android开发.虽然Android如今非常火,但作为程序员的我们必须时刻保持清醒的头脑.我虽不是什么预言家,但最近接触的Android项目,却让我真实的感受到Android操作系统正在走向灭亡的道路...来看看是什么操作系统可能会灭亡Android吧:Firefox OS,专案名称为Boot to Gecko.是由谋智公司(Mozilla Corporation)主导研发的开放源代码移动操作系统,采用Linux核心,应用于智能

安卓开发解决android.os.NetworkOnMainThreadException异常方法(主线程不能直接调用webservice)

安卓开发解决android.os.NetworkOnMainThreadException异常方法 2013-01-07 14:01:04|  分类: 技术 |  标签:安卓  技术  java  |举报|字号 订阅 在android 2.3上访问网络的方法,在android 4.0上运行时报android.os.NetworkOnMainThreadException异常,主要问题在于4.0中访问网络不能在主线程中进行,有两个方法可以解决.第一种是在主线程中增加如下代码[不推荐]: // 详见

一步步开发自己的博客 .NET版(4、文章发布功能)百度编辑器

前言 这次开发的博客主要功能或特点:    第一:可以兼容各终端,特别是手机端.    第二:到时会用到大量html5,炫啊.    第三:导入博客园的精华文章,并做分类.(不要封我)    第四:做个插件,任何网站上的技术文章都可以转发收藏 到本博客. 所以打算写个系类:<一步步搭建自己的博客> 一.一步步开发自己的博客  .NET版(1.页面布局.blog迁移.数据加载) 二.一步步开发自己的博客  .NET版(2.评论功能) 三.一步步开发自己的博客  .NET版(3.注册登录功能) 四

一步步开发自己的博客 .NET版 剧终篇(6、响应式布局 和 自定义样式)

前言 这次开发的博客主要功能或特点:    第一:可以兼容各终端,特别是手机端.    第二:到时会用到大量html5,炫啊.    第三:导入博客园的精华文章,并做分类.(不要封我)    第四:做个插件,任何网站上的技术文章都可以转发收藏 到本博客. 所以打算写个系类:<一步步搭建自己的博客> 一步步开发自己的博客  .NET版(1.页面布局.blog迁移.数据加载) 一步步开发自己的博客  .NET版(2.评论功能) 一步步开发自己的博客  .NET版(3.注册登录功能) 一步步开发自己

WPF一步步开发XMPP IM客户端:入门

[起因&目标] 因为工作原因接触openfire服务端和spark客户端开发2年,主要是基于openfire扩展开发了针对企业用途的服务器插件,还开发了各个平台上的客户端,详情可搜索微信公众号:CVTalk 在开发过程中,发现基于Spark开发Java Swing客户端(公司内部命名CVTalk)比较重,用户体验很难做到和微信客户端看齐,皮肤的开发也比较费力,公司里绝大部分是windows的客户端,而且高清分辨率屏幕的用户越来越多,内存占用过多的问题也解决不了,swing客户端越发力不从心. 于

一步步开发自己的博客 .NET版(5、Lucenne.Net 和 必应站内搜索)

前言 这次开发的博客主要功能或特点:    第一:可以兼容各终端,特别是手机端.    第二:到时会用到大量html5,炫啊.    第三:导入博客园的精华文章,并做分类.(不要封我)    第四:做个插件,任何网站上的技术文章都可以转发收藏 到本博客. 所以打算写个系类:<一步步搭建自己的博客> 一步步开发自己的博客  .NET版(1.页面布局.blog迁移.数据加载) 一步步开发自己的博客  .NET版(2.评论功能) 一步步开发自己的博客  .NET版(3.注册登录功能) 一步步开发自己

IBM Z/OS 操作系统学习笔记(持续更新)

存储管理子系统(DFSMS) 存储管理也是系统的一项基本服务. 系统存储管理子系统(Storage Management System,SMS)定义了系统中的各种输入/输出设备,并控制这些设备的操作:同时,它还提供文件系统的基本功能,使用户可以方便.快速地访问数据.系统的各种程序及数据都保存在硬盘上,如果希望执行某些程序,必须用到存储管理的服务,因此,SMS一般先于其他子系统启动,以提供基本的存储管理服务. 存储管理软件组件(Data Facility Storage Management Su