搜索
bottom↓
回复: 18

借傻孩子老师的地盘发个小小调度器

[复制链接]

出0入0汤圆

发表于 2015-5-13 10:33:24 | 显示全部楼层 |阅读模式
/*!
*************************************************************************************
*\file    switch.h
*\brief   简易的调度器
*         1、轮番调度
*         2、可以主动释放CPU
*         3、用户的栈大小可自定义
*         4、任务数可自定义
*      
*\author  worldsing
*\version V0.01
*\date    2015/04/24
*
*\b       1、去除C文件, 实现单个头文件代码结构
*         2、目前仅在ST系列的Cortex-M3平台测试过
*\li      2015/04/24
*         SWITCH_EN 宏须在创建任务的文件里定义
*************************************************************************************
*/
#ifndef __SWITCH_H__
#define __SWITCH_H__


//------------------------------------------------------------------------------------
//                                    Include File
//------------------------------------------------------------------------------------

#include <stm32f10x.h>
#include <core_cm3.h>
#include <stdint.h>
#include <stdbool.h>

//------------------------------------------------------------------------------------
//                                    Function declare
//------------------------------------------------------------------------------------

void switchDelayMs(uint16_t nTick);   


//------------------------------------------------------------------------------------
//                                    Switch code
//------------------------------------------------------------------------------------
#ifdef  SWITCH_EN

__asm void setPSP(uint32_t topOfProcStack)
{
  msr psp, r0
  bx lr
}
                                                      
__asm void taskSwitch(void)                                    
{                                                              
    LDR     R0, =0xE000ED22                                    
    LDR     R1, =0xFF                                          
    STRB    R1, [R0]                                          
    LDR     R0, =0xE000ED04                                    
    LDR     R1, =0x10000000                                    
    STR     R1, [R0]                                          
    BX      LR                                                
    ALIGN
}                                                              
__asm void PendSV_Handler(void)                                
{                                                              
    IMPORT  taskRuning
    IMPORT  taskNew
    CPSID   I                                                  
    MRS     R0, PSP                                            
    CBZ     R0, NoSave                                         
    SUBS    R0, R0, #0x20                                 
    STM     R0, {R4-R11}                                   
    LDR     R1, =taskRuning                                    
    LDR     R1, [R1]                                          
    STR     R0, [R1]                                          
                                                               
NoSave                                                   
    LDR     R0, =taskRuning                                    
    LDR     R1, =taskNew                                       
    LDR     R2, [R1]                                          
    STR     R2, [R0]                                       
    LDR     R0, [R2]                                          
    LDM     R0, {R4-R11}                                       
    ADDS    R0, R0, #0x20                                 
    MSR     PSP, R0                                            
    ORR     LR, LR, #0x04                                 
    CPSIE   I                                                  
    BX      LR                                                
    ALIGN                                                      
}                                                              


#define SWITCH_CONFIG(MAX_TASK, N_TICK_IN_SECOND, SYSTEM_CLK_NMHZ,    \
                      SYS_TICK_HOOK, IDLE_HOOK);                      \
                                                                      \
typedef struct {                                                      \
  uint32_t *pTaskStack;                                               \
  uint16_t delay;                                                     \
}TCB;                                                                 \
                                                                      \
TCB taskTCB[MAX_TASK + 1] = {0};                                      \
                                                                      \
TCB *taskNew, *taskRuning;                                            \
                                                                      \
uint8_t  taskCnt = 0;                                                 \
uint8_t  nTask;                                                       \
                                                                      \
