原创 msOS的学习

2019-1-7 16:52 2555 4 分类: MCU/ 嵌入式 文集: msOS
  《嵌入式微系统》买来很长时间了,也很用心的看,觉得里面的软件很巧妙和精致,一看就是很用心的一本良心之作。
但没有在系统层面看懂,  总结的原因有2个:  1  没有实际的应用。 前后台是设计方法已经满足一般的设计要求,没有更上一层楼的动力。
2  以前一直用PIC的芯片, 对STM32的芯片不熟悉,一改动一出错就不知所措。
PIC芯片的厂家在青岛有好多技术支持也是最主要的原因。 

现在没有什么事情了,准备重新开始,在一个小领域从0开始。 

罗胖子说过很多没有节操的话,也说过很多有用 的。 他说: 一个人要不断的从傻瓜开始,在一个方向努力,从开始傻瓜到不傻瓜  的时间  称其为:傻瓜时间。
傻瓜的周期越短,说明人进步的越快。

/*******************************************************************************
*   操作系统 的节拍
*******************************************************************************/
   操作系统了解的不多,只知道比常用的程序多了节拍和抢断的概念。
在常用的前后台设计中也有节拍的概念, 譬如常用到的数码管显示用4~5MS的节拍来轮扫。  按键扫描用20MS 的速度来扫描。
例:
main
{
if (abs(LedT -Time0Value)>= Con_5ms )     
{
LedT = Time0Value; //重新计时
SubLedDisplay(&ledBuf);  //5ms时间到,运行LED显示程序
}
if (abs(KeyT - Time0Value) > Con_20ms)
{
KeyT = Time0Value;   //   重新赋值
SubKey ();
}
.......
}

一般情况下,SubLedDisplay(),SubKey () 这些函数 运行时间是可以估值出来的,
但是在大系统中,如果某个单一的函数运行时间过长,会造成其他函数的响应迟钝。
msOS 的节拍 是10ms, 我一个初学者的理解:
     是一个高优先极的任务在运行到10ms时,系统强制切换到另一个任务。吃饭也不能一人光吃,也得转转桌子。

/*******************************************************************************
*   操作系统 的切换和抢占
*******************************************************************************/
操作系统任务的切换,和正常的中断处理 几乎是一个流程。
中断处理要打断主程序,转去中断处理程序时,当然首先要保存当前的运行指针 PC, 还要保存当前主程序运行所需要的变量寄存器,R0.R1....之类的,
还有状态寄存器等一堆,估计得有10多个吧。  运行完中断处理程序,再把这10多个数据从堆栈里取出来,继续运行主程序。 

操作系统的切换也是要把这套流程完整的做一遍,所不同的是,任务切换用的栈不同。 中断是用MSP主栈,任务使用PSP任务栈。
可见STM32的架构 就是为操作系统设计的。  平常我们单任务系统只用到MSP,浪费了PSP。
2019  0918  
/*******************************************************************************
*   msOS 双任务内核的理解    (我写的没有规律,理解到那,写到那,写下来是为了加深理解和记忆)
*******************************************************************************/
int main(void) 
{      
    InitData();
    System.Init();                       
    System.OS.CreateLogicTask(LogicTask);     // 创建业务逻辑任务
    System.OS.CreateMenuTask(MenuTask);     // 创建第二个任务
    System.OS.Start();
    EnableIrq();                            // 关中断
}
msOS  在主程序里一共有2个任务, LogicTask和MenuTask   .一个高优先级的任务和低优先级的任务。
在学习msOS的过程中,源码与系统学习无关的东西实在太多, 我很长时间为里面的逻辑关系和菜单项目的各种关系头痛。
初学者第一要务是能照着葫芦花瓢的先用起来,然后那不懂再深入学习会好些,总比一开始就看一个实际项目,就此难住好些。 
我的目标就是把MSOS 先简化成一个KEY 任务和一个LED灯的任务。KEY 高优先级,LED灯 低优先级。
2019 0918    22:25
      我理解的msOS任务 就是两个while(1).  ....两个死循环。
   人为认定这两个死循环 一个是高任务,一个是低任务。  
    当运行在低任务循环中时,有两种情况可以检测事件的发生,外设中断和定时中断。
定时中断以0.1MS的周期中断,在系统中称为节拍。   void SysTick_Handler(void) 
    在节拍中处理的程序    Routine
   无论外设中断和节拍Routine ,都可以发出消息。PostMessageQueue
    消息是只对高任务的,有Message ,则切换到高任务循环。

/*******************************************************************************
* 描述     : 发送一个消息到消息队列中,处于等待的任务会自动运行
*******************************************************************************/
static bool PostMessageQueue(uint message)
{
    EnterCritical();
    // 菜单界面任务下,且无消息,用任务成员Message传递,不用消息队列
    if (CurrentTaskPointer == &MenuTask && LogicTask.Message == 0)
    {
        LogicTask.Delay = 0;
        LogicTask.Message = message;   
        ExitCritical();
        Schedule(&LogicTask);     //切换到业务逻辑业务
        return (true);
    }

    if (MessageQueue.Entries >= QueueBufferSum)    // 消息队列满  ,退出
    {                                                              
        ExitCritical();
        return (false);
    }
//在高任务下,有消息,则保存到消息队列中。
    MessageQueue.Entries++;
     *MessageQueue.In++ = message;
    if (MessageQueue.In > MessageQueue.End)
        MessageQueue.In = MessageQueue.Start;

    ExitCritical();
   return (true);
}

