__HAL_LOCK()这个函数有什么用?
比如串口,串口类型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生成的工程)。
#define __HAL_LOCK(__HANDLE__) \
do{ \
if((__HANDLE__)->Lock == HAL_LOCKED) \
{ \
return HAL_BUSY; \
} \
else \
{ \
(__HANDLE__)->Lock = HAL_LOCKED; \
} \
}while (0)
#define __HAL_UNLOCK(__HANDLE__) \
do{ \
(__HANDLE__)->Lock = HAL_UNLOCKED; \
}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请求。
HAL_StatusTypeDef HAL_DMA_Start(...)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check the parameters */
assert_param(IS_DMA_BUFFER_SIZE(DataLength));
/* Process locked */
__HAL_LOCK(hdma);
...
}
调用HAL_DMA_Start会在函数的开头调用__HAL_LOCK,假如DMA已经被开启了,那么这条语句将立即返回HAL_BUSY,否则标记DMA为加锁状态,并继续下面的代码。
HAL_StatusTypeDef HAL_DMA_PollForTransfer(...)
{
...
if(HAL_DMA_STATE_BUSY != hdma->State)
{
/* No transfer ongoing */
hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
__HAL_UNLOCK(hdma);
return HAL_ERROR;
}
...
while(((tmpisr & mask_cpltlevel) == RESET) && ((hdma->ErrorCode & HAL_DMA_ERROR_TE) == RESET))
{
/* Check for the Timeout (Not applicable in circular mode)*/
if(Timeout != HAL_MAX_DELAY)
{
if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
{
/* Update error code */
hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
/* Process Unlocked */
__HAL_UNLOCK(hdma);
/* Change the DMA state */
hdma->State = HAL_DMA_STATE_READY;
return HAL_TIMEOUT;
}
}
...
}
if(hdma->ErrorCode != HAL_DMA_ERROR_NONE)
{
if((hdma->ErrorCode & HAL_DMA_ERROR_TE) != RESET)
{
HAL_DMA_Abort(hdma);
/* Clear the half transfer and transfer complete flags */
regs->IFCR = (DMA_FLAG_HTIF0_4 | DMA_FLAG_TCIF0_4) << hdma->StreamIndex;
/* Process Unlocked */
__HAL_UNLOCK(hdma);
/* Change the DMA state */
hdma->State= HAL_DMA_STATE_READY;
return HAL_ERROR;
}
}
/* Get the level transfer complete flag */
if(CompleteLevel == HAL_DMA_FULL_TRANSFER)
{
/* Clear the half transfer and transfer complete flags */
regs->IFCR = (DMA_FLAG_HTIF0_4 | DMA_FLAG_TCIF0_4) << hdma->StreamIndex;
/* Process Unlocked */
__HAL_UNLOCK(hdma);
hdma->State = HAL_DMA_STATE_READY;
}
else
{
/* Clear the half transfer and transfer complete flags */
regs->IFCR = (DMA_FLAG_HTIF0_4) << hdma->StreamIndex;
}
return status;
}
HAL_DMA_PollForTransfer会根据当前的DMA状态在适当的时机调用__HAL_UNLOCK解锁。 有用的,不知道你用过F0系列没有,F0的HAL库里面调用更新时间函数后时间不更新,就是由于这个锁,我开始还以为是硬件问题呢。应该和RTOS里面的互斥量差不多吧 之所以这么问,是之前看到creep大神给的DMA+空闲中断里的空闲回调函数里有个
__HAL_UNLOCK(huart->hdmarx);
之前一直不明白为什么这里有个UNLOCK,而没有找到对应的LOCK。今天修改这部分时,没有加这句,结果接收数组一直是第一次接收的数据。现在想想,应该是后来DMA就没有再使能。
但我没找到根据Lock位做判断的地方。 估计是一个标志位?停止没完成当前的工作,然后又重复操作? 是一个什么的锁来着吧 本帖最后由 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;则直接退出上级函数了。感谢指教。
页:
[1]