STM32U5中的两个域
LPDMA 是 STM32U5 中实现超低功耗的一个重要外设。STM32U5 有域的概念,包括两个域:
CD(CPU Demain)
SRD(Smart Run Domain)
CD 是 CPU 域,包括 Cortex-M33 内核,Flash 存储器,大部分高性能外设(GPDMA1,高速通信接口)以及大部分的 SRAM(SRAM1,SRAM2,SRAM3)。当系统运行时,这个域的设备在全速运行;当系统进入低功耗时,这个域的绝大部分设备会被断电或进入保留状态。
SRD 是智能运行域,这个域中的外设可以实现在内核停止时自主运行,包括的设备有LPDMA1、LPUART、I2C3、SRAM4等。即使 CD 域在 STOP2 模式下停止了,SRD 域中的设备仍然可以保持全速供电和时钟运行。比如 LPDMA 可以实现在不唤醒 CPU 的情况下搬运数据到 SRAM4 中。
这部分内容我们可以在 STM32U5 手册的开头看到:
(请注意这里的提示:SRAM4 是唯一一个被 LPDMA1 允许的 SRAM)

CubeMX中LPDMA1和SRAM4的配置
我使用的 IDE 是 IAR 9.70.1 搭配 vscode 中的 IAR 官方插件IAR Build,这是我在使用过各种方案(Keil、Keil+EIDE、CMake+Clion)后感觉最方便同时最现代的方案。
由上文数据手册可以看到想要使用 LPDMA1,搬运的数据(目的地)必须位于 SRAM4。CubeMX 中 U5 的初始配置是没有启用 SRAM4 的,想要启用 SRAM4 需要修改链接文件,IAR 中是.icf 文件。方便起见我也用 CubeMX 来生成工程中的.icf 文件。

这个工具的位置在 Tools->Memory Management,可以看到这里启用了 SRAM4(16KB),并将这部分 SRAM 命名为 SRAM4。

具体配置部分我打开了上面的两个开关,只有打开这两个开关后 CubeMX 才会生成对应的.icf 文件;将 SRAM4 定义为需要特权级才能读写(其实应该放开读写权限),不可执行代码,不可共享,不可缓存(避免 CPU 读取到 Cache 中的旧数据),可以将 SRAM4 配置成一个合适的存放 LPDMA1 搬运数据的 RAM。请注意,打开上方两个开关后会自动配置好 U5 的 Flash 和 GTZC,不过不会对工程产生负面影响。

在 LPDMA1 中打开两个通道,分别用于 LPUART 的接收和发送。模式选择标准请求模式,可以用传统的 xxx_DMA 函数方式调用 DMA;另一个模式是链表模式,通过在链表中添加配置实现自动的多个搬运任务,使用标准模式可以进行快速开发(链表模式之后再学吧)。

由于将 SRAM4 配置成了需要特权,所以也要将两个 LPDMA 通道都配置为特权级,这样才能正确读写。

要为 TX 的 LPDMA 通道开启源地址自增,这样才能正确搬运地址连续的数组数据;

同样的,RX 的 LPDMA 通道需要开启目标地址自增,这样才能将串口接收到的连续数据写入数组中。
到此为止,LPDMA1 和 SRAM4 的相关 CubeMX 配置已经完成了,可以生成代码准备编写业务了 ~
补充:
CubeMX 生成的.icf 文件中出现修改的部分如下:
/*-Start of symbols-Auto-generated By STM32CubeMX*/
define symbol __ICFEDIT_region_SRAM4_start__ =0x28000000;
define symbol __ICFEDIT_region_SRAM4_end__ =0x28003FFF;
/*-End of MX Symbols*/
...
/*-Start of Regions- Auto-generated By STM32CubeMX*/
define region SRAM4_region = mem:[from __ICFEDIT_region_SRAM4_start__ to __ICFEDIT_region_SRAM4_end__];
/*-End of MX Regions-*/在 IAR 工程中,想要在定义的 SRAM4 地址中创建数组,代码如下:
#pragma location = "SRAM4_section"
static uint8_t lora_tx_buffer[LORA_UART_BUFFER_MAX_SIZE];
#pragma location = "SRAM4_section"
static uint8_t lora_rx_buffer[LORA_BUFFER_MAX_DEPTH][LORA_UART_BUFFER_MAX_SIZE];