|

楼主 |
发表于 2018-8-9 16:45:14
|
显示全部楼层
实例2:MDMA_LinkedList

例程说明:
这个例程实现的功能也比较简单,不过最重要的功能是实现MDMA的List模式,这个模式简单的说就是大家可以做多种配置,然后将其做成个列表连接起来,MDMA可以按照相应的配置,依次进行传输。
这个例子配置三个源地址空间和三个目的地址,然后分别配置好,进行传输。
注意事项:
1、配置的节点0是通过函数HAL_MDMA_Init创建,后面增加节点通过函数HAL_MDMA_LinkedList_CreateNode/HAL_MDMA_LinkedList_AddNode
2、节点1和节点2的的结构体定义用的32字节对齐
ALIGN_32BYTES( MDMA_LinkNodeTypeDef Xfer_Node1);
ALIGN_32BYTES( MDMA_LinkNodeTypeDef Xfer_Node2);
3、Cache问题
启动前,节点1和节点2的结构体变量做了Clean操作,保证内容写入到此变量了。
但是MDMA传输完毕后,读取MDMA的目的缓冲区,此例子没有做无效化操作,个人觉得不妥。
配置如下:
- /* Private typedef -----------------------------------------------------------*/
- #define BUFFER_SIZE0 32
- #define BUFFER_SIZE1 16
- #define BUFFER_SIZE2 8
- /* Private define ------------------------------------------------------------*/
- /* Private macro -------------------------------------------------------------*/
- /* Private variables ---------------------------------------------------------*/
- MDMA_HandleTypeDef MDMA_Handle;
- static const uint32_t SRC_Const_Buffer0[BUFFER_SIZE0] =
- {
- 0x01020304, 0x05060708, 0x090A0B0C, 0x0D0E0F10,
- 0x11121314, 0x15161718, 0x191A1B1C, 0x1D1E1F20,
- 0x21222324, 0x25262728, 0x292A2B2C, 0x2D2E2F30,
- 0x31323334, 0x35363738, 0x393A3B3C, 0x3D3E3F40,
- 0x41424344, 0x45464748, 0x494A4B4C, 0x4D4E4F50,
- 0x51525354, 0x55565758, 0x595A5B5C, 0x5D5E5F60,
- 0x61626364, 0x65666768, 0x696A6B6C, 0x6D6E6F70,
- 0x71727374, 0x75767778, 0x797A7B7C, 0x7D7E7F80
- };
- static const uint32_t SRC_Const_Buffer1[BUFFER_SIZE1] =
- {
- 0x0A0B0C0D, 0x1A1B1C1D, 0x2A2B2C2D, 0x2A2B2C2D,
- 0x3A3B3C3D, 0x4A4B4C4D, 0x5A5B5C5D, 0x6A6B6C6D,
- 0x7A7B7C7D, 0x8A8B8C8D, 0x9A9B9C9D, 0xAAABACAD,
- 0xBABBBCBD, 0xCACBCCCD, 0xDADBDCDD, 0xEAEBECED
- };
- static const uint32_t SRC_Const_Buffer2[BUFFER_SIZE2] =
- {
- 0x00010203, 0x04050607, 0x08090A0B, 0x0C0D0E0F,
- 0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF
- };
- /******** MDMA Destination 0 Buffer definition *******/
- /*Buffer location and size should aligned to cache line size (32 bytes) */
- #if defined ( __ICCARM__ )
- #pragma location = 0x24004000
- uint32_t DESTBuffer0_D1_AXISRAM[BUFFER_SIZE0];
- #elif defined ( __CC_ARM )
- ALIGN_32BYTES(__attribute__((section (".RAM_D1"))) uint32_t DESTBuffer0_D1_AXISRAM[BUFFER_SIZE0]);
- #elif defined ( __GNUC__ )
- ALIGN_32BYTES(uint32_t __attribute__((section (".RAM_D1"))) DESTBuffer0_D1_AXISRAM[BUFFER_SIZE0]);
- #endif
- /*****************************************************/
- /******** MDMA Destination 1 Buffer definition *******/
- /*Buffer location and size should aligned to cache line size (32 bytes) */
- #if defined ( __ICCARM__ )
- #pragma location = 0x30000000
- uint32_t DESTBuffer1_D2_SRAM1[BUFFER_SIZE0];
- #elif defined ( __CC_ARM )
- ALIGN_32BYTES(__attribute__((section (".RAM_D2"))) uint32_t DESTBuffer1_D2_SRAM1[BUFFER_SIZE0]);
- #elif defined ( __GNUC__ )
- ALIGN_32BYTES(uint32_t __attribute__((section (".RAM_D2"))) DESTBuffer1_D2_SRAM1[BUFFER_SIZE0]);
- #endif
- /*****************************************************/
- /******** MDMA Destination 2 Buffer definition *******/
- /*Buffer location and size should aligned to cache line size (32 bytes) */
- #if defined ( __ICCARM__ )
- #pragma location = 0x38000000
- uint32_t DESTBuffer2_D3_AHBSRAM[BUFFER_SIZE0];
- #elif defined ( __CC_ARM )
- ALIGN_32BYTES(uint32_t __attribute__((section (".RAM_D3"))) DESTBuffer2_D3_AHBSRAM[BUFFER_SIZE0]);
- #elif defined ( __GNUC__ )
- ALIGN_32BYTES(uint32_t __attribute__((section (".RAM_D3"))) DESTBuffer2_D3_AHBSRAM[BUFFER_SIZE0]);
- #endif
- /*****************************************************/
- __IO uint32_t TransferErrorDetected = 0;
- __IO uint32_t TransferCompleteDetected = 0;
- /******** Linked list nodes 1 to 2 definition *******/
- /*
- According to the Ref Manual :
- The channel configuration (LAR address) must be in the AXI address space.
- LAR value must be aligned at a Double Word address, i.e. LAR[2:0] = 0x0
- The LAR address register represents the next Linked list Node address.
- As consequence the Liked list transfer nodes must be 64 bits aligned and must be in the AXI address space.
- */
- /* 32-bytes Alignement is needed for cache maintenance purpose */
- ALIGN_32BYTES( MDMA_LinkNodeTypeDef Xfer_Node1);
- ALIGN_32BYTES( MDMA_LinkNodeTypeDef Xfer_Node2);
- /*****************************************************/
- /**
- * @brief MDMA Liked List transfer configuraion
- * @note This function configure the DMA for a linked list transfer.
- * The linked list contains 3 nodes.
- * Node 0 transfer parameters are configured within the Handle init parameters.
- * Next nodes are filled using HAL function "HAL_MDMA_SetLinkNodeParams"
- * after setting all nodes parameters (node 0 using HAL_MDMA_Init and
- * next nodes uing HAL_MDMA_SetLinkNodeParams) start the transfer in interrupt mode
- * using function "HAL_MDMA_Start_IT". Note that the source and destination addresses given to
- * the function HAL_MDMA_Start_IT must correspond to the node 0 source and destination addresses,
- * same for the transfer data length.
- * Note that using the MDMA the transfer data length is always expressed in bytes whatever
- * is the source and data size (byte, half word, word or double word)
- *
- * @retval None
- */
- static void MDMA_Config(void)
- {
- MDMA_LinkNodeConfTypeDef mdmaLinkNodeConfig;
- uint32_t hal_status = HAL_OK;
-
- /*##-1- Enable the MDMA clock ###############################################*/
- __HAL_RCC_MDMA_CLK_ENABLE();
-
-
- /*##-2- Select the MDMA instance to be used for the transfer : MDMA_Channel0 #*/
- MDMA_Handle.Instance = MDMA_INSTANCE;
-
- /*##-3- Initialize the MDMA channel for Node 0###############################*/
-
- /* Set the parameters to be configured for transfer Node0*/
- MDMA_Handle.Init.Request = MDMA_REQUEST_SW;
- MDMA_Handle.Init.TransferTriggerMode = MDMA_FULL_TRANSFER;
- MDMA_Handle.Init.Priority = MDMA_PRIORITY_HIGH;
- MDMA_Handle.Init.Endianness = MDMA_LITTLE_ENDIANNESS_PRESERVE;
- MDMA_Handle.Init.SourceInc = MDMA_SRC_INC_WORD;
- MDMA_Handle.Init.DestinationInc = MDMA_DEST_INC_BYTE;
- MDMA_Handle.Init.SourceDataSize = MDMA_SRC_DATASIZE_WORD;
- MDMA_Handle.Init.DestDataSize = MDMA_DEST_DATASIZE_BYTE;
- MDMA_Handle.Init.DataAlignment = MDMA_DATAALIGN_PACKENABLE;
- MDMA_Handle.Init.SourceBurst = MDMA_SOURCE_BURST_SINGLE;
- MDMA_Handle.Init.DestBurst = MDMA_DEST_BURST_SINGLE;
- MDMA_Handle.Init.BufferTransferLength = 4;
- MDMA_Handle.Init.SourceBlockAddressOffset = 0;
- MDMA_Handle.Init.DestBlockAddressOffset = 0;
- hal_status = HAL_MDMA_Init(&MDMA_Handle);
- if(hal_status != HAL_OK)
- {
- /* Initialization Error */
- Error_Handler();
- }
-
- /*##-4 Add linkedklist node 1 and 2##########################################*/
- /* Set the parameters to be configured for transfer Node1*/
- mdmaLinkNodeConfig.Init.Request = MDMA_REQUEST_SW;
- mdmaLinkNodeConfig.Init.TransferTriggerMode = MDMA_FULL_TRANSFER;
- mdmaLinkNodeConfig.Init.Priority = MDMA_PRIORITY_HIGH;
- mdmaLinkNodeConfig.Init.Endianness = MDMA_LITTLE_ENDIANNESS_PRESERVE;
- mdmaLinkNodeConfig.Init.SourceInc = MDMA_SRC_INC_BYTE;
- mdmaLinkNodeConfig.Init.DestinationInc = MDMA_DEST_INC_BYTE;
- mdmaLinkNodeConfig.Init.SourceDataSize = MDMA_SRC_DATASIZE_BYTE;
- mdmaLinkNodeConfig.Init.DestDataSize = MDMA_DEST_DATASIZE_BYTE;
- mdmaLinkNodeConfig.Init.DataAlignment = MDMA_DATAALIGN_PACKENABLE;
- mdmaLinkNodeConfig.Init.SourceBurst = MDMA_SOURCE_BURST_SINGLE;
- mdmaLinkNodeConfig.Init.DestBurst = MDMA_DEST_BURST_SINGLE;
- mdmaLinkNodeConfig.Init.BufferTransferLength = 2;
- mdmaLinkNodeConfig.Init.SourceBlockAddressOffset = 0;
- mdmaLinkNodeConfig.Init.DestBlockAddressOffset = 0;
-
- mdmaLinkNodeConfig.SrcAddress = (uint32_t)SRC_Const_Buffer1;
- mdmaLinkNodeConfig.DstAddress = (uint32_t)DESTBuffer1_D2_SRAM1;
- mdmaLinkNodeConfig.BlockDataLength = (BUFFER_SIZE1*4);
- mdmaLinkNodeConfig.BlockCount = 1;
-
- HAL_MDMA_LinkedList_CreateNode(&Xfer_Node1, &mdmaLinkNodeConfig);
-
- /* Set the parameters to be configured for transfer Node2*/
- mdmaLinkNodeConfig.Init.Request = MDMA_REQUEST_SW;
- mdmaLinkNodeConfig.Init.TransferTriggerMode = MDMA_FULL_TRANSFER;
- mdmaLinkNodeConfig.Init.Priority = MDMA_PRIORITY_HIGH;
- mdmaLinkNodeConfig.Init.Endianness = MDMA_LITTLE_ENDIANNESS_PRESERVE;
- mdmaLinkNodeConfig.Init.SourceInc = MDMA_SRC_INC_BYTE;
- mdmaLinkNodeConfig.Init.DestinationInc = MDMA_DEST_INC_WORD;
- mdmaLinkNodeConfig.Init.SourceDataSize = MDMA_SRC_DATASIZE_BYTE;
- mdmaLinkNodeConfig.Init.DestDataSize = MDMA_DEST_DATASIZE_WORD;
- mdmaLinkNodeConfig.Init.DataAlignment = MDMA_DATAALIGN_PACKENABLE;
- mdmaLinkNodeConfig.Init.SourceBurst = MDMA_SOURCE_BURST_SINGLE;
- mdmaLinkNodeConfig.Init.DestBurst = MDMA_DEST_BURST_SINGLE;
- mdmaLinkNodeConfig.Init.BufferTransferLength = 4;
- mdmaLinkNodeConfig.Init.SourceBlockAddressOffset = 0;
- mdmaLinkNodeConfig.Init.DestBlockAddressOffset = 0;
- mdmaLinkNodeConfig.SrcAddress = (uint32_t)SRC_Const_Buffer2;
- mdmaLinkNodeConfig.DstAddress = (uint32_t)DESTBuffer2_D3_AHBSRAM;
- mdmaLinkNodeConfig.BlockDataLength = (BUFFER_SIZE2*4);
- mdmaLinkNodeConfig.BlockCount = 1;
-
- HAL_MDMA_LinkedList_CreateNode(&Xfer_Node2, &mdmaLinkNodeConfig);
-
- HAL_MDMA_LinkedList_AddNode(&MDMA_Handle, &Xfer_Node1, 0);
- HAL_MDMA_LinkedList_AddNode(&MDMA_Handle, &Xfer_Node2, 0);
-
- /*##-5- Select Callbacks functions called after Transfer complete and Transfer error */
- HAL_MDMA_RegisterCallback(&MDMA_Handle, HAL_MDMA_XFER_CPLT_CB_ID, MDMA_TransferCompleteCallback);
- HAL_MDMA_RegisterCallback(&MDMA_Handle, HAL_MDMA_XFER_ERROR_CB_ID, MDMA_TransferErrorCallback);
-
- /*##-6- Configure NVIC for MDMA transfer complete/error interrupts ##########*/
- /* Set Interrupt Group Priority */
- HAL_NVIC_SetPriority(MDMA_IRQn, 0, 0);
-
- /* Enable the MDMA channel global Interrupt */
- HAL_NVIC_EnableIRQ(MDMA_IRQn);
-
- /*
- As the MDMA Nodes descriptor are located in the SRAM which
- is cacheable, it is necessary to clean the data cache after creating the node
- in order to make sure that the MDMA will load up to date data from the linked list node
- */
- SCB_CleanDCache_by_Addr( (uint32_t*)&Xfer_Node1, sizeof(MDMA_LinkNodeTypeDef));
- SCB_CleanDCache_by_Addr( (uint32_t*)&Xfer_Node2, sizeof(MDMA_LinkNodeTypeDef));
-
- /*##-7- Start the MDMA transfer using the interrupt mode ####################*/
- /* Configure the source, destination and buffer size MDMA fields and Start MDMA channel transfer of the Node 0 */
- hal_status = HAL_MDMA_Start_IT(&MDMA_Handle, (uint32_t)&SRC_Const_Buffer0,
- (uint32_t)&DESTBuffer0_D1_AXISRAM,
- (BUFFER_SIZE0 * 4),
- 1);
- if(hal_status != HAL_OK)
- {
- /* Transfer Error */
- Error_Handler();
- }
- }
复制代码
|
|