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

__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位做判断的地方。
ts2000 回答时间: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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版