原创 msOS的学习

2019-1-7 16:52 4262 18 分类: 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 2024-09-05 09:06
训练集loss下降,但是验证集loss上升
当训练集loss下降而验证集loss上升时,这通常表明模型可能出现了过拟合。‌这种情况意味着模型在训练数据上的表现优于在测试数据上的表现,即模型很好地拟合了训练数据,但对于新数据的预测能力较差。分析种...
esad0 2023-05-27 08:41
吃饱闲的玩 做的
...
esad0 2021-07-09 15:46
传说中的嘉立创紫和TMF8801测距模块
这个色彩鲜艳的PCB 就是刚推出的嘉立创紫, 我感觉有点偏黑。    激光测距传感器 TMF8801的测试板。TMF8801 的资料还需要给老外签订保密合同才可以...
esad0 2021-04-19 15:38
AIR724 一拖8 LORA 系统
         AIR724通过LORA模块  和其他的8个模块进行通讯。  从而实现1拖8的效果。  &n...
esad0 2020-10-13 13:41
stm32f407移植cJSON 归纳
测试很顺利,主要感谢以下三位前行者的无私开源。参考下列三位大神文章汇总:在STM32F407上简单移植Cjson  https://blog.csdn.net/qq_4176464...
我要评论
1
18
关闭 站长推荐上一条 /2 下一条