void taskIdle(void) {                                                 \
  while(1){                                                           \
    IDLE_HOOK();                                                      \
    __nop();                                                          \
  }                                                                   \
}                                                                     \
void  SysTick_Handler (void) {                                        \
    uint8_t i;                                                        \
    bool bOneSwitch;                                                  \
    SYS_TICK_HOOK();                                                  \
    bOneSwitch = false;                                               \
    for(i = 0; i < nTask; i++){                                       \
      if(taskTCB[i].delay != 0){                                      \
        taskTCB[i].delay--;                                           \
      }                                                               \
      if(bOneSwitch == false){                                        \
        taskCnt %= nTask;                                             \
        if(0 == taskTCB[taskCnt].delay){                              \
          bOneSwitch = true;                                          \
          taskNew = &taskTCB[taskCnt];                                \
          }                                                           \
        taskCnt++;                                                    \
        }                                                             \
    }                                                                 \
    if(bOneSwitch == false)                                           \
      taskNew = &taskTCB[nTask];                                      \
    taskSwitch();                                                     \
}                                                                     \
                                                                      \
                                                                      \
void switchDelayMs(uint16_t nTick) {                                  \
    uint8_t i;                                                        \
    if(0 == nTick)                                                    \
      return;                                                         \
                                                                      \
    taskRuning->delay = nTick;                                        \
    for(i = 0; i < nTask; i++){                                       \

      if(0 == taskTCB[taskCnt].delay){                                \
         taskNew = &taskTCB[taskCnt++];                               \
         break;                                                       \
      }else taskCnt++;                                                \
    }                                                                 \
    if(taskRuning == taskNew)                                         \
      taskNew = &taskTCB[nTask];                                      \
    taskSwitch();                                                     \
}                                                                     \
                                                                      \
                                                                      \
void switchTaskInt(void (*task)(void), uint32_t *ptos) {              \
    if(MAX_TASK + 1 <= taskCnt){                                      \
      taskCnt = 0;                                                    \
      return;                                                         \
    }                                                                 \
    *(ptos)    = (uint32_t)0x01000000L;                               \
    *(--ptos)  = (uint32_t)task;                                      \
    taskTCB[taskCnt++]. pTaskStack =  ptos -14;                       \
}                                                                     \
                                                                      \
                                                                      \
void switchStart(void){                                               \
  switchTaskCreate(taskIdle, 256);                                    \
  if(taskCnt < (MAX_TASK + 1))                                        \
    nTask = taskCnt;                                                  \
  else                                                                \
    nTask = MAX_TASK;                                                 \
  setPSP(0);                                                          \
  SysTick_Config((SYSTEM_CLK_NMHZ / N_TICK_IN_SECOND) - 1);           \
  while(1);                                                           \
}

#define switchTaskCreate(task, stackSize) {__align(8) static uint32_t task##Stack[stackSize / 4]; \
                                           switchTaskInt(task, &task##Stack[(stackSize/4)-1]);    \
                                          }

#endif

//------------------------------------------------------------------------------------
//                                    Demo code
//------------------------------------------------------------------------------------
#if(0)

#define   SWITCH_EN
#include  "switch.h"

void tickHook(void)
{
        //不得放入阻塞\复杂\死循环代码       
}
       
void idleHook(void)
{
       
}       

//配置参数:最大任务数  1秒Tick数 系统时钟  时钟钩子  空闲钩子
SWITCH_CONFIG(2, 100, 72000000, tickHook, idleHook);

       
void task0(void){                         //任务0
   for(;;){
   //这放入您的代码
   switchDelayMs(200);                    //可用delay()释放CPU
   }
}
  
void task1(void){                         //任务1
  for(;;){
  //这放入您的代码
  switchDelayMs(1);                       //可用delay()释放CPU
  }
}

       

int main(void){
  switchTaskCreate(task0, 60);            //在调度前建立任务
  switchTaskCreate(task1, 30);            //在调度前建立任务
  switchStart();                          //开始调度
}
#endif

#endif

//------------------------------------------------------------------------------------
//                                    End of file
//------------------------------------------------------------------------------------

   

出0入0汤圆

 楼主| 发表于 2015-5-13 20:31:29 | 显示全部楼层
