硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1716|回复: 12
收起左侧

[FreeRTOS] FreeRTOS工程中,低优先级的任务反而先于高优先级任务执行

[复制链接]

3

主题

35

回帖

44

积分

新手上路

积分
44
发表于 2021-12-17 18:44:22 | 显示全部楼层 |阅读模式
然后我在在高优先级的任务中 释放信号量,低优先级任务接收
高优先级任务反而不执行了,而是反复的进入低优先级任务的(有正确的延时函数)
请问原因可能出现在哪里
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106738
QQ
发表于 2021-12-18 00:28:48 | 显示全部楼层
方便的话,发代码看看。
回复

使用道具 举报

3

主题

35

回帖

44

积分

新手上路

积分
44
 楼主| 发表于 2021-12-20 10:37:45 | 显示全部楼层
freeRtos.c中的任务配置如下
osThreadId_t Rs485SysHandle;
const osThreadAttr_t Rs485Sys_attributes = {
  .name = "Rs485Sys",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) (osPriorityAboveNormal-10),
};
osThreadId_t mbSysMasterHandle
const osThreadAttr_t mbSysMaster_attributes = {
  .name = "mbSysMaster",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityAboveNormal,
};

osSemaphoreId_t MasterSem = NULL;

Rs485SysHandle = osThreadNew(Rs485SysTask, NULL,&Rs485Sys_attributes);

mbSysMasterHandle == osThreadNew(MBSysMasterTask, NULL, &mbSysMaster_attributes);

MasterSem =xSemaphoreCreateBinary();

