你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

__HAL_LOCK()这个函数有什么用?

[复制链接]
any012 提问时间:2017-1-20 15:48 /
悬赏5ST金币已解决
比如串口,串口类型UART_HandleTypeDef的定义有Lock这个变量,其类型是下面这个枚举。
typedef enum
{
  HAL_UNLOCKED = 0x00,
  HAL_LOCKED   = 0x01  
} HAL_LockTypeDef;

串口接收/发送,或者中断模式接收/发送,都是先设置__HAL_LOCK(),然后配置huart,配置完后再__HAL_UNLOCK()。但感觉这个Lock没什么用啊。
接受过程中及中断里都没有涉及到这个变量,也许是我没找到。

最佳答案

查看完整内容

以STM32F4系列为例 __HAL_LOCK和__HAL_UNLOCK定义在Drivers/STM32F4xx_HAL_driver/Inc/stm32f4xx_hal_def.h头文件中(假设是Cube生成的工程)。 通过代码可以看出__HAL_LOCK的作用是判断被操作的__HANDLE__是否已经加锁,如果已经加锁那么返回忙,并立即推出函数,如果未加锁,那么执行加锁。__HAL_UNLOCK则是解锁。 举个DMA操作的例子,调用HAL_DMA_Start启动一次DMA传输,在本次传输结束前不允许开始第二次DMA传输,因此HAL_DM ...
收藏 1 评论6 发布时间:2017-1-20 15:48

举报

6个回答
zoomdy 回答时间:2017-1-20 15:48:55
以STM32F4系列为例
__HAL_LOCK和__HAL_UNLOCK定义在Drivers/STM32F4xx_HAL_driver/Inc/stm32f4xx_hal_def.h头文件中(假设是Cube生成的工程)。
  1.   #define __HAL_LOCK(__HANDLE__)                                           \
  2.                                 do{                                        \
  3.                                     if((__HANDLE__)->Lock == HAL_LOCKED)   \
  4.                                     {                                      \
  5.                                        return HAL_BUSY;                    \
  6.                                     }                                      \
  7.                                     else                                   \
  8.                                     {                                      \
  9.                                        (__HANDLE__)->Lock = HAL_LOCKED;    \
  10.                                     }                                      \
  11.                                   }while (0)

  12.   #define __HAL_UNLOCK(__HANDLE__)                                          \
  13.                                   do{                                       \
  14.                                       (__HANDLE__)->Lock = HAL_UNLOCKED;    \
  15.                                     }while (0)
复制代码

通过代码可以看出__HAL_LOCK的作用是判断被操作的__HANDLE__是否已经加锁,如果已经加锁那么返回忙,并立即推出函数,如果未加锁,那么执行加锁。__HAL_UNLOCK则是解锁。

举个DMA操作的例子,调用HAL_DMA_Start启动一次DMA传输,在本次传输结束前不允许开始第二次DMA传输,因此HAL_DMA_Start操作执行了__HAL_LOCK进行加锁,在解锁前调用HAL_DMA_Start会返回HAL_BUSY而不会执行DMA操作。接下来调用HAL_DMA_PollForTransfer来轮询DMA是否操作完成,一旦HAL_DMA_PollForTransfer函数检测到DMA操作完成或发生错误,那么会调用__HAL_UNLOCK解锁,解锁之后才能进行下一次DMA请求。
  1. HAL_StatusTypeDef HAL_DMA_Start(...)
  2. {
  3.   HAL_StatusTypeDef status = HAL_OK;
  4.   
  5.   /* Check the parameters */
  6.   assert_param(IS_DMA_BUFFER_SIZE(DataLength));

  7.   /* Process locked */
  8.   __HAL_LOCK(hdma);
  9. ...
  10. }
复制代码

