[STM32U5] STM32U575板子DMA的问题

[复制链接]
362|56
 楼主| Tom952331 发表于 2026-6-4 18:02 | 显示全部楼层
elephant00 发表于 2026-6-4 16:38
源数组是const uint16_t,取地址应该是uint16_t*,你转成uint16_t的话,只取了地址的低16位,高16位没了。 ...

谢谢!改成uint16_t *也不行。
 楼主| Tom952331 发表于 2026-6-4 18:03 | 显示全部楼层
classroom 发表于 2026-6-4 17:37
半字传要求地址2字节对齐,你那两个数组起始地址是不是奇数?比如0x20000001这种,DMA传半字会出错。 ...

我用原来字传输的数组也不行。
xch 发表于 2026-6-4 21:24 | 显示全部楼层
本帖最后由 xch 于 2026-6-4 21:25 编辑

  1. #define MAXIUM_DMA_BLOCK_SIZE  ( 65536-4 )
  2. typedef struct{
  3.   uint32_t BR1; //数据量
  4.   uint32_t DAR; //填充仅需要更新目标地址
  5.   uint32_t DSR; //填充仅需要更新目标地址
  6.   uint32_t LLR; //数据链
  7. }tDMA_LLS;

  8. /*******链表结构必须在同一个64K区域*******/
  9. tDMA_LLS DMA_MEM_LLS[MAX_LLS_ARRAY_NUM] @0x20000000 ;

  10. void DmaCopyHalfWordBlock (uint32_t bytes, uint16_t * dst ,uint16_t *src)
  11. {
  12.   
  13.   DMA_MEM_CH->CTR1 = DMA_CTR1_SAP|DMA_CTR1_DINC|DMA_CTR1_SINC|\
  14.     (DMA_DEST_DATAWIDTH_HALFWORD)|(DMA_DEST_DATAWIDTH_HALFWORD);
  15.   DMA_MEM_CH ->CTR2 = DMA_REQUEST_SW|DMA_BREQ_BLOCK|DMA_TCEM_EACH_LL_ITEM_TRANSFER;    //使用软件 DMA请求
  16.   DMA_MEM_CH ->CSAR = (uint32_t)(uint64_t)src;
  17.   DMA_MEM_CH ->CDAR = (uint32_t)(uint64_t)dst;

  18.   if( bytes <=MAXIUM_DMA_BLOCK_SIZE ){
  19.     DMA_MEM_CH ->CBR1 = bytes ;
  20.   }
  21.   else{
  22.     DMA_MEM_CH ->CBR1 = MAXIUM_DMA_BLOCK_SIZE;
  23.     uint32_t lls = DMA_CLLR_UB1|DMA_CLLR_UDA|DMA_CLLR_USA|DMA_CLLR_ULL;
  24.     uint32_t base = (uint32_t )(uint64_t)DMA_MEM_LLS;
  25.     DMA_MEM_CH ->CLLR = lls|(uint16_t)base;
  26.     DMA_MEM_CH ->CLBAR = (uint32_t)base&0xffff0000; //MSB,LLS BASE
  27.     DMA_LLS_Config ( DMA_MEM_LLS,\
  28.       bytes - MAXIUM_DMA_BLOCK_SIZE,\
  29.         (uint32_t)(uint64_t)dst+MAXIUM_DMA_BLOCK_SIZE,  (uint32_t)(uint64_t)src+MAXIUM_DMA_BLOCK_SIZE,lls);
  30.   }
  31.   //启动传输
  32.   DMA_MEM_CH ->CCR  = DMA_CCR_EN;
  33. }

  34. /****************************************
  35. 填充一片区域,超出65535需要使用动态链表
  36. size 是 uint32_t 的数量,按照字节数计算一个传输链
  37. 不得超出16383*4 字节
  38. ***********************************************/
  39. static void DMA_LLS_Config ( tDMA_LLS *plls,uint32_t bytes,uint32_t dar, uint32_t sar, uint32_t lls)
  40. {
  41.   uint8_t max = (bytes +MAXIUM_DMA_BLOCK_SIZE-1)/MAXIUM_DMA_BLOCK_SIZE-1;
  42.   uint8_t i =0;
  43.   for (;i<max;i++){
  44.     plls[i].DAR = dar +i*(MAXIUM_DMA_BLOCK_SIZE);
  45.     plls[i].SAR = sar +i*(MAXIUM_DMA_BLOCK_SIZE);
  46.     plls[i].BR1 = MAXIUM_DMA_BLOCK_SIZE;   //当前传输数量
  47.     plls[i].LLR = lls|(uint16_t)(uint64_t)&plls[i+1];//指向下一个链表的低16位
  48.   }
  49.   plls[i].DAR = dar +i*(MAXIUM_DMA_BLOCK_SIZE); //新内存地址
  50.   plls[i].SAR = sar +i*(MAXIUM_DMA_BLOCK_SIZE); //新内存地址
  51.   plls[i].BR1 = bytes % MAXIUM_DMA_BLOCK_SIZE; //剩余数据量
  52.   plls[i].LLR = 0;  //表示链表结束
  53. }
 楼主| Tom952331 发表于 2026-6-5 06:43 | 显示全部楼层
