精华内容
下载资源
问答
  • Freertos学习--初识任务函数

    千次阅读 2012-10-09 09:55:47
      Freertos泛泛看了很多相关文章,有点头绪,除了不太喜欢其变量的...先来认识一下Freertos任务函数,看看这个系统是怎么操作任务的。(以下例子大部分来自网络)    1.任务创建  signed portBASE_TYPE xTaskC

    转自:http://blog.csdn.net/djjyi/article/details/6170025

     

    Freertos泛泛看了很多相关文章,有点头绪,除了不太喜欢其变量的名字,其他的倒还可以接受。先来认识一下Freertos任务函数,看看这个系统是怎么操作任务的。(以下例子大部分来自网络)

     

        1.任务创建

        signed portBASE_TYPE xTaskCreate(

        pdTASK_CODE pvTaskCode, --指向任务的入口函数

        const signed portCHAR * const pcName, --任务的名字

        unsigned portSHORT usStackDepth, --指定任务堆栈的大小 ,堆栈能保护变量的数目-

        void *pvParameters, --指针用于作为一个参数传向创建的任务

        unsigned portBASE_TYPE uxPriority, --任务的优先级

        xTaskHandle *pxCreatedTask )--用于传递一个处理

     

       例子:

        xTaskCreate( StarTask , ( signed portCHAR * ) "StarTask ", 128, NULL, tskIDLE_PRIORITY, NULL );

        我们先按任务创建函数设定好任务的入口名字StarTask ,任务名字StarTask ,堆栈大小128,优先级等,然后编写我们任务StarTask 的内容,下面就是任务StarTask函数:

        void StarTask (void *pvParameter)

        {}

      

        2.任务删除

           void vTaskDelete( xTaskHandle pxTaskToDelete )

           例子:

            void vOtherFunction( void )

         {

          xTaskHandle xHandle;

         // 创建任务,存储处理

         xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );

         // 使用处理来删除任务. 

         vTaskDelete( xHandle );

          }

           注:INCLUDE_vTaskDelete必须定义为1,这个函数才能可用

       3.任务延时

       void vTaskDelay( portTickType xTicksToDelay );

           例子:

            const portTickType xDelay = 1000/ portTICK_RATE_MS;

     注:INCLUDE_vTaskDelay必须设置为1,这个函数才为可用。

     

        4.任务延时--延时一个任务到指定时间

            void vTaskDelayUntil(

             portTickType *pxPreviousWakeTime, --指定一个变量来掌握任务最后开启的时间,                                  这个变量在第一次使用中(参考下面的例子)必须                                    使用当前时间来初始化

             portTickType xTimeIncrement );--循环周期时间。任务将在一定时间开启                               (*pxPreviousWakeTime + xTimeIncrement)

            例子:

      void vTaskFunction( void * pvParameters )

          注:INCLUDE_vTaskDelayUntil 必须定义为1,此函数才能用。

          5.获取任务优先级

         unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask );

        7.任务挂起或暂停

            void vTaskSuspend(

            xTaskHandle pxTaskToSuspend ); --处理需要挂起的任务。传递NULL将挂起调用此函数的任务。

     

        例子:

     void vAFunction( void )

     {

     xTaskHandle xHandle;

         // 创建任务,保存句柄

         xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );

         // ...

         // 使用此句柄来挂起创建的任务

         vTaskSuspend( xHandle );

         // ...

         // 创建的任务不会在这期间运行,除非

         // 其他任务调用 vTaskResume( xHandle )

         //...

         // 挂起自己

         vTaskSuspend( NULL );

         // 不能运行到这里,除非另一个任务调用vTaskResume

      }

     

    注:设置INCLUDE_vTaskSuspend 为1,此函数才能使用。

       8.任务恢复

      void vTaskResume( xTaskHandle pxTaskToResume );

        9.启动内核

            void vTaskStartScheduler( void );

     

     

          

     

      

    必须是调用 vTaskSuspend () 后挂起的任务,才有可能通过调用 vTaskResume ()重新运行。

         

         例子:

     

    注:设置INCLUDE_vTaskSuspend为1,此函数才能使用。

     void vAFunction( void )

     {

        xTaskHandle xHandle;

         // 创建任务,保存句柄

         xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );

         // ...

         // 使用此句柄来挂起创建的任务

         vTaskSuspend( xHandle );

         // ...

         // 创建的任务不会在此期间运行,除

         // 另外一个任务调用 vTaskResume( xHandle )

         //...

         // 唤醒自己

         vTaskResume( xHandle );

      }

     

     

           例子:

     

          注:设置INCLUDE_vTaskPriorityGet 为1,此函数才能用。

     6.设置任务优先级

     

     

           void vTaskPrioritySet(

           xTaskHandle pxTask, --需要设置优先级的任务。当传递NULL,将设置调用任务的优先级

           unsigned portBASE_TYPE uxNewPriority );--任务需要设置的优先级

        例子: 

     void vAFunction( void )

     {

     xTaskHandle xHandle;

         // 创建任务,准备处理

         xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );

         // 使用其句柄来提高创建任务的优先级

         vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 );

         // 使用NULL处理,来提高优先级到同一个值

         vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 );

     }

    注:设置INCLUDE_vTaskPrioritySet为1,才能使用此函数

     

     

     

     

     {

      portTickType xLastWakeTime;

      const portTickType xFrequency = 10;

     

         // 使用当前时间 初始化xLastWakeTime 变量

         xLastWakeTime = xTaskGetTickCount();

     

         for( ;; )

         {

             // 等待下一个循环

             vTaskDelayUntil( &xLastWakeTime, xFrequency );

              // 执行区域

         }

     }

     

           for( ;; )

         {

             /* 简单的每 500ms触发LED, .在每两次触发间挂起*/

             vONLED();

             vTaskDelay( xDelay );

         }

    xTicksToDelay 是指延时的时间片个数,

     void vAFunction( void )

     {

         xTaskHandle xHandle;

         // 创建任务,准备处理 

         xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );

     

     

         // / 使用 tskIDLE_PRIORITY创建, 但是可能改

     

         if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY )

         {

             // 任务已经改变了其优先级

         }

      }

     

    展开全文
  • 进程池 apply_async里任务函数不执行

    千次阅读 2019-06-21 21:22:26
    这个问题搞了很久,除了网上大神们说的参数后面必须加逗号之外还有队列,原来redis对象也不能写在init初始化方法里面,不知道什么原因,写在外面,进程池ok,任务开始执行。还望解惑,谢谢 redis_conn_1 = ...

    这个问题搞了很久,除了网上大神们说的参数后面必须加逗号之外还有队列,原来redis对象也不能写在init初始化方法里面,不知道什么原因,写在外面,进程池ok,任务开始执行。还望解惑,谢谢

    redis_conn_1 = RedisUtil(db=1)  # redis对象放在init方法里面,进程池不执行,不知道原因,所以写在了这里
    
    
    class StartDisguise(object):
    
        def __init__(self):
            self.cc = ChaosCombination()
    
        def wait_disguise(self):
    
            pool = Pool(MAX_PROCESS_NUM)
            while True:
    
                time.sleep(random.randint(1, 3))
                print('有任务吗,来看看')
                task_disguise_info = redis_conn_1.get_connection().brpop('disguise_content_queue', timeout=3)
                print('从redis里面取到的数据是:', task_disguise_info)
                if task_disguise_info:
    
                    key, task_disguise_bytes = task_disguise_info
                    task_disguise_dict = json.loads(str(task_disguise_bytes, encoding="utf-8"))
                    user_name = task_disguise_dict.get('user_name')
                    task_id = task_disguise_dict.get('task_id')
                    key_word = task_disguise_dict.get('key_word')
                    item = task_disguise_dict.get('item')
                    pool.apply_async(self.insert_into_table_from_disguise_text, args=(item, user_name, task_id, key_word,))
                    
    
        def insert_into_table_from_disguise_text(self, item, user_name, task_id, key_word):
            print('进程2', os.getpid())
            print('多进程开始处理====>>>>')
    展开全文
  • FreeRTOS任务API函数的使用

    千次阅读 2017-08-27 18:01:41
    FreeRTOS 任务函数API

    这篇文章最后的demo工程可以在网盘中自行下载:
    链接:https://pan.baidu.com/s/1o1U-niMKu0RuDAFio1nKMA 密码:ysev

    本文是《ALIENTEK STM32F429 FreeRTOS 开发教程》第六章学习笔记
    第一章笔记–FreeRTOS简介与源码下载
    第二章笔记–FreeRTOS在STM32F4上移植
    第三章笔记-FreeRTOS系统配置
    第四章笔记-FreeRTOS中断分析
    第四章笔记补充-FreeRTOS临界段代码
    第五章笔记-FreeRTOS任务基础

    1. 任务创建和删除API函数

    1.1 xTaskCreate()

    函数xTaskCreate()使用动态的方法创建一个任务,创建人物所需的RAM自动从FreeRTOS的堆中分配,宏configSUPPORT_DYNAMIC_ALLOCATION必须为1

    函数原型:

        BaseType_t xTaskCreate( 
        TaskFunction_t pxTaskCode,
        const char * const pcName,
        const uint16_t usStackDepth,
        void * const pvParameters,
        UBaseType_t uxPriority,
        TaskHandle_t * const pxCreatedTask ) 

    pxTaskCode: 任务函数

    pcName: 任务名字,任务名字长度不能超过 configMAX_TASK_NAME_LEN

    usStackDepth: 任务堆栈大小,实际申请堆栈是usStackDepth的4倍(因为这里是uint16,而申请时的类型是uint32).空闲任务的堆栈大小为configMINIMAL_STACK_SIZE

    pvParameters: 传递给任务函数的参数

    uxPriotiry: 任务优先级,范围0~configMAX_PRIORITIES-1

    pxCreatedTask: 任务句柄,任务创建成功以后返回此任务的任务句柄,任务句柄其实就是这个任务的任务堆栈。此参数就是用来保存这个任务句柄,其他API函数可能会使用到这个任务句柄。

    返回值:

    pdPASS: 任务创建成功

    errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY: 任务创建失败,堆内存不足。

    1.2 xTaskCreateStatic()

    此函数与xTaskCreate()的功能相同,但是创建任务所需的RAM需要用户来提供,宏configSUPPORT_STATIC_ALLOCATION必须定义为1

    函数原型:

    xTaskCreateStatic(
        TaskFunction_t pxTaskCode,
        const char * const pcName,
        const uint32_t ulStackDepth,
        void * const pvParameters,
        UBaseType_t uxPriority,
        StackType_t * const puxStackBuffer,
        StaticTask_t * const pxTaskBuffer )

    pxTaskCode: 任务函数

    pcName:任务名字,任务名字长度不能超过 configMAX_TASK_NAME_LEN

    usStackDepth: 任务堆栈大小,由于此函数是用静态方法创建任务,所以任务堆栈由用户给出,一般是一个数组,此参数就是这个数组的大小

    pvParameters: 传递给任务函数的参数

    uxPriotiry: 任务优先级,范围0~configMAX_PRIORITIES-1

    puxStackBuffer: 任务堆栈,一般为数组,类型为StackType_t

    pxTaskBuffer: 任务控制块

    返回值:

    NULL: 任务创建失败,pxTaskBuffer或puxStackBuffer为NULL时会导致错误发生

    其他值:任务创建成功,返回任务的任务句柄

    1.3 VTaskDelete()

    删除一个已经创建乐的任务,被删除的任务不再存在(不会进入运行态)。任务被删除后不能再使用此任务的句柄。

    若是用动态方法创建,删除任务后,此任务之前申请的堆栈和控制块内存会在空闲任务中被释放掉,因此当调用函数vTaskDelete()删除任务以后必须给空闲任务一定的运行时间

    若是静态方法创建任务,删除任务后用户分配给任务的内存需要用户自行释放掉。

    函数原型:

    void vTaskDelete( TaskHandle_t xTaskToDelete )

    xTaskDelete: 要删除的任务的任务句柄

    2. 任务创建和删除

    2.1 任务相关声明:

    //任务优先级
    #define START_TASK_PRIO         1
    //任务堆栈大小    
    #define START_STK_SIZE          256  
    //任务句柄
    TaskHandle_t StartTask_Handler;
    //任务函数
    void start_task(void *pvParameters);
    
    //任务优先级
    #define LED0_TASK_PRIO      2
    //任务堆栈大小    
    #define LED0_STK_SIZE       50  
    //任务句柄
    TaskHandle_t LED0Task_Handler;
    //任务函数
    void led0_task(void *pvParameters);
    
    //任务优先级
    #define LED1_TASK_PRIO      3
    //任务堆栈大小    
    #define LED1_STK_SIZE       50  
    //任务句柄
    TaskHandle_t LED1Task_Handler;
    //任务函数
    void led1_task(void *pvParameters);

    声明了每个任务的优先级,堆栈大小和句柄,以及任务函数

    2.2 main()

    int main(void)
    {
      HAL_Init();                     //初始化HAL库   
      Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhz
        delay_init(180);                //初始化延时函数
        uart_init(115200);              //初始化串口
      LED_Init();                     //初始化LED 
    
        xTaskCreate((TaskFunction_t )start_task,            //任务函数
                  (const char*    )"start_task",          //任务名称
                  (uint16_t       )START_STK_SIZE,        //任务堆栈大小
                  (void*          )NULL,                  //传递给任务函数的参数
                  (UBaseType_t    )START_TASK_PRIO,       //任务优先级
                                (TaskHandle_t*  )&StartTask_Handler);   //任务句柄        
        vTaskStartScheduler();//开启任务调度
    }

    用来初始化相关硬件,并且调用函数xTaskCreate()创建start_task任务,再调用函数vTaskStartScheduler()开启FreeRTOS的任务调度器,FreeRTOS开始运行

    2.3 任务函数

    //开始任务任务函数
    void start_task(void *pvParameters)
    {
        taskENTER_CRITICAL();           //进入临界区
        //创建LED0任务
        xTaskCreate((TaskFunction_t )led0_task,         
                    (const char*    )"led0_task",       
                    (uint16_t       )LED0_STK_SIZE, 
                    (void*          )NULL,              
                    (UBaseType_t    )LED0_TASK_PRIO,    
                    (TaskHandle_t*  )&LED0Task_Handler);   
        //创建LED1任务
        xTaskCreate((TaskFunction_t )led1_task,     
                    (const char*    )"led1_task",   
                    (uint16_t       )LED1_STK_SIZE, 
                    (void*          )NULL,
                    (UBaseType_t    )LED1_TASK_PRIO,
                    (TaskHandle_t*  )&LED1Task_Handler);        
        vTaskDelete(StartTask_Handler); //删除开始任务
        taskEXIT_CRITICAL();            //退出临界区
    }
    //LED0任务函数 
    void led0_task(void *pvParameters)
    {
        while(1)
        {
            LED0=~LED0;
            vTaskDelay(500);
        }
    }   
    
    //LED1任务函数
    void led1_task(void *pvParameters)
    {
        while(1)
        {
            LED1=0;
            vTaskDelay(200);
            LED1=1;
            vTaskDelay(800);
        }
    }

    start_task任务的任务函数中创建了另外两个任务led0_task和led1_task。这个任务用来创建其他任务,完成之后调用vTaskDelete(StartTask_Handler)删除掉开始任务

    led0_task的任务函数每隔500ms让LED0亮灭反转,led1_task的任务函数间隔200ms和800ms来回反转LED1

    3. 任务挂起和恢复API函数

    暂停某个任务的运行,过一段时间再重新运行。 任务挂起后任务中变量保存的值不变,而任务删除和重建后任务中变量保存的值会丢失。

    3.1 vTaskSuspend()

    此函数用于将某个任务设置为挂起状态。

    函数原型:

    void vTaskSuspend( TaskHandle_t xTaskToSuspend )

    xTaskToSuspend: 要挂起任务的任务句柄。如果参数为NULL表示挂起任务自己。

    3.2 vTaskResume()

    将一个任务从挂起态恢复到就绪态

    函数原型:

    void vTaskResume( TaskHandle_t xTaskToResume )

    xTaskToResume: 要恢复任务的任务句柄

    3.3 xTaskResumeFromISR()

    此函数用于在中断服务函数中恢复一个任务,是vTaskResume()的中断版本
    函数原型:

    BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )

    xTaskResumeFromISR:要恢复任务的任务句柄

    返回值:

    pdTRUE: 恢复运行的任务的任务优先级等于或高于正在运行的任务(被中断打断的任务),在退出中断服务函数以后必须进行一次上下文切换

    pdFALSE: 恢复运行的任务的任务优先级低于正在运行的任务(被中断打断的任务),在退出中断服务函数以后不需要进行一次上下文切换

    4. 任务挂起和恢复

    4.1 任务相关声明:

    #define START_TASK_PRIO         1
    //任务堆栈大小    
    #define START_STK_SIZE          256  
    //任务句柄
    TaskHandle_t StartTask_Handler;
    //任务函数
    void start_task(void *pvParameters);
    
    //任务优先级
    #define KEY_TASK_PRIO   2
    //任务堆栈大小    
    #define KEY_STK_SIZE        128  
    //任务句柄
    TaskHandle_t KEYTask_Handler;
    //任务函数
    void key_task(void  *pvParameters);
    
    //任务优先级
    #define LED0_TASK_PRIO      3
    //任务堆栈大小    
    #define LED0_STK_SIZE       50  
    //任务句柄
    TaskHandle_t LED0Task_Handler;
    //任务函数
    void led0_task(void *pvParameters);
    
    //任务优先级
    #define LED1_TASK_PRIO      4
    //任务堆栈大小    
    #define LED1_STK_SIZE       50  
    //任务句柄
    TaskHandle_t LED1Task_Handler;
    //任务函数
    void led1_task(void  *pvParameters);
    

    4.2 main()

    int main(void)
    {
      HAL_Init();                     //初始化HAL库   
      Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhz
        delay_init(180);                //初始化延时函数
        uart_init(115200);              //初始化串口
      LED_Init();                     //初始化LED 
      KEY_Init();                     //初始化KEY
    
        xTaskCreate((TaskFunction_t )start_task,            //任务函数
                  (const char*    )"start_task",          //任务名称
                  (uint16_t       )START_STK_SIZE,        //任务堆栈大小
                  (void*          )NULL,                  //传递给任务函数的参数
                  (UBaseType_t    )START_TASK_PRIO,       //任务优先级
                                (TaskHandle_t*  )&StartTask_Handler);   //任务句柄        
        vTaskStartScheduler();//开启任务调度
    }

    4.3 任务函数

    //开始任务任务函数
    void start_task(void *pvParameters)
    {
        taskENTER_CRITICAL();           //进入临界区
          //创建KEY任务
            xTaskCreate((TaskFunction_t )key_task,      
                    (const char*    )"key_task",    
                    (uint16_t       )KEY_STK_SIZE, 
                    (void*          )NULL,              
                    (UBaseType_t    )KEY_TASK_PRIO, 
                    (TaskHandle_t*  )&KEYTask_Handler);  
        //创建LED0任务
        xTaskCreate((TaskFunction_t )led0_task,         
                    (const char*    )"led0_task",       
                    (uint16_t       )LED0_STK_SIZE, 
                    (void*          )NULL,              
                    (UBaseType_t    )LED0_TASK_PRIO,    
                    (TaskHandle_t*  )&LED0Task_Handler);   
        //创建LED1任务
        xTaskCreate((TaskFunction_t )led1_task,     
                    (const char*    )"led1_task",   
                    (uint16_t       )LED1_STK_SIZE, 
                    (void*          )NULL,
                    (UBaseType_t    )LED1_TASK_PRIO,
                    (TaskHandle_t*  )&LED1Task_Handler);        
        vTaskDelete(StartTask_Handler); //删除开始任务
        taskEXIT_CRITICAL();            //退出临界区
    }
    //KEY任务函数
    void key_task(void *pvParameters)
    {
        u8 key;
        while(1)
        {
            key=KEY_Scan(0);
            switch(key)
            {
                case WKUP_PRES:
                    vTaskSuspend(LED0Task_Handler);//挂起任务led0
                    printf("挂起LED0!\r\n");
                    break;
                case KEY0_PRES:
                    vTaskResume(LED0Task_Handler);  //恢复任务led0
                    printf("恢复LED0!\r\n");
                    break;
                case KEY1_PRES:
                    vTaskSuspend(LED1Task_Handler);//挂起任务led1
                    printf("挂起LED1!\r\n");
                    break;
                case KEY2_PRES:
                    vTaskResume(LED1Task_Handler);//恢复任务led1
                    printf("恢复LED1!\r\n");
                    break;  
            }
            vTaskDelay(10);         //延时10ms 
        }
    }
    //LED0任务函数 
    void led0_task(void *pvParameters)
    {
        while(1)
        {
            LED0=~LED0;
            vTaskDelay(500);
        }
    }   
    
    //LED1任务函数
    void led1_task(void *pvParameters)
    {
        while(1)
        {
            LED1=0;
            vTaskDelay(200);
            LED1=1;
            vTaskDelay(800);
        }
    }

    start_task任务创建了三个任务函数后删除自己;

    key_task任务函数进行按键扫描,当WKUP按下 挂起任务led0_task;当KEY0按下,恢复任务led0_task;当KEY1按下,挂起任务led1_task;当KEY2按下,恢复任务led1_task;并且串口输出打印在电脑端显示
    这里写图片描述

    led0_task和led1_task 分别控制LED0和LED1闪烁

    展开全文
  • FreeRTOS任务延时函数

    千次阅读 2019-03-01 00:04:33
    系统提供了两个任务延时函数:相对延时函数vTaskDelay()和绝对延时函数vTaskDelayUntil() 相对延时是指:vTaskDelay()开始执行到退出执行的时间固定 /* 相对延时函数 */ void vTaskDelay(const TickType_t ...

    系统提供了两个任务延时函数:相对延时函数vTaskDelay()和绝对延时函数vTaskDelayUntil()

    相对延时是指:vTaskDelay()开始执行到退出执行的时间固定

    /* 相对延时函数 */
    void vTaskDelay(const TickType_t xTicksToDelay)
    {
    	BaseType_t xAlreadyYielded = pdFALSE;
    
    	/* 延时时间大于0 */
    	if(xTicksToDelay > (TickType_t)0U)
    	{
    		configASSERT(uxSchedulerSuspended == 0);
    		
    		/* 调度器挂起 */
    		vTaskSuspendAll();
    		{
    			traceTASK_DELAY();
    
    			/* 将任务添加到延时列表 */
    			prvAddCurrentTaskToDelayedList(xTicksToDelay, pdFALSE);
    		}
    		/* 解除调度器挂起,解除的时候可能请求调度 */
    		xAlreadyYielded = xTaskResumeAll();
    	}
    	else
    	{
    		mtCOVERAGE_TEST_MARKER();
    	}
    
    	/* 解除调度器挂起的时候没有请求调度 */
    	if(xAlreadyYielded == pdFALSE)
    	{
    		/* 请求切换任务 */
    		portYIELD_WITHIN_API();
    	}
    	else
    	{
    		mtCOVERAGE_TEST_MARKER();
    	}
    }

     

     

    绝对延时是指:相邻两次vTaskDelayUntil()唤醒的时间固定

    /* 绝对延时 */
    void vTaskDelayUntil(TickType_t *const pxPreviousWakeTime, const TickType_t xTimeIncrement)
    {
    	TickType_t xTimeToWake;
    	BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;
    
    	configASSERT(pxPreviousWakeTime);
    	configASSERT((xTimeIncrement > 0U));
    	configASSERT(uxSchedulerSuspended == 0);
    
    	/* 挂起调度器 */
    	vTaskSuspendAll();
    	{
    		const TickType_t xConstTickCount = xTickCount;
    
    		/* 下一次任务唤醒时间 */
    		xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
    
    		/* 前一次唤醒时间大于系统当前节拍,说明系统节拍已经溢出 */
    		if(xConstTickCount < *pxPreviousWakeTime)
    		{
    			/* 下一次唤醒时间小于前一次唤醒时间,说明下一次唤醒时间溢出 */
    			/* 下一次唤醒时间大于系统当前节拍 */
    			/* 综上,下一次唤醒时间在当前系统节拍的后面 */
    			if((xTimeToWake < *pxPreviousWakeTime) && (xTimeToWake > xConstTickCount))
    			{
    				/* 应该延时 */
    				xShouldDelay = pdTRUE;
    			}
    			else
    			{
    				mtCOVERAGE_TEST_MARKER();
    			}
    		}
    		/* 系统节拍没有溢出 */
    		else
    		{
    			/* 下一次唤醒时间小于前一次唤醒时间,说明下一次唤醒时间溢出 */
    			/* 或者下一次唤醒时间大于当前系统节拍 */
    			/* 综上,下一次唤醒时间在当前系统节拍的后面 */
    			if((xTimeToWake < *pxPreviousWakeTime) || (xTimeToWake > xConstTickCount))
    			{
    				/* 应该延时 */
    				xShouldDelay = pdTRUE;
    			}
    			else
    			{
    				mtCOVERAGE_TEST_MARKER();
    			}
    		}
    
    		/* 将下一次唤醒时间赋值给pxPreviousWakeTime,留作下一次使用 */
    		*pxPreviousWakeTime = xTimeToWake;
    
    		/* 需要延时 */
    		if(xShouldDelay != pdFALSE)
    		{
    			traceTASK_DELAY_UNTIL(xTimeToWake);
    
    			/* 将任务添加到延时列表,延时时长为当前节拍到唤醒时间 */
    			prvAddCurrentTaskToDelayedList(xTimeToWake - xConstTickCount, pdFALSE);
    		}
    		else
    		{
    			mtCOVERAGE_TEST_MARKER();
    		}
    	}
    	/* 解除调度器挂起,解除的时候可能切换任务 */
    	xAlreadyYielded = xTaskResumeAll();
    	/* 解除调度器挂起的时候没有切换任务 */
    	if(xAlreadyYielded == pdFALSE)
    	{
    		/* 请求切换任务 */
    		portYIELD_WITHIN_API();
    	}
    	else
    	{
    		mtCOVERAGE_TEST_MARKER();
    	}
    }

     

     

    系统节拍采用32位计数,所以最终肯定会溢出,同样唤醒时间也存在溢出。系统一共维护了两个延时列表,分别是延时列表和溢出延时列表,两条列表都是按照唤醒时间的从小到大进行排列。当唤醒时间溢出的时候,就不能和没溢出的插入同一个列表了。系统将唤醒时间没有溢出的任务放入延时列表,将唤醒时间溢出的任务放入溢出延时列表。

    /* 将任务添加到延时列表 */
    static void prvAddCurrentTaskToDelayedList(TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely)
    {
    	TickType_t xTimeToWake;
    	const TickType_t xConstTickCount = xTickCount;
    
    	#if (INCLUDE_xTaskAbortDelay == 1)
    	{
    		pxCurrentTCB->ucDelayAborted = pdFALSE;
    	}
    	#endif
    
    	/* 当前任务肯定挂接在就绪列表中,将其移除。该就绪列表中没有任何任务 */
    	if(uxListRemove(&(pxCurrentTCB->xStateListItem)) == (UBaseType_t)0)
    	{
    		/* 清除任务优先级记录中的优先级 */
    		portRESET_READY_PRIORITY(pxCurrentTCB->uxPriority, uxTopReadyPriority);
    	}
    	else
    	{
    		mtCOVERAGE_TEST_MARKER();
    	}
    
    	#if (INCLUDE_vTaskSuspend == 1)
    	{
    		/* 延时时间为portMAX_DELAY并且允许无限期阻塞 */
    		if((xTicksToWait == portMAX_DELAY) && (xCanBlockIndefinitely != pdFALSE))
    		{
    			/* 将任务挂接到挂起列表 */
    			vListInsertEnd(&xSuspendedTaskList, &(pxCurrentTCB->xStateListItem));
    		}
    		else
    		{
    			/* 计算唤醒时间 */
    			xTimeToWake = xConstTickCount + xTicksToWait;
    
    			/* 设置状态列表项值为唤醒时间 */
    			listSET_LIST_ITEM_VALUE(&(pxCurrentTCB->xStateListItem), xTimeToWake);
    
    			/* 唤醒时间小于当前节拍说明已经溢出了 */
    			if(xTimeToWake < xConstTickCount)
    			{
    				/* 将当前任务挂接到延时溢出列表 */
    				vListInsert(pxOverflowDelayedTaskList, &(pxCurrentTCB->xStateListItem));
    			}
    			/* 唤醒时间大于当前节拍说明没有溢出 */
    			else
    			{
    				/* 将当前任务挂接到延时列表 */
    				vListInsert(pxDelayedTaskList, &(pxCurrentTCB->xStateListItem));
    
    				/* 当前任务唤醒时间,小于原先下一个解除阻塞任务的唤醒时间 */
    				if(xTimeToWake < xNextTaskUnblockTime)
    				{
    					/* 更新当前任务唤醒时间为下一个解除阻塞任务的唤醒时间 */
    					xNextTaskUnblockTime = xTimeToWake;
    				}
    				else
    				{
    					mtCOVERAGE_TEST_MARKER();
    				}
    			}
    		}
    	}
    	#else
    	{
    		xTimeToWake = xConstTickCount + xTicksToWait;
    
    		listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
    
    		if( xTimeToWake < xConstTickCount )
    		{
    			vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
    		}
    		else
    		{
    			vListInsert(pxDelayedTaskList, &(pxCurrentTCB->xStateListItem));
    
    			if(xTimeToWake < xNextTaskUnblockTime)
    			{
    				xNextTaskUnblockTime = xTimeToWake;
    			}
    			else
    			{
    				mtCOVERAGE_TEST_MARKER();
    			}
    		}
    
    		(void)xCanBlockIndefinitely;
    	}
    	#endif
    }

     

     

    当前系统节拍到达最近的唤醒时间时,系统会将应该唤醒的任务从延时列表中清除,并挂接到就绪列表中。

    /* 系统节拍加一 */
    BaseType_t xTaskIncrementTick(void)
    {
    	TCB_t *pxTCB;
    	TickType_t xItemValue;
    	BaseType_t xSwitchRequired = pdFALSE;
    
    	traceTASK_INCREMENT_TICK(xTickCount);
    	
    	/* 调度器没有被挂起 */
    	if(uxSchedulerSuspended == (UBaseType_t)pdFALSE)
    	{
    		/* 系统节拍计数器加一 */
    		const TickType_t xConstTickCount = xTickCount + (TickType_t)1;
    		xTickCount = xConstTickCount;
    
    		/* 系统节拍溢出 */
    		if(xConstTickCount == (TickType_t)0U)
    		{
    			/* 切换延时列表,更新下一次解除阻塞的时间 */
    			taskSWITCH_DELAYED_LISTS();
    		}
    		else
    		{
    			mtCOVERAGE_TEST_MARKER();
    		}
    
    		/* 处理延时列表中超时的任务 */
    		if(xConstTickCount >= xNextTaskUnblockTime)
    		{
    			for(;;)
    			{
    				/* 如果延时列表已经为空,则将下一次解除时间设为最大 */
    				if(listLIST_IS_EMPTY(pxDelayedTaskList) != pdFALSE)
    				{
    					xNextTaskUnblockTime = portMAX_DELAY;
    					break;
    				}
    				/* 延时列表不是空的 */
    				else
    				{
    					/* 获取延时列表中需要最先解除的任务 */
    					pxTCB = listGET_OWNER_OF_HEAD_ENTRY(pxDelayedTaskList);
    					xItemValue = listGET_LIST_ITEM_VALUE(&(pxTCB->xStateListItem));
    
    					/* 最先需要解除的任务都没有超时 */
    					if(xConstTickCount < xItemValue)
    					{
    						/* 更新下一次解除时间 */
    						xNextTaskUnblockTime = xItemValue;
    						break;
    					}
    					else
    					{
    						mtCOVERAGE_TEST_MARKER();
    					}
    
    					/* 将超时任务从延时列表中移除 */
    					(void)uxListRemove(&(pxTCB->xStateListItem));
    
    					/* 如果该任务被挂接到某个事件列表,还需要从事件列表中移除 */
    					if(listLIST_ITEM_CONTAINER(&(pxTCB->xEventListItem)) != NULL)
    					{
    						(void)uxListRemove(&(pxTCB->xEventListItem));
    					}
    					else
    					{
    						mtCOVERAGE_TEST_MARKER();
    					}
    
    					/* 将任务加入就绪列表中 */
    					prvAddTaskToReadyList(pxTCB);
    
    					......
    				}
    			}
    		}
    
    		......
    	}
    	/* 调度器被挂起 */
    	else
    	{
    		......
    	}
    
    	......
    
    	return xSwitchRequired;
    }

    一旦系统节拍出现溢出,系统会对延时列表和溢出延时列表进行切换。由于系统节拍溢出,原来溢出延时列表变成了延时列表,而原来的延时列表里的任务在系统节拍溢出之后肯定已经全部被超时唤醒,之后这条原先的延时列表则被拿来作为溢出延时列表。

    /* 切换延时列表 */
    #define taskSWITCH_DELAYED_LISTS()																	\
    {																									\
    	List_t *pxTemp;																					\
    																									\
    	configASSERT((listLIST_IS_EMPTY(pxDelayedTaskList)));		/* 延时列表必须为空 */	\
    																													\
    	/* 交换延时列表和溢出延时列表 */																			\
    	pxTemp = pxDelayedTaskList;													\
    	pxDelayedTaskList = pxOverflowDelayedTaskList;													\
    	pxOverflowDelayedTaskList = pxTemp;																\
    																													\
    	xNumOfOverflows++;						/* 系统节拍溢出次数加一 */							\
    	prvResetNextTaskUnblockTime();	/* 更新下一个要解除阻塞的时间 */						\
    }

     

    展开全文
  • 系统任务4.1 显示任务4.1.1 display和write任务4.1.2 strobe监控4.1.3 连续监控4.2 文件I/O任务函数4.2.1 打开文件和关闭文件4.2.2 文件输出4.2.3 数据转换为字符串4.2.4 读取文件内容4.2.5 文件I/O错误状态4.2.6 ...
  • 任务创建函数OSTaskCreate解析

    万次阅读 2012-12-31 11:31:23
    任务创建函数有两种,一种是基本的创建函数OSTaskCreate,另一种是扩展的任务创建函数OSTaskCreateExt。两个函数都实现了任务的创建,但是OSTaskCreateExt的功能更强,带有很多附加的功能,如果不需要附加功能,...
  • ucos 任务延时函数

    千次阅读 2017-01-09 15:41:17
    在ucos里,系统也提供了这样的延时函数,一个是大众版本OSTimeDly(),一个是精致版本的...这两个函数有着非常重要的作用,就是当你调用这两个函数的时候,ucos会进行一次任务调度,所以CPU能在各任务间进
  • verilog中的任务函数

    千次阅读 2019-05-01 15:30:21
    目录 ...3.系统函数和系统任务 3.1显示任务 3.1.1显示和写任务(display and write) 3.1.2选通任务strobe 3.1.3 监控任务monitor 3.2文件输入输出任务 3.2.1文件的打开和关闭 3.2.2输出到...
  • 任务——损失函数

    万次阅读 2018-08-02 22:41:21
    《Multi-Task Learning Using ...创新点:之前的损失函数是根据不同任务的权重参数计算得来,这些权重的设置是困难的,而且需要花费大量时间和精力去进行验证,在实践中多任务学习望而却步。作者提出了一种考虑hom...
  • UCOS-II任务堆栈初始化函数移植

    千次阅读 2013-08-03 18:41:53
    http://blog.sina.com.cn/s/blog_6d589a300100nc3n.html### (2010-10-20 16:34:40) 转载▼ ...UCOS-II的在建立任务函数中要对新建任务的堆栈进行初始化。堆栈初始化函数原型是: OS_STK *OSTaskStkInit (vo
  • FreeRTOS之任务挂起和恢复函数

    千次阅读 2017-10-10 17:23:54
    1.任务挂起和恢复相关的函数如下 vTaskSuspend():挂起一个任务 vTaskResume():恢复一个任务的运行 vTaskResumeFromISR():中断服务函数中恢复一个任务的运行2.函数的详细描述 (1)函数vTaskSuspend() 该函数...
  • Verilog HDL的任务函数

    千次阅读 2009-09-11 15:35:00
    Technorati 标签: FPGA,CPLD,Verilog HDL 任务函数只能实现组合逻辑,而对时序逻辑无能为力。 一、任务 任务就是一段封装在“task…endtask”之间的程序。任务可以彼此调用,而且任务内还可以调用函数。 1、任务...
  • uCOS-II任务之延时函数

    千次阅读 2016-12-08 10:31:18
    uCOS-II任务延时函数 编写过单片机程序的都知道,延时函数是经常被用到的。 在uCOS-II里,系统也提供了这样的延时函数。一个是大众版的OSTimeDly(),一个是精致版的OSTimeDlyHMSM()。 萝卜青菜,各有所爱,随你...
  • //例:使用成员函数、友元函数和一般函数的区别 #include using namespace std; class Time {public: Time(int h,int m,ints):hour(h),minute(m),sec(s){} void display1(); //成员函数声明 friend voiddisplay2...
  • FreeRTOS系列第12篇---FreeRTOS任务应用函数

    万次阅读 多人点赞 2016-01-11 17:15:59
    任务应用函数是一组辅助类函数,一般用于调试信息输出、获取任务句柄、获取任务状态、操作任务标签值等等。1.获取任务系统状态1.1函数描述 UBaseType_t uxTaskGetSystemState( TaskStatus_t * ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 993,242
精华内容 397,296
关键字:

任务函数