zoukankan      html  css  js  c++  java
  • 嵌入式框架Zorb Framework搭建七:任务的实现

    我是卓波,我是一名嵌入式工程师,我万万没想到我会在这里跟大家吹牛皮。

    嵌入式框架Zorb Framework搭建过程

    嵌入式框架Zorb Framework搭建一:嵌入式环境搭建、调试输出和建立时间系统

    嵌入式框架Zorb Framework搭建二:环形缓冲区的实现

    嵌入式框架Zorb Framework搭建三:列表的实现

    嵌入式框架Zorb Framework搭建四:状态机的实现

    嵌入式框架Zorb Framework搭建五:事件的实现

    嵌入式框架Zorb Framework搭建六:定时器的实现

    嵌入式框架Zorb Framework搭建七:任务的实现

    一、前言

      在开发程序时,有时候会发现单线程程序开发起来比较吃力,要是可以多线程那该多好。本篇要为Zorb Framework提供多线程功能,也就是多任务功能。

    二、任务功能设计

      我们先来看看要实现的任务提供什么功能:

      初步要提供的功能如下:

      1、可以开始和停止任务

      2、任务有优先级区分

      3、可以进行系统延时

      4、可以知道任务的运行时间

      5、可以动态创建和销毁任务

      因此,初步设计的数据结构如下:

     1 /* 任务状态 */
     2 typedef enum _TaskState
     3 {
     4     TASK_STATE_STOP = 0,          /* 停止 */
     5     TASK_STATE_RUNNING            /* 运行 */
     6 } TaskState;
     7 
     8 /* 任务结构 */
     9 typedef struct _Task
    10 {
    11     uint32_t *pStkPtr;            /* 堆栈指针 */
    12     uint32_t *pStkBase;           /* 堆栈基地址 */
    13     uint32_t StkSize;             /* 堆栈大小 */
    14     uint32_t DelayTime;           /* 任务延时时间(系统周期) */
    15     uint8_t Priority;             /* 任务优先级 */
    16     uint8_t State;                /* 任务状态 */
    17     uint32_t RunTime;             /* 任务总运行时间(系统周期) */
    18     
    19     /* 开始任务 */
    20     bool (*Start)(struct _Task * const pTask);
    21     
    22     /* 停止任务 */
    23     bool (*Stop)(struct _Task * const pTask);
    24     
    25     /* 销毁任务 */
    26     void (*Dispose)(struct _Task * const pTask);
    27     
    28     /* 延时任务 */
    29     bool (*Delay)(struct _Task * const pTask, uint32_t tick);
    30 } Task;

      为Zorb Framework提供的任务功能比较简单,状态也只有运行和关闭两种状态。任务功能实现的关键在于任务调度,而任务调度的核心又在于任务堆栈的保存和恢复。这部分需要根据使用的芯片进行修改,在STM32中,通过触发PendSV异常进行任务切换:

     1 /******************************************************************************
     2  * 描述  :PendSV异常处理
     3  * 参数  :无
     4  * 返回  :无
     5 ******************************************************************************/
     6 __asm void PendSV_Handler(void)
     7 {
     8     IMPORT  pCurrentTask
     9     IMPORT  pTopPriorityTask
    10     
    11     /* 任务的保存,即把CPU寄存器的值存储到任务的堆栈中 */
    12     /* 关中断,NMI和HardFault除外 */
    13     CPSID   I
    14     
    15     /* 判断是否第一次运行 */
    16     MRS     R0, PSP
    17     CBZ     R0, PendSVHandler_NotSave
    18     
    19     /**
    20         在进入PendSV异常的时候,当前CPU的xPSR,PC(任务入口地址),
    21         R14,R12,R3,R2,R1,R0会自动存储到当前任务堆栈,同时递减PSP的值
    22     **/
    23     /* 手动存储CPU寄存器R4-R11的值到当前任务的堆栈 */
    24     STMDB   R0!, {R4-R11}
    25     
    26     /* R0指向pCurrentTask的堆栈指针(指向空闲位置的顶部) */
    27     LDR     R1, = pCurrentTask
    28     LDR     R1, [R1]
    29     STR     R0, [R1]
    30     NOP
    31     
    32 /* 任务的切换,即把下一个要运行的任务的堆栈内容加载到CPU寄存器中 */
    33 PendSVHandler_NotSave
    34 
    35     /* 等效操作pCurrentTask = pTopPriorityTask; */
    36     LDR     R0, = pCurrentTask
    37     LDR     R1, = pTopPriorityTask
    38     LDR     R2, [R1]
    39     STR     R2, [R0]
    40     
    41     /* pTopPriorityTask的信息出栈 */
    42     LDR     R0, [R2]
    43     LDMIA   R0!, {R4-R11}
    44     
    45     /* 设置PSP指向下一个要执行的任务的堆栈的栈底(已弹出了寄存器信息) */
    46     MSR     PSP, R0
    47     /* 确保异常返回使用的堆栈指针是PSP */
    48     ORR     LR, LR, #0x04 /* 设置LR寄存器的位2为1 */
    49     CPSIE   I /* 开中断 */
    50     
    51     /**
    52         函数返回,这个时候任务堆栈中的剩下内容将会自动加载到
    53         xPSR,PC(任务入口地址),R14,R12,R3,R2,R1,R0(任务的形参)
    54         同时PSP的值也将更新,即指向任务堆栈的栈顶。
    55         在STM32中,堆栈是由高地址向低地址生长的
    56     **/
    57     BX      LR
    58     NOP
    59 }

      具体实现请看附件代码或在文末的github地址拉框架源码。

    三、任务结果测试

      简单的测试代码如下:

      1 /**
      2   *****************************************************************************
      3   * @file    app_task.c
      4   * @author  Zorb
      5   * @version V1.0.0
      6   * @date    2018-06-28
      7   * @brief   任务测试的实现
      8   *****************************************************************************
      9   * @history
     10   *
     11   * 1. Date:2018-06-28
     12   *    Author:Zorb
     13   *    Modification:建立文件
     14   *
     15   *****************************************************************************
     16   */
     17 
     18 #include "app_task.h"
     19 #include "zf_includes.h"
     20 
     21 static Task *pTask1; /* 任务1 */
     22 static Task *pTask2; /* 任务2 */
     23 static Task *pTask3; /* 任务3 */
     24 
     25 static void Process1(void *pArg); /* 任务1程序定义 */
     26 static void Process2(void *pArg); /* 任务2程序定义 */
     27 static void Process3(void *pArg); /* 任务3程序定义 */
     28 
     29 /******************************************************************************
     30  * 描述  :任务1程序
     31  * 参数  :(in)-pArg  参数指针
     32  * 返回  :无
     33 ******************************************************************************/
     34 static void Process1(void *pArg)
     35 {
     36     ZF_DEBUG(LOG_D, "
    ");
     37     ZF_DEBUG(LOG_D, "system time is %dms
    ", ZF_SYSTIME_MS());
     38     ZF_DEBUG(LOG_D, "I am %s
    ", (char *)pArg);
     39     ZF_DEBUG(LOG_D, "task count is %d
    ", TASK_GET_TASK_COUNT());
     40     
     41     ZF_DEBUG(LOG_D, "I will create task3
    ");
     42     
     43     /* 创建任务3 */
     44     Task_create(&pTask3, Process3, "task3", 3, 256);
     45     
     46     ZF_DEBUG(LOG_D, "task count is %d
    ", TASK_GET_TASK_COUNT());
     47     
     48     ZF_DEBUG(LOG_D, "I will dispose myself
    ");
     49     
     50     pTask1->Dispose(pTask1);
     51 }
     52 
     53 /******************************************************************************
     54  * 描述  :任务2程序
     55  * 参数  :(in)-pArg  参数指针
     56  * 返回  :无
     57 ******************************************************************************/
     58 static void Process2(void *pArg)
     59 {
     60     while(1)
     61     {
     62         ZF_DEBUG(LOG_D, "
    ");
     63         ZF_DEBUG(LOG_D, "system time is %dms
    ", ZF_SYSTIME_MS());
     64         ZF_DEBUG(LOG_D, "I am %s
    ", (char *)pArg);
     65         ZF_DEBUG(LOG_D, "task count is %d
    ", TASK_GET_TASK_COUNT());
     66         ZF_DEBUG(LOG_D, "I will sleep 1000ms
    ");
     67         ZF_DEBUG(LOG_D, "wake up time is %dms
    ", ZF_SYSTIME_MS() + 1000);
     68         ZF_DELAY_MS(1000);
     69     }
     70 }
     71 
     72 /******************************************************************************
     73  * 描述  :任务3程序
     74  * 参数  :(in)-pArg  参数指针
     75  * 返回  :无
     76 ******************************************************************************/
     77 static void Process3(void *pArg)
     78 {
     79     while(1)
     80     {
     81         ZF_DEBUG(LOG_D, "
    ");
     82         ZF_DEBUG(LOG_D, "system time is %dms
    ", ZF_SYSTIME_MS());
     83         ZF_DEBUG(LOG_D, "I am %s
    ", (char *)pArg);
     84         ZF_DEBUG(LOG_D, "task count is %d
    ", TASK_GET_TASK_COUNT());
     85         ZF_DEBUG(LOG_D, "I will sleep 1000ms
    ");
     86         ZF_DEBUG(LOG_D, "wake up time is %dms
    ", ZF_SYSTIME_MS() + 1000);
     87         ZF_DELAY_MS(1000);
     88     }
     89 }
     90 
     91 /******************************************************************************
     92  * 描述  :任务初始化
     93  * 参数  :无
     94  * 返回  :无
     95 ******************************************************************************/
     96 void App_Task_init(void)
     97 {
     98     /* 创建任务1 */
     99     Task_create(&pTask1, Process1, "task1", 1, 512);
    100     /* 创建任务1 */
    101     Task_create(&pTask2, Process2, "task2", 2, 512);
    102     /* 运行任务系统 */
    103     Task_run();
    104     
    105     /* 程序不会到这 */
    106 }
    107 
    108 /******************************** END OF FILE ********************************/

      结果:

    system time is 3ms
    I am task1
    task count is 3
    I will create task3
    task count is 4
    I will dispose myself
    
    system time is 13ms
    I am task2
    task count is 3
    I will sleep 1000ms
    wake up time is 1019ms
    
    system time is 21ms
    I am task3
    task count is 3
    I will sleep 1000ms
    wake up time is 1028ms
    
    system time is 1021ms
    I am task2
    task count is 3
    I will sleep 1000ms
    wake up time is 2027ms
    
    system time is 1030ms
    I am task3
    task count is 3
    I will sleep 1000ms
    wake up time is 2036ms
    
    system time is 2029ms
    I am task2
    task count is 3
    I will sleep 1000ms
    wake up time is 3035ms
    
    system time is 2038ms
    I am task3
    task count is 3
    I will sleep 1000ms
    wake up time is 3044ms
    
    省略...

    四、最后

      本篇为Zorb Framework提供了任务功能。使用多任务功能进行开发是方便了许多,但同时任务间的协作和资源调用加大了调试和排错的难度。在享受多任务带来的快乐的同时,要做好排错时痛苦的准备。

     

      Zorb Framework github:https://github.com/54zorb/Zorb-Framework

      版权所有,转载请打赏哟

    如果你喜欢我的文章,可以通过微信扫一扫给我打赏哟

  • 相关阅读:
    SuperMap房产测绘成果管理平台
    SuperMap产权登记管理平台
    Android adb shell am 的用法(1)
    由浅入深谈Perl中的排序
    Android 内存监测和分析工具
    Android 网络通信
    adb server is out of date. killing...
    引导页使用ViewPager遇到OutofMemoryError的解决方案
    adb logcat 详解
    How to send mail by java mail in Android uiautomator testing?
  • 原文地址:https://www.cnblogs.com/54zorb/p/9337754.html
Copyright © 2011-2022 走看看