应用代码如下
void Rs485SysTask(void *argument)
{
        BaseType_t xResult;

       while(1)
      {
          xResult = xSemaphoreTake(MasterSem,10);
          if(xResult == pdPASS)
         {
              SysPoll(); //Modbus数据打包
         }
         osDelay(100);
}
   
void MBSysMasterTask(void *argument)
{
     eMBMasterInit(MB_RTU, SYS_UART, 9600, MB_PAR_NONE);
     eMBMasterEnable();

    while(1)
   {
       xSemaphoreGive(MasterSem);
      eMBMasterPoll();
      osDelay(1);
   }

}
回复

使用道具 举报

334

主题

2032

回帖

3039

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3039
发表于 2021-12-20 11:05:37 | 显示全部楼层
24841500 发表于 2021-12-20 10:37
freeRtos.c中的任务配置如下
osThreadId_t Rs485SysHandle;
const osThreadAttr_t Rs485Sys_attributes = ...

由于高级任务的osdelay只有1毫秒,可能是高级任务的执行频率太高,你没有监控到。你可以把高级任务的osdelay变成10毫秒或更多一点。

另外,你这个设计思想有点悖论。
高级任务释放的信号量太快太多了。给出了一个信号量,低级任务来不及处理,肯定会丢失大量的信号量。
低级任务中,不用加osdlay(100),应该把这个100毫秒放到take信号量的等待时间中去,就是xSemaphoreTake(MasterSem,100);
回复

使用道具 举报

3

主题

35

回帖

44

积分

新手上路

积分
44
 楼主| 发表于 2021-12-20 11:49:46 | 显示全部楼层
caicaptain2 发表于 2021-12-20 11:05
由于高级任务的osdelay只有1毫秒,可能是高级任务的执行频率太高,你没有监控到。你可以把高级任务的osde ...

我的2个任务是组合任务,
思路是 A任务的数据打包一旦完成,B任务立刻开始发送
信号量是二值信号量,上限为1
程序开始执行后,串口没有数据发送,高级任务未被监控到的可能性是不存在的
另外我按照你的说法尝试后,取消低级任务的OSdelay,在take信号量的等待时间中 加以改变没有效果
take时间10到MAX没有区别,执行程序卡在take中,而高级任务不再执行导致低级任务监测不到信号量
回复

使用道具 举报

334

主题

2032

回帖

3039

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3039
发表于 2021-12-20 12:25:00 | 显示全部楼层
24841500 发表于 2021-12-20 11:49
我的2个任务是组合任务,
思路是 A任务的数据打包一旦完成,B任务立刻开始发送
信号量是二值信号量,上 ...

那这个现象确实很奇怪。
我怀疑是信号量的问题。你可以试试这个函数创建信号量:xSemaphoreCreateBinaryStatic()

参考的这个说明:
* If a binary semaphore
* is created using xSemaphoreCreateBinary() then the required memory is
* automatically dynamically allocated inside the xSemaphoreCreateBinary()
* function.  (see http://www.freertos.org/a00111.html).  If a binary semaphore
* is created using xSemaphoreCreateBinaryStatic() then the application writer
* must provide the memory.  xSemaphoreCreateBinaryStatic() therefore allows a
* binary semaphore to be created without using any dynamic memory allocation.
回复

使用道具 举报

334

主题

2032

回帖

3039

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3039
发表于 2021-12-20 12:31:54 | 显示全部楼层
本帖最后由 caicaptain2 于 2021-12-20 12:33 编辑
24841500 发表于 2021-12-20 11:49
我的2个任务是组合任务,
思路是 A任务的数据打包一旦完成,B任务立刻开始发送
信号量是二值信号量,上 ...

还发现一个异常的地方:osSemaphoreId_t 是个无类型的指针。
但是,在rtos的说明中,信号量是一个结构体。
例子是:
SemaphoreHandle_t xSemaphore = NULL;
xSemaphore = xSemaphoreCreateBinary();

结构体跟踪后,typedef QueueHandle_t SemaphoreHandle_t;
typedef struct QueueDefinition * QueueHandle_t;

它定义如下:
typedef struct QueueDefinition                 /* The old naming convention is used to prevent breaking kernel aware debuggers. */
{
        int8_t *pcHead;                                        /*< Points to the beginning of the queue storage area. */
        int8_t *pcWriteTo;                                /*< Points to the free next place in the storage area. */

        union
        {
                QueuePointers_t xQueue;                /*< Data required exclusively when this structure is used as a queue. */
                SemaphoreData_t xSemaphore; /*< Data required exclusively when this structure is used as a semaphore. */
        } u;

        List_t xTasksWaitingToSend;                /*< List of tasks that are blocked waiting to post onto this queue.  Stored in priority order. */
        List_t xTasksWaitingToReceive;        /*< List of tasks that are blocked waiting to read from this queue.  Stored in priority order. */

        volatile UBaseType_t uxMessagesWaiting;/*< The number of items currently in the queue. */
        UBaseType_t uxLength;                        /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
        UBaseType_t uxItemSize;                        /*< The size of each items that the queue will hold. */

        volatile int8_t cRxLock;                /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */
        volatile int8_t cTxLock;                /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */

        #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
                uint8_t ucStaticallyAllocated;        /*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */
        #endif

        #if ( configUSE_QUEUE_SETS == 1 )
                struct QueueDefinition *pxQueueSetContainer;
        #endif

        #if ( configUSE_TRACE_FACILITY == 1 )
                UBaseType_t uxQueueNumber;
                uint8_t ucQueueType;
        #endif

}

回复

使用道具 举报

3

主题

35

回帖

44

积分

新手上路

积分
44
 楼主| 发表于 2021-12-20 13:51:05 | 显示全部楼层
caicaptain2 发表于 2021-12-20 12:25
那这个现象确实很奇怪。
我怀疑是信号量的问题。你可以试试这个函数创建信号量:xSemaphoreCreateBinary ...

我试过这个方法,没有效果
用cubeM生成一个信号量后,仍然是同样的现象
高级任务只执行一次,低级任务反复执行,卡在信号量的take中,高级任务不再执行
而且低级任务先于高级任务执行,症结应该在这里
但为什么有这种现象,想不明白
回复

使用道具 举报

3

主题

35

回帖

44

积分

新手上路

积分
44
 楼主| 发表于 2021-12-20 14:00:12 | 显示全部楼层
caicaptain2 发表于 2021-12-20 12:25
那这个现象确实很奇怪。
我怀疑是信号量的问题。你可以试试这个函数创建信号量:xSemaphoreCreateBinary ...

当时想着用信号量进行同步的原因,就是因为低优先级任务总是先执行俩次,然后才轮到高优先级任务
结果便是低优先级任务里的  第一次数据打包会被第二次数据打包给顶掉,高级任务还未开始发送便出现了丢包
freeRTOS里,这种低级任务先执行几次的现象 原因到底是什么呢
回复

使用道具 举报

334

主题

2032

回帖

3039

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3039
发表于 2021-12-21 15:35:25 | 显示全部楼层
24841500 发表于 2021-12-20 14:00
当时想着用信号量进行同步的原因,就是因为低优先级任务总是先执行俩次,然后才轮到高优先级任务
结果便 ...

具体的原因也不知道怎么分析下去了。 。。
但是,FreeRTOS已经是十年以上的成熟软件了,如果任务高低优先级都是错误的话,似乎也不可能啊?

建议你避开这个二值信号量的方法。FreeRTOS经过CMSIS封装后,它的注释文件里面都提示用TaskNotify来代替信号量,你可以试试看。
回复

使用道具 举报

0

主题

16

回帖

16

积分

新手上路

积分
16
发表于 2021-12-23 14:15:49 | 显示全部楼层
TaskNotify 占用资源少,稳定,就是使用条件有限制。
回复

使用道具 举报

3

主题

35

回帖

44

积分

新手上路

积分
44
 楼主| 发表于 2021-12-28 10:16:00 | 显示全部楼层
本帖最后由 24841500 于 2021-12-28 17:14 编辑

最终解决了,问题出在freemodbus 主站的移植代码里
portevent_m.c里 涉及freertos的信号量获取释放 导致了 相关任务的优先级出错
回复

使用道具 举报

334

主题

2032

回帖

3039

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3039
发表于 2021-12-29 08:43:32 | 显示全部楼层
24841500 发表于 2021-12-28 10:16
最终解决了,问题出在freemodbus 主站的移植代码里
portevent_m.c里 涉及freertos的信号量获取释放 导致了 ...

感谢分享!
其实各种RTOS在应用函数方便都是差不多的。所以cmsis可以统一很多函数
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-3 05:57 , Processed in 0.329398 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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