美文网首页
超简单的线程切换

超简单的线程切换

作者: 小鱼儿他老汉 | 来源:发表于2019-12-27 13:14 被阅读0次

    背景

    接手一个IoT工程,使用STM8L + NBIOT模块实现远程数传。源代码大体上已经构建完成,但是既没有使用ISR + Mainloop + FSM的设计方式,又没有使用RTOS做任务调度。所以如果花时间重新撸代码,时间和精力都不允许。实际上,我已经投入了大量时间来翻代码(填坑),增加了ISR,systicker,FSM,以及数据收发结构体......但是依然存在很多问题。

    延时问题

    阻塞型的代码设计,很多事情无法同时完成。尤其是阻塞型delay/wait会造成很多麻烦,比如Modem在通讯时需要较长时间等待和重试,而此时keyboard判断和处理几乎无法实现,而我并不希望在定时中断嵌入键盘处理。因为定时中断应该只提供ticker,而不应该和应用相关。

    RTOS Thread.yield的做法是,在Modem等慢速设备通讯任务中,遇到延时,将控制权交还给RTOS,并调度到其他任务中。于是我参考了这一做法,利用回调函数和systicker来实现任务切换。

    // setup callback functions of void cb(void)
    void set_delay_cb(void (*cb)()){
      callback = cb;
    }
    
    void yield_ms(uint8_t t)
    {
      assert_param(t<=250);
      u32 period = t;
      u32 start = systicker;
      while((systicker - start)<period){
        if(callback==NULL)
          asm("nop");
        else
          callback();
      }
    }
    
    void yield(uint8_t t)
    {
      assert_param(t<=60);
      u32 period = (u32)(t*1000);
      u32 start = systicker;
      while((systicker - start)<period){
        if(callback==NULL)
          asm("nop");
        else
          callback();
      }  
    }
    

    time.c

    void hw_update(void){
      LED_update();
      key_update();
      MTR_update();
      PM_update();
    }
    
    void main {
      set_delay_cb(hw_update);  // set callback as background task
      yield(10);  // delay 10 seconds, which perform callback functions.
    }
    

    main.c

    结构简单非常简单。但是放在hw_update()后台的函数与前台函数不能够有资源竞争,后台函数最好不要有while循环,也不要递归调用yield。

    相关文章

      网友评论

          本文标题:超简单的线程切换

          本文链接:https://www.haomeiwen.com/subject/luqdoctx.html