高任务的退出 : 有消息,进行处理,处理完毕 ,退出,退回到低任务循环。
高任务循环的时候,节拍程序还是要定时运行的。
关于内核切换和消息 之类的内容都在 OS.C,  我认为是整个系统的核心和精华。
2019 0922
       大体明白了OSMS 的框架。   低优先级任务,高优先级任务,10MS的节拍运行例行扫描的程序,类似中断。
其中内核的切换,看了看,模模糊糊明白了点,其实里面的细节不清楚,其实也没有必要弄的太明白吧,毕竟对我来说是用系统,不是写系统。

        在低任务中 加了一个LED 灯,闪动频率1HZ.
/*******************************************************************************
* 函数名 : MenuTask
* 描述     : MenuTask任务,必须为最低优先级任务
* 返回参数  : 无
********************************************************************************
*版本     作者            日期            说明
*V0.1    Wangsw        2013/12/16       修改版本
*******************************************************************************/
void MenuTask (void)
{
    static uint MenuSystick; 
    InitMenu();
InitLed();      //testt
    MenuSystick = App.Data.Systick1000 + 500;    //Systick1000  在系统中是1MS ,+500   间隔就是500MS
    while(true)             
    {
        if (App.Data.Systick1000 >= MenuSystick)           //500MS
        {
            MenuSystick = App.Data.Systick1000 + 500;
  GPIO_WriteBit(GPIOB, GPIO_Pin_0, (BitAction)((1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_0))));  //取反
        }
    }
}

再增加一个按键, 在节拍中扫描,按下则进入高任务。
/*******************************************************************************
* 描述     : 系统节拍中断入口,非常重要,每秒10000次,即0.1mS一次
*           : 系统节拍通过switch细分为每秒1000次,每秒100次的例行节拍
*           : 同层直接调用,高层采用注册调用
*******************************************************************************/
void SysTick_Handler(void)
{
    byte div;
    static byte Counter = 0;
    if(++Counter == 100) Counter = 0;
    div = Counter / 10;
    switch(Counter % 10)
    {
        case 0: Systick1000RegisterPointerBlock[0](); break;
        case 1: Systick1000RegisterPointerBlock[1](); break;
        case 2: Systick1000RegisterPointerBlock[2](); break;
        case 3: Systick1000RegisterPointerBlock[3](); break;
        case 4: Systick100RegisterPointerBlock[div]();break;
        case 5: AppDataPointer->Systick1000++;        break;    //软件定时器  ,1MS加1;
        case 6: Systick1000RegisterPointerBlock[3](); break;
        case 7: Systick1000RegisterPointerBlock[3](); break;
        case 8: KeySystick1000Routine();               break;                     //按键扫描
        case 9: Systick1000RegisterPointerBlock[0]();   break;
    }    
}
#define GetKey  GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) //读取按键0
//---------------------------------------------------------------------------------------------------------------
void KeySystick1000Routine(void) 
{
if (GetKey ==0)
{
PostMessage(MessageKey, 1);
}
}
//--------------------------------------------------------------------------------------------------------------------
在高任务中  ,增加按键后的事件处理程序。
void LogicTask(void)
{
    int i;
    uint message;
    uint data; 
    InitLogic();
    System.OS.DelayMs(2000);
    
    //逻辑业务任务获取消息,分配处理
    while(true)
    {     
        message = System.OS.PendMessageQueue(); //获取消息
   
        data = message & 0x00FFFFFF;
        switch(message >> 24)
        {
            case MessageKey:                    //按键消息
    GPIO_WriteBit(GPIOB, GPIO_Pin_0, (BitAction)((1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_0))));
            break;
            case MessageTimer:
             //   Function(data + RomBase);
                break;
            default:
                break;
        }
    }
}
//--------------测试,运行正常。 下一步整合自己的程序,一点一点的加进去。

如果需要源代码,请留E-MAIL ,我会发到您邮箱。

同时建议去雨滴科技 去下最新版本的OSMS , 对照着看。 我的是简化的。
http://bbs.raindi.net/forum.php

作者: esad0, 来源:面包板社区

链接: https://mbb.eet-china.com/blog/uid-me-1039027.html

版权声明:本文为博主原创,未经本人允许,禁止转载!

文章评论1条评论)

登录后参与讨论

凤舞天 2019-1-7 21:53

支持,看到亲切的msOS了
相关推荐阅读
esad0 2020-05-14 13:58
关于读写ic卡的程序注释
         IC卡,RFID卡,M1卡。E:\eDiary\2020\4\PIC18F97J60_SPI.cE:\eDiary\202...
esad0 2020-02-10 19:32
NTP 不好用
[2020-02-10 19:29:09.704]: [I]-[testNtp.printTime] 2012/06/01,11:17:12[2020-02-10 19:29:10.701]: [I]...
esad0 2020-02-09 15:27
用AIR202 在ONENET 上位置定位
onenet 有位置的增值服务。是收费的。 但是ONENET 还是很厚道的, 每天300万以下的定位服务是不收费的。 鉴于我的设备是固定安装的, 因此只使用应用管理中的  地图 ...
esad0 2020-02-06 10:44
python 做智力题
和儿子一块学PYTHON .   感觉和C 语言基础的没有什么不同。感觉还不如C语言灵活。编程语言,一通百通。题目见下图。结题思路:   这是一个最简单的密码加...
esad0 2019-12-31 15:23
超声波模块开放笔记
       这是简单文章。       市场上的超声波模块大部分和我DIY的一样 是用HOLTEK的45F23A做的。...
广告
EE直播间
更多
我要评论
1
4
广告
关闭 热点推荐上一条 /5 下一条