打印

理解STM32H7的MDMA的循环列表模式

[复制链接]
225|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
张さん|  楼主 | 2018-8-5 08:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
关于这个循环里面模式,要特别注意一点

他不是从节点0开始循环的,是从节点1开始循环的,如节点1,节点2,节点3组成一个循环

而节点0是初始配置,在用户调用了HAL_MDMA_Start_IT后仅执行一次。




/**
  * @brief  Connect a node to the linked list.
  * @param  hmdma    : Pointer to a MDMA_HandleTypeDef structure that contains
  *                    the configuration information for the specified MDMA Channel.
  * @param  pNewNode : Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node
  *                    to be add to the list.
  * @param pPrevNode : Pointer to the new node position in the linked list or zero to insert the new node
  *                    at the end of the list
  *
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_MDMA_LinkedList_AddNode(MDMA_HandleTypeDef *hmdma, MDMA_LinkNodeTypeDef *pNewNode, MDMA_LinkNodeTypeDef *pPrevNode)
{
  MDMA_LinkNodeTypeDef *pNode = 0;
  uint32_t counter = 0, nodeInserted = 0;
  HAL_StatusTypeDef hal_status = HAL_OK;  
  
  /* Check the MDMA peripheral handle */
  if((hmdma == NULL) || (pNewNode == NULL))
  {
    return HAL_ERROR;
  }  
  
  /* Process locked */
  __HAL_LOCK(hmdma);
  
  if(HAL_MDMA_STATE_READY == hmdma->State)
  {
    /* Change MDMA peripheral state */
    hmdma->State = HAL_MDMA_STATE_BUSY;
   
    /* Check if this is the first node (after the Inititlization node) */
    if((uint32_t)hmdma->FirstLinkedListNodeAddress == 0)
    {
      if(pPrevNode == NULL)
      {
        /* if this is the first node after the initialization  
        connect this node to the node 0 by updating
        the MDMA channel CLAR register to this node address */
        hmdma->Instance->CLAR = (uint32_t)pNewNode;
        /* Set the MDMA handle First linked List node*/
        hmdma->FirstLinkedListNodeAddress = pNewNode;
        
        /*reset New node link */
        pNewNode->CLAR = 0;
        
        /* Update the Handle last node address */      
        hmdma->LastLinkedListNodeAddress = pNewNode;
        
        hmdma->LinkedListNodeCounter = 1;
      }
      else
      {
        hal_status = HAL_ERROR;
      }
    }
    else if(hmdma->FirstLinkedListNodeAddress != pNewNode)  
    {
      /* Check if the node to insert already exists*/        
      pNode = hmdma->FirstLinkedListNodeAddress;
      while((counter < hmdma->LinkedListNodeCounter) && (hal_status == HAL_OK))
      {
        if(pNode->CLAR == (uint32_t)pNewNode)
        {
          hal_status = HAL_ERROR; /* error this node already exist in the linked list and it is not first node */
        }
        pNode = (MDMA_LinkNodeTypeDef *)pNode->CLAR;
        counter++;
      }
      
      if(hal_status == HAL_OK)
      {
        /* Check if the previous node is the last one in the current list or zero */     
        if((pPrevNode == hmdma->LastLinkedListNodeAddress) || (pPrevNode == 0))
        {
          /* insert the new node at the end of the list. */
          pNewNode->CLAR = hmdma->LastLinkedListNodeAddress->CLAR;            
          hmdma->LastLinkedListNodeAddress->CLAR = (uint32_t)pNewNode;
          /* Update the Handle last node address */
          hmdma->LastLinkedListNodeAddress = pNewNode;
          /* Increment the linked list node counter */
          hmdma->LinkedListNodeCounter++;
        }
        else
        {
          /*insert the new node after the pPreviousNode node */
          pNode = hmdma->FirstLinkedListNodeAddress;
          counter = 0;
          while((counter < hmdma->LinkedListNodeCounter) && (nodeInserted == 0))
          {
            counter++;
            if(pNode == pPrevNode)
            {
              /*Insert the new node after the previous one */
              pNewNode->CLAR = pNode->CLAR;
              pNode->CLAR = (uint32_t)pNewNode;
              /* Increment the linked list node counter */
              hmdma->LinkedListNodeCounter++;
              nodeInserted = 1;
            }
            else
            {
              pNode = (MDMA_LinkNodeTypeDef *)pNode->CLAR;
            }
          }
         
          if(nodeInserted == 0)
          {
            hal_status = HAL_ERROR;
          }
        }
      }      
    }
    else
    {
      hal_status = HAL_ERROR;     
    }
   
    /* Process unlocked */
    __HAL_UNLOCK(hmdma);
   
    hmdma->State = HAL_MDMA_STATE_READY;
   
    return hal_status;
  }
  else
  {
    /* Process unlocked */
    __HAL_UNLOCK(hmdma);
   
    /* Return error status */
    return HAL_BUSY;
  }
}
复制代码


/**
  * @brief  Make the linked list circular by connecting the last node to the first.
  * @param  hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
  *                 the configuration information for the specified MDMA Channel.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_MDMA_LinkedList_EnableCircularMode(MDMA_HandleTypeDef *hmdma)
{
  HAL_StatusTypeDef hal_status = HAL_OK;  
  
  /* Check the MDMA peripheral handle */
  if(hmdma == NULL)
  {
    return HAL_ERROR;
  }  
  
  /* Process locked */
  __HAL_LOCK(hmdma);
  
  if(HAL_MDMA_STATE_READY == hmdma->State)
  {
    /* Change MDMA peripheral state */
    hmdma->State = HAL_MDMA_STATE_BUSY;

    /* If first and last node are null (no nodes in the list) : return error*/
    if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0) || (hmdma->LinkedListNodeCounter == 0))
    {
      hal_status = HAL_ERROR;
    }
    else
    {
      /* to enable circular mode Last Node should be connected to first node */
      hmdma->LastLinkedListNodeAddress->CLAR = (uint32_t)hmdma->FirstLinkedListNodeAddress;
    }
   
  }
  /* Process unlocked */
  __HAL_UNLOCK(hmdma);
  
  hmdma->State = HAL_MDMA_STATE_READY;
  
  return hal_status;  
}复制代码

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

448

主题

464

帖子

1

粉丝