本帖最后由 worldsing 于 2015-5-13 20:33 编辑
  1. /*!
  2. *************************************************************************************
  3. *\file    switch.h
  4. *\brief   简易的调度器
  5. *         1、轮番调度
  6. *         2、可以主动释放CPU
  7. *         3、用户的栈大小可自定义
  8. *         4、任务数可自定义
  9. *      
  10. *\author  worldsing
  11. *\version V0.01
  12. *\date    2015/04/24
  13. *
  14. *\b       1、去除C文件, 实现单个头文件代码结构
  15. *         2、目前仅在ST系列的Cortex-M3平台测试过
  16. *\li      2015/04/24
  17. *         SWITCH_EN 宏须在创建任务的文件里定义
  18. *************************************************************************************
  19. */
  20. #ifndef __SWITCH_H__
  21. #define __SWITCH_H__


  22. //------------------------------------------------------------------------------------
  23. //                                    Include File
  24. //------------------------------------------------------------------------------------

  25. #include <stm32f10x.h>
  26. #include <core_cm3.h>
  27. #include <stdint.h>
  28. #include <stdbool.h>

  29. //------------------------------------------------------------------------------------
  30. //                                    Function declare
  31. //------------------------------------------------------------------------------------

  32. void switchDelayMs(uint16_t nTick);   


  33. //------------------------------------------------------------------------------------
  34. //                                    Switch code
  35. //------------------------------------------------------------------------------------
  36. #ifdef  SWITCH_EN

  37. __asm void setPSP(uint32_t topOfProcStack)
  38. {
  39.   msr psp, r0
  40.   bx lr
  41. }
  42.                                                       
  43. __asm void taskSwitch(void)                                    
  44. {                                                              
  45.     LDR     R0, =0xE000ED22                                    
  46.     LDR     R1, =0xFF                                          
  47.     STRB    R1, [R0]                                          
  48.     LDR     R0, =0xE000ED04                                    
  49.     LDR     R1, =0x10000000                                    
  50.     STR     R1, [R0]                                          
  51.     BX      LR                                                
  52.     ALIGN
  53. }                                                              
  54. __asm void PendSV_Handler(void)                                
  55. {                                                              
  56.     IMPORT  taskRuning
  57.     IMPORT  taskNew
  58.     CPSID   I                                                  
  59.     MRS     R0, PSP                                            
  60.     CBZ     R0, NoSave                                         
  61.     SUBS    R0, R0, #0x20                                 
  62.     STM     R0, {R4-R11}                                   
  63.     LDR     R1, =taskRuning                                    
  64.     LDR     R1, [R1]                                          
  65.     STR     R0, [R1]                                          
  66.                                                                
  67. NoSave                                                   
  68.     LDR     R0, =taskRuning                                    
  69.     LDR     R1, =taskNew                                       
  70.     LDR     R2, [R1]                                          
  71.     STR     R2, [R0]                                       
  72.     LDR     R0, [R2]                                          
  73.     LDM     R0, {R4-R11}                                       
  74.     ADDS    R0, R0, #0x20                                 
  75.     MSR     PSP, R0                                            
  76.     ORR     LR, LR, #0x04                                 
  77.     CPSIE   I                                                  
  78.     BX      LR                                                
  79.     ALIGN                                                      
  80. }                                                              


  81. #define SWITCH_CONFIG(MAX_TASK, N_TICK_IN_SECOND, SYSTEM_CLK_NMHZ,    \
  82.                       SYS_TICK_HOOK, IDLE_HOOK);                      \
  83.                                                                       \
  84. typedef struct {                                                      \
  85.   uint32_t *pTaskStack;                                               \
  86.   uint16_t delay;                                                     \
  87. }TCB;                                                                 \
  88.                                                                       \
  89. TCB taskTCB[MAX_TASK + 1] = {0};                                      \
  90.                                                                       \
  91. TCB *taskNew, *taskRuning;                                            \
  92.                                                                       \
  93. uint8_t  taskCnt = 0;                                                 \
  94. uint8_t  nTask;                                                       \
  95.                                                                       \
  96. void taskIdle(void) {                                                 \
  97.   while(1){                                                           \
  98.     IDLE_HOOK();                                                      \
  99.     __nop();                                                          \
  100.   }                                                                   \
  101. }                                                                     \
  102. void  SysTick_Handler (void) {                                        \
  103.     uint8_t i;                                                        \
  104.     bool bOneSwitch;                                                  \
  105.     SYS_TICK_HOOK();                                                  \
  106.     bOneSwitch = false;                                               \
  107.     for(i = 0; i < nTask; i++){                                       \
  108.       if(taskTCB[i].delay != 0){                                      \
  109.         taskTCB[i].delay--;                                           \
  110.       }                                                               \
  111.       if(bOneSwitch == false){                                        \
  112.         taskCnt %= nTask;                                             \
  113.         if(0 == taskTCB[taskCnt].delay){                              \
  114.           bOneSwitch = true;                                          \
  115.           taskNew = &taskTCB[taskCnt];                                \
  116.           }                                                           \
  117.         taskCnt++;                                                    \
  118.         }                                                             \
  119.     }                                                                 \
  120.     if(bOneSwitch == false)                                           \
  121.       taskNew = &taskTCB[nTask];                                      \
  122.     taskSwitch();                                                     \
  123. }                                                                     \
  124.                                                                       \
  125.                                                                       \
  126. void switchDelayMs(uint16_t nTick) {                                  \
  127.     uint8_t i;                                                        \
  128.     if(0 == nTick)                                                    \
  129.       return;                                                         \
  130.                                                                       \
  131.     taskRuning->delay = nTick;                                        \
  132.     for(i = 0; i < nTask; i++){                                       \
  133.                                                                                \
  134.       if(0 == taskTCB[taskCnt].delay){                                \
  135.          taskNew = &taskTCB[taskCnt++];                               \
  136.          break;                                                       \
  137.       }else taskCnt++;                                                \
  138.     }                                                                 \
  139.     if(taskRuning == taskNew)                                         \
  140.       taskNew = &taskTCB[nTask];                                      \
  141.     taskSwitch();                                                     \
  142. }                                                                     \
  143.                                                                       \
  144.                                                                       \
  145. void switchTaskInt(void (*task)(void), uint32_t *ptos) {              \
  146.     if(MAX_TASK + 1 <= taskCnt){                                      \
  147.       taskCnt = 0;                                                    \
  148.       return;                                                         \
  149.     }                                                                 \
  150.     *(ptos)    = (uint32_t)0x01000000L;                               \
  151.     *(--ptos)  = (uint32_t)task;                                      \
  152.     taskTCB[taskCnt++]. pTaskStack =  ptos -14;                       \
  153. }                                                                     \
  154.                                                                       \
  155.                                                                       \
  156. void switchStart(void){                                               \
  157.   switchTaskCreate(taskIdle, 256);                                    \
  158.   if(taskCnt < (MAX_TASK + 1))                                        \
  159.     nTask = taskCnt;                                                  \
  160.   else                                                                \
  161.     nTask = MAX_TASK;                                                 \
  162.   setPSP(0);                                                          \
  163.   SysTick_Config((SYSTEM_CLK_NMHZ / N_TICK_IN_SECOND) - 1);           \
  164.   while(1);                                                           \
  165. }

  166. #define switchTaskCreate(task, stackSize) {__align(8) static uint32_t task##Stack[stackSize / 4]; \
  167.                                            switchTaskInt(task, &task##Stack[(stackSize/4)-1]);    \
  168.                                           }

  169. #endif

  170. //------------------------------------------------------------------------------------
  171. //                                    Demo code
  172. //------------------------------------------------------------------------------------
  173. #if(0)

  174. #define   SWITCH_EN
  175. #include  "switch.h"

  176. void tickHook(void)
  177. {
  178.         //不得放入阻塞\复杂\死循环代码       
  179. }
  180.        
  181. void idleHook(void)
  182. {
  183.        
  184. }       

  185. //配置参数:最大任务数  1秒Tick数 系统时钟  时钟钩子  空闲钩子
  186. SWITCH_CONFIG(2, 100, 72000000, tickHook, idleHook);

  187.        
  188. void task0(void){                         //任务0
  189.    for(;;){
  190.    //这放入您的代码
  191.    switchDelayMs(200);                    //可用delay()释放CPU
  192.    }
  193. }
  194.   
  195. void task1(void){                         //任务1
  196.   for(;;){
  197.   //这放入您的代码
  198.   switchDelayMs(1);                       //可用delay()释放CPU
  199.   }
  200. }

  201.        

  202. int main(void){
  203.   switchTaskCreate(task0, 60);            //在调度前建立任务
  204.   switchTaskCreate(task1, 30);            //在调度前建立任务
  205.   switchStart();                          //开始调度
  206. }
  207. #endif

  208. #endif

  209. //------------------------------------------------------------------------------------
  210. //                                    End of file
  211. //------------------------------------------------------------------------------------

  212.    
