嵌入式软件异步编程:同步转为异步

来源:互联网 发布:java成员变量是什么 编辑:程序博客网 时间:2024/05/17 01:50

在现有同步实现的基础上进行异步实现,需要将同步代码转换成异步代码。

http://blog.csdn.net/zoomdy/article/details/64125084
mingdu.zheng at gmail dot com

基本方法:分开请求和结果

I/O的基本操作可以细分为两个部分:

  1. 发起请求
  2. 检查结果

同步编程模型中,这两部分是在一个函数中的,在没有操作系统的情况下,检查结果部分可能是一个繁忙等待式的轮询,在有操作系统的情况下,检查结果部分可能首先是一个等待信号量的操作,该操作会将线程挂起直到得到I/O的通知。要将同步编程转换成异步编程就要将这两个基本部分分开,若采用轮询式异步编程,只要系统空闲就会调用检查结果部分,若采用回调式异步编程,检查结果部分则可以作为回调函数。

以轮询异步串口发送为例

同步发送

HAL_StatusTypeDef syncUART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size){  huart->TxXferCount = Size;  while (huart->TxXferCount > 0U)  {    huart->TxXferCount--;    huart->Instance->TDR = *pData++;    while(__HAL_UART_GET_FLAG(huart, UART_FLAG_TXE) == RESET){}  }  return HAL_OK;}

异步发送

异步发送将syncUART_Transmit分割为两个函数:asyncUART_Transmit和asyncUART_Process。asyncUART_Transmit是I/O请求发起函数,asyncUART_Process检查I/O请求的完成情况。asyncUART_Transmit函数在需要发送数据时调用一次,而asyncUART_Process则需要在主函数循环中不断地调用以检查I/O完成请求。

发起请求

  • asyncUART_Transmit发起I/O请求成功后立即返回,并不会等待I/O完成。
HAL_StatusTypeDef asyncUART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size){  if(huart->gState != HAL_UART_STATE_READY)  {    return HAL_BUSY;  }  huart->TxXferCount = Size;  huart->pTxBuffPtr = pData;  if (huart->TxXferCount > 0U)  {    huart->TxXferCount--;    huart->Instance->TDR = *huart->pTxBuffPtr++;    huart->gState = HAL_UART_STATE_BUSY_TX;  }  return HAL_OK;}

检查结果

  • asyncUART_Process检查I/O的完成情况,如果I/O未完成,那么立即退出,等下一次主循环再次调用。
  • 这个例子在检查到上一个I/O请求已经完成的情况下会发起下一个I/O请求。
  • asyncUART_Process使用了状态机,因为asyncUART_Process不停地被调用,需要根据外设的状态执行不同的检查或者什么都不做。
void asyncUART_Process(UART_HandleTypeDef *huart){  switch(huart->gState)  {  case HAL_UART_STATE_BUSY_TX:    if(__HAL_UART_GET_FLAG(huart, UART_FLAG_TXE) == SET)    {      if (huart->TxXferCount > 0U)      {        huart->TxXferCount--;        huart->Instance->TDR = *huart->pTxBuffPtr++;      }      else      {        huart->gState = HAL_UART_STATE_READY;      }    }    break;  default:    break;  }}
0 0
原创粉丝点击