硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1438|回复: 0
收起左侧

[DMA] 理解STM32H7的MDMA的循环列表模式

[复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106913
QQ
发表于 2019-7-6 09:58:49 | 显示全部楼层 |阅读模式
关于这个循环里面模式,要特别注意一点

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

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




  1. /**
  2.   * @brief  Connect a node to the linked list.
  3.   * @param  hmdma    : Pointer to a MDMA_HandleTypeDef structure that contains
  4.   *                    the configuration information for the specified MDMA Channel.
  5.   * @param  pNewNode : Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node
  6.   *                    to be add to the list.
  7.   * @param pPrevNode : Pointer to the new node position in the linked list or zero to insert the new node
  8.   *                    at the end of the list
  9.   *
  10.   * @retval HAL status
  11.   */
  12. HAL_StatusTypeDef HAL_MDMA_LinkedList_AddNode(MDMA_HandleTypeDef *hmdma, MDMA_LinkNodeTypeDef *pNewNode, MDMA_LinkNodeTypeDef *pPrevNode)
  13. {
  14.   MDMA_LinkNodeTypeDef *pNode = 0;
  15.   uint32_t counter = 0, nodeInserted = 0;
  16.   HAL_StatusTypeDef hal_status = HAL_OK;  
  17.   
  18.   /* Check the MDMA peripheral handle */
  19.   if((hmdma == NULL) || (pNewNode == NULL))
  20.   {
  21.     return HAL_ERROR;
  22.   }  
  23.   
  24.   /* Process locked */
  25.   __HAL_LOCK(hmdma);
  26.   
  27.   if(HAL_MDMA_STATE_READY == hmdma->State)
  28.   {
  29.     /* Change MDMA peripheral state */
  30.     hmdma->State = HAL_MDMA_STATE_BUSY;
  31.    
  32.     /* Check if this is the first node (after the Inititlization node) */
  33.     if((uint32_t)hmdma->FirstLinkedListNodeAddress == 0)
  34.     {
  35.       if(pPrevNode == NULL)
  36.       {
  37.         /* if this is the first node after the initialization  
  38.         connect this node to the node 0 by updating
  39.         the MDMA channel CLAR register to this node address */
  40.         hmdma->Instance->CLAR = (uint32_t)pNewNode;
  41.         /* Set the MDMA handle First linked List node*/
  42.         hmdma->FirstLinkedListNodeAddress = pNewNode;
  43.         
  44.         /*reset New node link */
  45.         pNewNode->CLAR = 0;
  46.         
  47.         /* Update the Handle last node address */      
  48.         hmdma->LastLinkedListNodeAddress = pNewNode;
  49.         
  50.         hmdma->LinkedListNodeCounter = 1;
  51.       }
  52.       else
  53.       {
  54.         hal_status = HAL_ERROR;
  55.       }
  56.     }
  57.     else if(hmdma->FirstLinkedListNodeAddress != pNewNode)  
  58.     {
  59.       /* Check if the node to insert already exists*/        
  60.       pNode = hmdma->FirstLinkedListNodeAddress;
  61.       while((counter < hmdma->LinkedListNodeCounter) && (hal_status == HAL_OK))
  62.       {
  63.         if(pNode->CLAR == (uint32_t)pNewNode)
  64.         {
  65.           hal_status = HAL_ERROR; /* error this node already exist in the linked list and it is not first node */
  66.         }
  67.         pNode = (MDMA_LinkNodeTypeDef *)pNode->CLAR;
  68.         counter++;
  69.       }
  70.       
  71.       if(hal_status == HAL_OK)
  72.       {
  73.         /* Check if the previous node is the last one in the current list or zero */     
  74.         if((pPrevNode == hmdma->LastLinkedListNodeAddress) || (pPrevNode == 0))
  75.         {
  76.           /* insert the new node at the end of the list. */
  77.           pNewNode->CLAR = hmdma->LastLinkedListNodeAddress->CLAR;            
  78.           hmdma->LastLinkedListNodeAddress->CLAR = (uint32_t)pNewNode;
  79.           /* Update the Handle last node address */
  80.           hmdma->LastLinkedListNodeAddress = pNewNode;
  81.           /* Increment the linked list node counter */
  82.           hmdma->LinkedListNodeCounter++;
  83.         }
  84.         else
  85.         {
  86.           /*insert the new node after the pPreviousNode node */
  87.           pNode = hmdma->FirstLinkedListNodeAddress;
  88.           counter = 0;
  89.           while((counter < hmdma->LinkedListNodeCounter) && (nodeInserted == 0))
  90.           {
  91.             counter++;
  92.             if(pNode == pPrevNode)
  93.             {
  94.               /*Insert the new node after the previous one */
  95.               pNewNode->CLAR = pNode->CLAR;
  96.               pNode->CLAR = (uint32_t)pNewNode;
  97.               /* Increment the linked list node counter */
  98.               hmdma->LinkedListNodeCounter++;
  99.               nodeInserted = 1;
  100.             }
  101.             else
  102.             {
  103.               pNode = (MDMA_LinkNodeTypeDef *)pNode->CLAR;
  104.             }
  105.           }
  106.          
  107.           if(nodeInserted == 0)
  108.           {
  109.             hal_status = HAL_ERROR;
  110.           }
  111.         }
  112.       }      
  113.     }
  114.     else
  115.     {
  116.       hal_status = HAL_ERROR;     
  117.     }
  118.    
  119.     /* Process unlocked */
  120.     __HAL_UNLOCK(hmdma);
  121.    
  122.     hmdma->State = HAL_MDMA_STATE_READY;
  123.    
  124.     return hal_status;
  125.   }
  126.   else
  127.   {
  128.     /* Process unlocked */
  129.     __HAL_UNLOCK(hmdma);
  130.    
  131.     /* Return error status */
  132.     return HAL_BUSY;
  133.   }
  134. }
复制代码



  1. /**
  2.   * @brief  Make the linked list circular by connecting the last node to the first.
  3.   * @param  hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
  4.   *                 the configuration information for the specified MDMA Channel.
  5.   * @retval HAL status
  6.   */
  7. HAL_StatusTypeDef HAL_MDMA_LinkedList_EnableCircularMode(MDMA_HandleTypeDef *hmdma)
  8. {
  9.   HAL_StatusTypeDef hal_status = HAL_OK;  
  10.   
  11.   /* Check the MDMA peripheral handle */
  12.   if(hmdma == NULL)
  13.   {
  14.     return HAL_ERROR;
  15.   }  
  16.   
  17.   /* Process locked */
  18.   __HAL_LOCK(hmdma);
  19.   
  20.   if(HAL_MDMA_STATE_READY == hmdma->State)
  21.   {
  22.     /* Change MDMA peripheral state */
  23.     hmdma->State = HAL_MDMA_STATE_BUSY;

  24.     /* If first and last node are null (no nodes in the list) : return error*/
  25.     if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0) || (hmdma->LinkedListNodeCounter == 0))
  26.     {
  27.       hal_status = HAL_ERROR;
  28.     }
  29.     else
  30.     {
  31.       /* to enable circular mode Last Node should be connected to first node */
  32.       hmdma->LastLinkedListNodeAddress->CLAR = (uint32_t)hmdma->FirstLinkedListNodeAddress;
  33.     }
  34.    
  35.   }
  36.   /* Process unlocked */
  37.   __HAL_UNLOCK(hmdma);
  38.   
  39.   hmdma->State = HAL_MDMA_STATE_READY;
  40.   
  41.   return hal_status;  
  42. }
复制代码

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-10 08:08 , Processed in 0.237464 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表