复制代码

出0入0汤圆

发表于 2015-5-13 10:48:11 | 显示全部楼层
STM32可用?

出0入0汤圆

发表于 2015-5-13 10:51:16 | 显示全部楼层
码一个,改天试试

出0入0汤圆

发表于 2015-5-13 11:22:41 | 显示全部楼层
来个压缩文件分享一下,谢谢!

出0入0汤圆

发表于 2015-5-13 13:14:36 | 显示全部楼层
MARK.看看。。。。

出0入0汤圆

发表于 2015-5-13 14:09:36 | 显示全部楼层
楼主把汇编部分讲解下吧,汇编看起来太累!

出0入0汤圆

发表于 2015-5-13 14:27:32 | 显示全部楼层
MARK之。。。坐等傻孩子点评!!!

出0入8汤圆

发表于 2015-5-13 14:37:52 | 显示全部楼层
果断小白鼠一下,帮顶~

出0入0汤圆

发表于 2015-5-13 17:11:24 | 显示全部楼层
有空仔细研究一下

出0入0汤圆

发表于 2015-5-13 17:14:19 | 显示全部楼层
mark  试试看

出0入0汤圆

发表于 2015-5-13 17:25:08 | 显示全部楼层
有时间试试,貌似不错。

出0入0汤圆

