硬汉嵌入式论坛

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

[FreeRTOS] Freertos 下的__HAL_LOCK(stm32)问题

[复制链接]

1

主题

1

回帖

4

积分

新手上路

积分
4
发表于 2019-7-19 10:19:29 | 显示全部楼层 |阅读模式
最近发现一个问题,stm32 的HAL库中有__HAL_LOCK和__HAL_UNLOCK
在串口发送和接受函数中都存在,但是这样一来,串口就无法全双工了
#define __HAL_LOCK(__HANDLE__)                                           \
                                do{                                        \
                                    if((__HANDLE__)->Lock == HAL_LOCKED)   \
                                    {                                      \
                                       return HAL_BUSY;                    \
                                    }                                      \
                                    else                                   \
                                    {                                      \
                                       (__HANDLE__)->Lock = HAL_LOCKED;    \
                                    }                                      \
                                  }while (0U)

  #define __HAL_UNLOCK(__HANDLE__)                                          \
                                  do{                                       \
                                      (__HANDLE__)->Lock = HAL_UNLOCKED;    \
                                    }while (0U)

而在LWIP应用中,也有这样的问题,
low_level_output函数调用
HAL_StatusTypeDef HAL_ETH_TransmitFrame(ETH_HandleTypeDef *heth, uint32_t FrameLength)
{
  uint32_t bufcount = 0, size = 0, i = 0;

  /* Process Locked */
  __HAL_LOCK(heth);

这样的话,因为接受数据是在单独的线程中,如果要发送的时候正在接受,那么是不是意味着发送就莫名其妙的失败了,而且不是tcp的话,还不能重发
回复

使用道具 举报

23

主题

1403

回帖

1472

积分

至尊会员

积分
1472
发表于 2019-7-19 11:14:55 | 显示全部楼层
HAL库的锁机制不支持RTOS,而且不支持嵌套,是在接收的时候直接将其又开锁了。

我分析是这样,楼主看看对不对,以lwip为例
发送:
low_level_output ->HAL_ETH_TransmitFrame

接收接收中断:
HAL_ETH_IRQHandler -> 中断函数里面接收完成回调发送信号量 -> 中断函数结束时直接开锁了->等待信号量函数ethernetif_input ->low_level_input ->low_level_input->HAL_ETH_GetReceivedFrame_IT


由于接收在中断里面强行开启了锁,所以就不存在你说的发送时加上了锁后对接收的影响。




代码不规范,亲人两行泪!
回复

使用道具 举报

1

主题

1

回帖

4

积分

新手上路

积分
4
 楼主| 发表于 2019-7-19 11:46:04 | 显示全部楼层
missfox 发表于 2019-7-19 11:14
HAL库的锁机制不支持RTOS,而且不支持嵌套,是在接收的时候直接将其又开锁了。

我分析是这样,楼主看看 ...

还是会存在影响的,接受是在单独的进程里面的
osThreadDef(EthIf, ethernetif_input, osPriorityRealtime, 0, INTERFACE_THREAD_STACK_SIZE);
osThreadCreate (osThread(EthIf), netif);

所以在其他进程里面发送数据,那么HAL_LOCK有被同时调用的风险(并发风险),但接受在一个while函数里面,所以影响不大
for( ;; )
  {
    if (osSemaphoreWait( s_xSemaphore, TIME_WAITING_FOR_INPUT)==osOK)
    {
      do
      {   
        p = low_level_input( netif );
        if   (p != NULL)
        {
          if (netif->input( p, netif) != ERR_OK )
          {
            pbuf_free(p);
          }
        }
      } while(p!=NULL);
    }
  }

但发送就可能受到影响
回复

使用道具 举报

23

主题

1403

回帖

1472

积分

至尊会员

积分
1472
发表于 2019-7-19 12:05:45 | 显示全部楼层
寒号鸟 发表于 2019-7-19 11:46
还是会存在影响的,接受是在单独的进程里面的
osThreadDef(EthIf, ethernetif_input, osPriorityRealti ...

这个处理办法就简单很多了,提升接收任务的优先级可解决。

接收任务的优先级高,就不会存在发送被影响的情况。
代码不规范,亲人两行泪!
回复

使用道具 举报

1

主题

4

回帖

7

积分

新手上路

积分
7
发表于 2019-7-19 14:37:28 | 显示全部楼层
理解了,谢谢
回复

使用道具 举报

1

主题

4

回帖

7

积分

新手上路

积分
7
发表于 2019-7-19 14:37:59 | 显示全部楼层
missfox 发表于 2019-7-19 12:05
这个处理办法就简单很多了,提升接收任务的优先级可解决。

接收任务的优先级高,就不会存在发送被影响 ...

理解了,谢谢
回复

使用道具 举报

1

主题

4

回帖

7

积分

新手上路

积分
7
发表于 2019-7-20 10:09:20 | 显示全部楼层
missfox 发表于 2019-7-19 12:05
这个处理办法就简单很多了,提升接收任务的优先级可解决。

接收任务的优先级高,就不会存在发送被影响 ...

我今天思考了一下,发现还是会存在一种情况,您看我的想法是否合理

如果正在发送中(__HAL_locked已经加锁),突然来了一个接受中断(中断里面),
void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
{
  osSemaphoreRelease(s_xSemaphore);
}
然后接受函数被运行(接受函数的优先级高)
void ethernetif_input( void const * argument )
{
   。。。。。
    if (osSemaphoreWait( s_xSemaphore, TIME_WAITING_FOR_INPUT)==osOK)
    {
      do
      {
        p = low_level_input( netif );
        if (p != NULL)
        {
          if (netif->input( p, netif) != ERR_OK )
          {
            pbuf_free(p);
          }
        }
      }while(p!=NULL);
    }
  }
}
但是这个时候,注意发送函数正在发送(__HAL_LOCKD已经刚刚被发送加锁了),所以low_level_input肯定返回NULL(因为HAL_ETH_GetReceivedFrame_IT的HAL_LOCK返回busy,自然该函数会返回NULL),这样一来本次接收不就失败了嘛,本次的包就没有了
回复

使用道具 举报

23

主题

1403

回帖

1472

积分

至尊会员

积分
1472
发表于 2019-7-20 10:12:25 | 显示全部楼层
寒号鸟_SyD58 发表于 2019-7-20 10:09
我今天思考了一下,发现还是会存在一种情况,您看我的想法是否合理

如果正在发送中(__HAL_locked已经 ...

二楼已经回复你这种情况,在ETH中断接收处理函数里面已经开锁了。看下中断函数就明白了
代码不规范,亲人两行泪!
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-28 08:24 , Processed in 0.165628 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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