flycamelaaa 发表于 2026-6-4 19:38
半字传的话,SrcDataWidth和DestDataWidth得设成DMA_SRC_DATAWIDTH_HALFWORD,你初始化里改对了没? ...

这个初始化了。
 楼主| Tom952331 发表于 2026-6-5 11:19 | 显示全部楼层
onlycook 发表于 2026-6-4 21:39
中断服务函数GPDMA1_Channel15_IRQHandler里,有没有调用HAL_DMA_IRQHandler(&handle_GPDMA1_Channel15)? ...

有调用
CarterERO 发表于 2026-6-15 13:19 | 显示全部楼层
改用HAL_DMA_Start_IT1时,确保SrcAddress和DstAddress都是uint32_t类型,且数组地址必须是2字节对齐。检查你的源代码中地址转换是否正确。
 楼主| Tom952331 发表于 2026-6-15 13:45 | 显示全部楼层

谢谢!考进去一大堆错误。我找参考手册,没有找到DMA_MEM_CH这个寄存器
 楼主| Tom952331 发表于 2026-6-15 15:03 | 显示全部楼层

我考过来,一大堆错误。我找参考手册,没有DMA_MEM_CN这个寄存器
 楼主| Tom952331 发表于 2026-6-16 09:10 | 显示全部楼层

我考到文件里,一大堆错误。而且我找参考手册,没有找到DMA_MEM_CH寄存器
21ic小管家 发表于 2026-6-16 09:32 | 显示全部楼层
xch 发表于 2026-6-16 09:38 | 显示全部楼层
Tom952331 发表于 2026-6-15 13:45
谢谢!考进去一大堆错误。我找参考手册,没有找到DMA_MEM_CH这个寄存器

你自己定义用哪个通道就是了。比如
#define DMA_MEM_CH              GPDMA1_Channel0
xch 发表于 2026-6-16 09:40 | 显示全部楼层
#define DMA_MEM_LLS_CH              GPDMA1_Channel10
 楼主| Tom952331 发表于 2026-6-16 10:53 | 显示全部楼层

我把代码考到文件里,一大堆错误。我在参考手册里也找不到DMA_MEM_CH这个寄存器
xch 发表于 2026-6-16 12:03 | 显示全部楼层
Tom952331 发表于 2026-6-16 10:53
我把代码考到文件里,一大堆错误。我在参考手册里也找不到DMA_MEM_CH这个寄存器 ...

Tom952331 发表于 2026-6-15 13:45
谢谢!考进去一大堆错误。我找参考手册,没有找到DMA_MEM_CH这个寄存器

你自己定义用哪个通道就是了。比如:

#define DMA_MEM_CH                     GPDMA1_Channel0
#define DMA_MEM_LLS_CH              GPDMA1_Channel10
 楼主| Tom952331 发表于 2026-6-17 00:19 | 显示全部楼层
xch 发表于 2026-6-16 12:03
Tom952331 发表于 2026-6-15 13:45
谢谢!考进去一大堆错误。我找参考手册,没有找到DMA_MEM_CH这个寄存 ...

谢谢!这一句还有错误:

5.jpg