发表于 2015-5-13 19:12:29 | 显示全部楼层
楼主汇编看不懂啊,

出0入0汤圆

 楼主| 发表于 2015-5-13 20:34:42 | 显示全部楼层

可用

出0入0汤圆

发表于 2015-5-13 20:34:53 | 显示全部楼层
LZ是转过来的吗

出0入0汤圆

 楼主| 发表于 2015-5-13 20:36:09 | 显示全部楼层
xad74 发表于 2015-5-13 20:34
LZ是转过来的吗

欢迎找原文,找到有奖励。哈哈

出0入0汤圆

 楼主| 发表于 2015-5-13 20:37:54 | 显示全部楼层
embeddev_1 发表于 2015-5-13 14:09
楼主把汇编部分讲解下吧,汇编看起来太累!

大概的意思就是产生个软件异常中断,再切换任务栈。

出0入0汤圆

 楼主| 发表于 2015-5-13 20:42:08 | 显示全部楼层
creep 发表于 2015-5-13 11:22
来个压缩文件分享一下,谢谢!

没有细看帖子啊,整个调度器就一个头文件,还带demo还有什么好说的?

出0入4汤圆

发表于 2015-5-15 14:29:44 | 显示全部楼层
LZ高人!虽然不懂汇编,还是要拿来玩一下。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-20 09:15

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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