调用HAL_DMA_Start会在函数的开头调用__HAL_LOCK,假如DMA已经被开启了,那么这条语句将立即返回HAL_BUSY,否则标记DMA为加锁状态,并继续下面的代码。
  1. HAL_StatusTypeDef HAL_DMA_PollForTransfer(...)
  2. {
  3. ...

  4.   if(HAL_DMA_STATE_BUSY != hdma->State)
  5.   {
  6.     /* No transfer ongoing */
  7.     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
  8.     __HAL_UNLOCK(hdma);
  9.     return HAL_ERROR;
  10.   }

  11. ...
  12.   
  13.   while(((tmpisr & mask_cpltlevel) == RESET) && ((hdma->ErrorCode & HAL_DMA_ERROR_TE) == RESET))
  14.   {
  15.     /* Check for the Timeout (Not applicable in circular mode)*/
  16.     if(Timeout != HAL_MAX_DELAY)
  17.     {
  18.       if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
  19.       {
  20.         /* Update error code */
  21.         hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;

  22.         /* Process Unlocked */
  23.         __HAL_UNLOCK(hdma);
  24.         
  25.         /* Change the DMA state */
  26.         hdma->State = HAL_DMA_STATE_READY;
  27.         
  28.         return HAL_TIMEOUT;
  29.       }
  30.     }

  31. ...
  32.   }
  33.   
  34.   if(hdma->ErrorCode != HAL_DMA_ERROR_NONE)
  35.   {
  36.     if((hdma->ErrorCode & HAL_DMA_ERROR_TE) != RESET)
  37.     {
  38.       HAL_DMA_Abort(hdma);
  39.    
  40.       /* Clear the half transfer and transfer complete flags */
  41.       regs->IFCR = (DMA_FLAG_HTIF0_4 | DMA_FLAG_TCIF0_4) << hdma->StreamIndex;
  42.    
  43.       /* Process Unlocked */
  44.       __HAL_UNLOCK(hdma);

  45.       /* Change the DMA state */
  46.       hdma->State= HAL_DMA_STATE_READY;

  47.       return HAL_ERROR;
  48.    }

  49.   }

  50.   /* Get the level transfer complete flag */
  51.   if(CompleteLevel == HAL_DMA_FULL_TRANSFER)
  52.   {
  53.     /* Clear the half transfer and transfer complete flags */
  54.     regs->IFCR = (DMA_FLAG_HTIF0_4 | DMA_FLAG_TCIF0_4) << hdma->StreamIndex;
  55.    
  56.     /* Process Unlocked */
  57.     __HAL_UNLOCK(hdma);

  58.     hdma->State = HAL_DMA_STATE_READY;
  59.   }
  60.   else
  61.   {
  62.     /* Clear the half transfer and transfer complete flags */
  63.     regs->IFCR = (DMA_FLAG_HTIF0_4) << hdma->StreamIndex;
  64.   }
  65.   
  66.   return status;
  67. }
复制代码

HAL_DMA_PollForTransfer会根据当前的DMA状态在适当的时机调用__HAL_UNLOCK解锁。

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2

查看全部评分

海迹天涯 回答时间:2017-1-20 16:03:34
有用的,不知道你用过F0系列没有,F0的HAL库里面调用更新时间函数后时间不更新,就是由于这个锁,我开始还以为是硬件问题呢。应该和RTOS里面的互斥量差不多吧

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2

查看全部评分

any012 回答时间:2017-1-20 16:23:23
之所以这么问,是之前看到creep大神给的DMA+空闲中断里的空闲回调函数里有个
__HAL_UNLOCK(huart->hdmarx);
之前一直不明白为什么这里有个UNLOCK,而没有找到对应的LOCK。今天修改这部分时,没有加这句,结果接收数组一直是第一次接收的数据。现在想想,应该是后来DMA就没有再使能。
但我没找到根据Lock位做判断的地方。
小小超 回答时间:2017-1-21 08:20:04
估计是一个标志位?停止没完成当前的工作,然后又重复操作?

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2

查看全部评分

队长shiwo 回答时间:2017-1-21 08:51:52
是一个什么的锁来着吧
any012 回答时间:2017-1-21 12:09:51
本帖最后由 any012 于 2017-1-21 12:12 编辑
zoomdy 发表于 2017-1-20 15:48
以STM32F4系列为例
__HAL_LOCK和__HAL_UNLOCK定义在Drivers/STM32F4xx_HAL_driver/Inc/stm32f4xx_hal_def.h ...

能否指明下,__HAL_LOCK()这个函数,在已被锁的情况下被调用后,返回量return HAL_BUSY,这个值,在什么地方被用到?

额,明白了,,__HAL_LOCK()是个宏,如果执行return HAL_BUSY;则直接退出上级函数了。感谢指教。

所属标签

相似问题

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版