AIsignel 发表于 2026-7-15 21:22 | 显示全部楼层
检查DMA配置,确保源/目标地址、数据宽度、传输模式等参数正确,同时确认外设时钟使能。
 楼主| Tom952331 发表于 2026-6-17 16:26 | 显示全部楼层
xch 发表于 2026-6-16 12:03
Tom952331 发表于 2026-6-15 13:45
谢谢!考进去一大堆错误。我找参考手册,没有找到DMA_MEM_CH这个寄存 ...

我改成这样定义,通过了。tDMA_LLS DMA_MEM_LLS[MAX_LLS_ARRAY_NUM];

我这样调用:DmaCopyHalfWordBlock (BUFFER_SIZE,(uint16_t *)aSRC_Const_Buffer1,aDST_Buffer1);
发现不灵,没拷贝过去。
xch 发表于 2026-6-17 16:52 | 显示全部楼层
Tom952331 发表于 2026-6-17 16:26
我改成这样定义,通过了。tDMA_LLS DMA_MEM_LLS[MAX_LLS_ARRAY_NUM];

我这样调用:DmaCopyHalfWordBlock ...

BUFFER_SIZE 是字节数。
MCU启动后先用这段代码先初始化一下。

  1.   handle_GPDMA1_Channel10.Instance = GPDMA1_Channel10;
  2.   handle_GPDMA1_Channel10.Init.Request = DMA_REQUEST_SW;
  3.   handle_GPDMA1_Channel10.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
  4.   handle_GPDMA1_Channel10.Init.Direction = DMA_MEMORY_TO_MEMORY;
  5.   handle_GPDMA1_Channel10.Init.SrcInc = DMA_SINC_FIXED;
  6.   handle_GPDMA1_Channel10.Init.DestInc = DMA_DINC_FIXED;
  7.   handle_GPDMA1_Channel10.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
  8.   handle_GPDMA1_Channel10.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
  9.   handle_GPDMA1_Channel10.Init.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
  10.   handle_GPDMA1_Channel10.Init.SrcBurstLength = 1;
  11.   handle_GPDMA1_Channel10.Init.DestBurstLength = 1;
  12.   handle_GPDMA1_Channel10.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
  13.   handle_GPDMA1_Channel10.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
  14.   handle_GPDMA1_Channel10.Init.Mode = DMA_NORMAL;
  15.   if (HAL_DMA_Init(&handle_GPDMA1_Channel10) != HAL_OK)
  16.   {
  17.    // Error_Handler();
  18.   }
  19.   if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel10, DMA_CHANNEL_NPRIV) != HAL_OK)
  20.   {
  21. //    Error_Handler();
  22.   }
xch 发表于 2026-6-17 16:55 | 显示全部楼层
  1. handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;
  2.   handle_GPDMA1_Channel0.Init.Request = DMA_REQUEST_SW;
  3.   handle_GPDMA1_Channel0.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
  4.   handle_GPDMA1_Channel0.Init.Direction = DMA_MEMORY_TO_MEMORY;
  5.   handle_GPDMA1_Channel0.Init.SrcInc = DMA_SINC_INCREMENTED;
  6.   handle_GPDMA1_Channel0.Init.DestInc = DMA_DINC_INCREMENTED;
  7.   handle_GPDMA1_Channel0.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
  8.   handle_GPDMA1_Channel0.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
  9.   handle_GPDMA1_Channel0.Init.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
  10.   handle_GPDMA1_Channel0.Init.SrcBurstLength = 1;
  11.   handle_GPDMA1_Channel0.Init.DestBurstLength = 1;
  12.   handle_GPDMA1_Channel0.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
  13.   handle_GPDMA1_Channel0.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
  14.   handle_GPDMA1_Channel0.Init.Mode = DMA_NORMAL;
  15.   if (HAL_DMA_Init(&handle_GPDMA1_Channel0) != HAL_OK)
  16.   {
  17.     //Error_Handler();
  18.   }
  19.   if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV) != HAL_OK)
  20.   {
  21.     //Error_Handler();
  22.   }
 楼主| Tom952331 发表于 2026-6-17 17:03 | 显示全部楼层
xch 发表于 2026-6-17 16:52
BUFFER_SIZE 是字节数。
MCU启动后先用这段代码先初始化一下。

还是不行,我都快放弃了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部
0