STM32单片机项目实例:基于TouchGFX的智能手表设计(4)LPBAM的应用
目录
? STM32U5 系列微控制器基于具有 Arm? TrustZone?和 FPU 的高性能 Arm?32 位 Cortex?-M33 CPU。此类产品均采用新型结构制造,得益于其高度灵活性和高级外设集,实现了一流的超低功耗性能。
? 除了多种 CPU 激活模式配置(可实现更高性能或更低功耗)之外, STM32U5 系列还支持大量低功耗模式,每种模式都具有多个选项。这使得设计人员可以在低功耗性能、短启动时间、可用外设集与 SRAM 数量,以及唤醒源最大数量之间实现最佳折中。
? 嵌入式 SMPS(开关模式电源)降压转换器可用于带有“Q”后缀的特定部件号(例如 STM32U5xxxxxxQ),从而提高激活和低功耗模式下的能源性能。
?图 1-1??传统芯片与带SMPS芯片供电差异
? SMPS 和 LDO 是并行的,并且应用时可在运行中动态选择,LDO提供更少噪声,SMPS提供更高的转换效率。
图 1-2??内部调压器的工作范围
所有电源模式都支持SMPS和LDO:
图 1-3??内部调压器的功耗?
? 动态电压缩放是一种电源管理技术,它包括根据应用性能和功耗需求增加或降低用于数字外设(VCORE)的电压。
? 动态电压缩放以增加VCORE被称为过电压。它允许设备提高其性能。
? 动态电压缩放以降低VCORE被称为欠压。这样做是为了节省电力,特别是在笔记本电脑和其他移动设备中,这些设备的能量来自电池,因此是有限的。
该调节器在以下范围内工作:
它提供1.2 V的典型输出电压。当系统时钟频率高达160MHz时使用。
它提供1.1 V的典型输出电压。当系统时钟频率高达110MHz时使用。
典型输出电压为1.0 V。系统时钟频率最高可达55MHz。
提供0.9 V的典型输出电压。系统时钟频率最高可达25MHz。
? 在PWR_VOSR中,通过VOS[1:0]选择电压缩放。在将系统时钟频率增加到范围1和范围2的55mhz以上之前,必须使能并准备好EPOD(嵌入式电源分配)升压器。
STM32U5 器件支持 4 种主要低功耗模式:
CPU 时钟关闭,但所有外设均可保持激活状态。所有外设中断或事件可唤醒 CPU。
高速时钟默认关闭,所有外设和内存保留均可保持激活状态。四种停机模式可供使用:停机 0、停机 1、停机 2 和停机 3,功耗从高到低。 LPBAM(低功耗后台自主模式)是一项创新功能,停机 0、停机 1 和停机 2 模式均支持该功能。借助于LPBAM,一些外设继续与 DMA(直接内存访问)一起自主工作。当外设须保持激活状态时,这大幅降低了应用的功耗。通过 LPBAM,可保持激活的外设数量在停机 2 中要比在停机 0 和停机 1 更少。停机 3 模式不支持 LPBAM。
内部调压器关闭。大多数外设和 SRAM 保留随后丢失。在待机模式下最多可保留 64 KB SRAM2 和 2 KB BKPSRAM。
这与待机模式类似,但电源欠压复位和监控被禁用。在该模式下则无法切换到 VBAT。
通过 LPBAM 和高能效处理,高度灵活的低功耗模式与自主外设相结合,使 STM32U575xxxxQ/STM32U585xxxxQ 器件达到行业领先的 EEMBC?ULPBench 分数,高达 535ULPMark。
?1-4??STM32U5 Benchmarks 表现
?说明:文章来源于ST公司的《AN5645-应用笔记-STM32U5 系列使用 LPBAM 进行功耗优化》
? LPBAM(低功耗后台自主模式,low-power batch autonomous mode)是一种操作模式,允许外设从设备功耗模式到停机 2 模式独立地正常和自主运行,无需运行任何软件。由于 DMA 链表传输, LPBAM 子系统可以链接不同的操作。 DMA 操作可涉及:
使用 LPBAM 自动优化功耗:
? 即使在停机模式下,大量的硬件触发选择也允许外设自动启动的活动。外设中断在启用时从停机模式唤醒设备。
? LPBAM 的典型基本用例是设备处于停机 2 模式下的周期性外设操作(例如 ADC 转换,或通过 I2C 或 SPI 等通信接口仅限传感器采集)。唤醒源可以是任何外设中断,例如:
图 2-1??LPBAM典型应用?
? 可以使用多个 DMA 通道或在同一通道上链接来自不同外设的操作来构建更复杂的应用。
支持 LPBAM 的外设分为两类:
这些外设支持停机模式下的 DMA 传输。
? 这些外设不支持 DMA 请求,也不支持生成时钟请求。但借助于 DMA 时钟请求,可以在因 DMA 时钟请求而接收到系统时钟时,对外设本身的寄存机进行重新配置。除此之外,有些也可以为自主外设提供硬件触发。
? 自主或被动 LPBAM 外设产生的任何中断都会将 STM32U5 器件从停机模式唤醒。需要注意的是停机 3 模式不支持 LPBAM模式。
?图?2-2??支持LPBAM的外设
? STM32U5 分为两个域: CPU 域(CD)和 SmartRun 域(SRD)。下图和下表显示了 AHB 和 APB 外设在这两个域中的分布。
?图 3-1??电源和时钟域的架构?
?图?3-2??AHB/APB 总线的域分布
(1). 只有一部分外设支持 LPBAM(参见图?3-3)。
? 在停机 0 和停机 1 模式下, CPU 域和 SmartRun 域完全供电,而且均可支持 LPBAM 的动态活动。然后可以使用GPDMA1 和 LPDMA1 两者。 GPDMA1 可以访问所有设备 SRAM,而 LPDMA1 只能访问 SRAM4。
? 在停机 2 模式下, CPU 域处于低泄漏模式,禁止任何动态活动。借助 LPBAM,只有 SmartRun 域完全供电并且可以维持动态活动。只能使用 LPDMA1,其只能访问 SRAM4。 LPDMA1 链表项和外设数据缓冲区均须位于 SRAM4中。本文重点介绍停机 2 模式下的 LPBAM,因为这是最有效的节能源模式。
警告:在停机 0 和停机 1 模式下,映射到 AHB3 和 APB3(属于 SmartRun 域)的自主外设只能与 LPDMA1 和 SRAM4一起使用。主要原因在于当 SRD 外设请求总线时钟时, AHB 和 APB 时钟仅分布在 SmartRun 域中,而不是CPU 域中。
停机 0、停机 1 或停机 2 模式下 LPBAM 活动期间 SRD 中的时钟分布
自主外设可请求其时钟(内核时钟或总线时钟),使其能正常工作,在工作完毕后会自动恢复到默
认的关闭时钟状态(STOP 状态)来降低功耗(LSE 和 LSI 低功耗低速振荡器除外)。
? 在停机 2 模式中,只有 SmartRun 域中的外设可正常工作,时钟在该域中运行。下图放大了 SRD 架构,显示了在停机 2 模式下正常工作的所有外设。
?图?3-4??SRD 架构
SmartRun 域可以具有两种状态:
图?3-5??RD 状态转换?
提示:通过设置 PWR-CR2 中的 SRDRUN 位,可强制使 SRD 始终处于 DRun 状态。?
? LPBAM 工作在停机模式下,在该模式下内部振荡器默认禁用(LSI 和 LSE 等低速时钟除外), SRAM4 处于低功耗状态。外设的速度须考虑到停机 1 和停机 2 模式下的最大时钟速度为 24 MHz(类似于调压器处于 Range 4 中时的停机 0),以及时钟必须在停机模式需要时被唤醒,而这会引入延迟。?
? 警告: 与运行或睡眠模式 Range 4 中的操作相比,外设的速度受到更多限制,因为当外设请求时钟时,时钟可能是处于被禁用状态。
? 在FS-STM32U5开发板通过LPBAM实现低功耗模式下,每隔1S秒切换一个带LPDMA链表功能的LPGPIO引脚。
图?3-6??IOToggle实验
? 在主程序开始时调用HAL_Init()函数进行重置所有外设,初始化Flash接口和系统滴答定时器。然后使用SystemClock_Config()函数对系统进行配置,系统时钟(SYSCLK)运行在160 MHz。
1. AHB外设的HCLK运行频率为160兆赫。
2. APB时钟分频器APB1、APB2、APB3外设运行频率为160 MHz。
FS-STM32U575-LPGPIO_IOToggle应用程序包含:
1. 一个LPBAM子应用名为**WriteIO**。
WriteIO应用程序包含:
1. 一个名为“**WriteSeq**”的LPBAM场景。
LPBAM?WriteIO应用配置系统达到最低功耗。
LPBAM?WriteSeq场景配置所使用的外设,并构建场景链表。
WriteSeq场景执行:
1. 创建写LPGPIO引脚11(PB3)值队列(LPGPIO_BSRR)。
2. 每次写操作由LPTIM1 PWM上升沿信号触发。
此场景无限循环重复。
LPTIM1 PWM触发信号周期为1s。
配置、构建、连接和启动LPBAM场景后,MCU进入Stop2模式。
用户按钮引脚(PA.12)配置为具有上升沿输入的外部中断(EXTI_Line12),当按键被按下后释放,系统从Stop2模式唤醒。
从Stop2模式唤醒后,LPBAM子系统仍在工作,蓝色led灯常亮。
当再按一次用户按钮时,LPBAM场景将被停止、解除链接和去初始化,蓝色led闪烁。新建工程,选择STM32U575RIT6。
Project?Manager页面,设置工程名:FS-STM32U575-LPGPIO_IOToggle,选择工程路径,工具链选择MDK-ARM,Code?Generator页面,Copy?only?the…?
?Clock?Configuration页面,设置MSIS时钟4000KHz,设置PLLM/1,X80,/2,系统运行频率160MHz。
?Pinout?&?Configuration 页面,设置PA12的GPIO mode为外部上升沿触发检测,配置PC13设置为PP输出。?
?NVIC页面使能EXTI Line?12?interrupt。
?ICACHE的模式设置为1-way(direct?mapped?cache)
? ?LPDMA1设置为Linked-List?Mode,Transfer?Event?Generation设置为The?TC(and?the?HT)event?is?generated?at?the?(respectively half) end of the last linked-list item。并在NVIC Settings页面设置LPDMA1全局中断使能。
User?Constants页面增加以下几个参数:
LPTIM1_PWM_PERIOD | 31999U |
LPTIM1_PWM_PULSE | 15999 |
LPGPIO_BUFFER_SIZE | 2U |
LPTIM1_PWM_REPETITION | 0U |
?点击Pinout下拉框中的Set?unused?GPIOs,快捷按键Ctrl+G,将滑条拉至最大,GPIO Type选择Analog,点击OK按钮进行设置。
?点击LPBAM Scenario?&?Configuration进行LPBAM场景的配置
点击Add?Application,修改LpbamAp1名称为WriteIO,修改Scenario名称为WriteSeq,修改Queue1名称为ToggleIO。?
点击WriteIO,设置队列模式为循环,并使能DMA的错误中断。
点击LPGPIO1选项,点击Write?Pin?Sequence右侧的+号,修改函数名称为WritePinSequence_1,选择端口PB3,端口状态数量设置2,端口状态Buffer设置LPGPIOBufferState,端口Buffer偏移设置为0。触发配置设置为trigged?on?the?Rising?Edge?of?the?Hardware?Signal,硬件触发信号选择LPTIM1_CH1。
?Pinout?&?Configuration 页面,RCC设置外部低速时钟源为Crystal/Ceramic?Resonator。
LPTIM1外设,设置模式为Counts?internal?clock?events,并按照下图进行配置:
?PWR对SRAM进行设置,除SRAM4与ICACHE以外全部Enable,SRAM fast wakeup下的选项Disable。
回到RCC界面,设置LSE的驱动能力为中高级。
?Clock?Configuration页面,设置LPTIM1时钟选择器为LSE。
Pinout?&?Configuration 页面,设置PB3为LPGPIO 为OD输出。
?点击右上角的CHECK LPBAM DESIGN ,检查通过后,点击GENERATE CODE生成工程。
?上述步骤中如果是第一次进入LPBAM常见,GENERATE CODE是灰色的,可以退出LPBAM场景后进行生成代码。退出过程会有警告,点击OK。
?在通用场景进行CHECK LPBAM DESIGN并点击GENERATE CODE,工程生成完成后打开。
?打开工程,在main.c文件Private includes位置增加lpbam_writeio.h头文件。
/* USER CODE BEGIN Includes */
#include "lpbam_writeio.h"
/* USER CODE END Includes */
?在Private variables位置增加LPGPIO的端口状态数组。
/* USER CODE BEGIN PV */
/* Push Button State */
__IO uint32_t PushButtonState = PB_NOT_PRESSED;
/* Buffer declaration */
uint32_t LPGPIOBufferState[LPGPIO_BUFFER_SIZE] =
{
__LPBAM_GPIO_STATE(LPBAM_GPIO_PIN_11, LPBAM_GPIO_PIN_SET),
__LPBAM_GPIO_STATE(LPBAM_GPIO_PIN_11, LPBAM_GPIO_PIN_RESET)
};
/* USER CODE END PV */
?在Private function prototypes位置增加函数声明。
/* USER CODE BEGIN PFP */
static void Enter_Stop2_Mode(void);
/* USER CODE END PFP */
?在main函数中增加初始化配置。
/* LPBAM WriteIO application init */
MX_WriteIO_Init();
/* LPBAM WriteIO application WriteSeq scenario init */
MX_WriteIO_WriteSeq_Init();
/* LPBAM WriteIO application WriteSeq scenario build */
MX_WriteIO_WriteSeq_Build();
/* LPBAM WriteIO application WriteSeq scenario link */
MX_WriteIO_WriteSeq_Link(&handle_LPDMA1_Channel0);
/* LPBAM WriteIO application WriteSeq scenario start */
MX_WriteIO_WriteSeq_Start(&handle_LPDMA1_Channel0);
/* Enter Stop2 mode */
Enter_Stop2_Mode();
/* Reset push button state */
PushButtonState = PB_NOT_PRESSED;
/* Wait for next push button press to stop the LPBAM WriteIO application WriteSeq scenario */
//停止模式下,核心板LED灯不亮,等待外部中断唤醒,LED长亮,再次按下按键,LED灯闪烁
while (PushButtonState == PB_NOT_PRESSED)
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
}
/* LPBAM WriteIO application WriteSeq scenario stop */
MX_WriteIO_WriteSeq_Stop(&handle_LPDMA1_Channel0);
/* LPBAM WriteIO application WriteSeq scenario unlink */
MX_WriteIO_WriteSeq_UnLink(&handle_LPDMA1_Channel0);
/* LPBAM WriteIO application WriteSeq scenario de-init */
MX_WriteIO_WriteSeq_DeInit();
/* Initialize gpio */
MX_GPIO_Init();
在while函数中增加端口控制代码。
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13); /* 运行指示灯状态翻转 */
HAL_Delay(500);
}
/* USER CODE END 3 */
?增加Enter_Stop2_Mode模式代码。
/* USER CODE BEGIN 4 */
/**
* @brief Enter Stop2 mode and checks whether the system was in Stop2 or not.
* @param None
* @retval None
*/
static void Enter_Stop2_Mode(void)
{
/* Enter the system to STOP2 mode */
__HAL_RCC_PWR_CLK_ENABLE();
/* 停止系统滴答计时器 */
HAL_SuspendTick();
/* 进入STOP2模式 */
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
/* 恢复系统滴答计时器 */
HAL_ResumeTick();//
/* Check that the system was resumed from stop 2 */
if (__HAL_PWR_GET_FLAG(PWR_FLAG_STOPF) == 0U)
{
Error_Handler();
}
/* Clear stop flag */
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_STOPF);
/* Check that stop flag is cleared */
if (__HAL_PWR_GET_FLAG(PWR_FLAG_STOPF) != 0U)
{
Error_Handler();
}
}
//退出STOP2模式
void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_12) //检测PA12按键
{
PushButtonState = PB_PRESSED;
}
/* Prevent unused argument(s) compilation warning */
UNUSED(GPIO_Pin);
}
/* USER CODE END 4 */
?在main.h中增加端口状态的枚举。
/* USER CODE BEGIN ET */
typedef enum
{
PB_NOT_PRESSED = 0,
PB_PRESSED = 1,
} PB_State_t;
/* USER CODE END ET */
在lpbam_writeio_writeseq_build.c文件中增加外部变量的声明。
/* USER CODE BEGIN EV */
/* Buffer declaration */
extern uint32_t LPGPIOBufferState[LPGPIO_BUFFER_SIZE];
/* USER CODE END EV */
?在lpbam_writeio_writeseq_build.c文件中增加外部变量的声明。
/* USER CODE BEGIN EV */
/* Buffer declaration */
extern uint32_t LPGPIOBufferState[LPGPIO_BUFFER_SIZE];
/* USER CODE END EV */
?在lpbam_writeio_writeseq_config.c文件中增加PWM的启动与停驶设置。
/**
* @brief WriteIO application WriteSeq scenario start
* @retval None
*/
void MX_WriteIO_WriteSeq_Start(DMA_HandleTypeDef *hdma)
{
/* LPBAM start DMA channel in linked-list mode */
if (HAL_DMAEx_List_Start(&hdma[TOGGLEIO_Q_IDX]) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN WriteIO_WriteSeq_Start */
/* Start PWM generation */
if (HAL_LPTIM_PWM_Start(&hlptim1, LPTIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE END WriteIO_WriteSeq_Start */
}
/**
* @brief WriteIO application WriteSeq scenario stop
* @retval None
*/
void MX_WriteIO_WriteSeq_Stop(DMA_HandleTypeDef *hdma)
{
/* LPBAM stop DMA channel in linked-list mode */
if ((hdma[TOGGLEIO_Q_IDX].State == HAL_DMA_STATE_BUSY) && (hdma[TOGGLEIO_Q_IDX].LinkedListQueue->FirstCircularNode != 0U))
{
if (HAL_DMA_Abort(&hdma[TOGGLEIO_Q_IDX]) != HAL_OK)
{
Error_Handler();
}
}
/* Check if DMA channel interrupt is enabled */
if ((hdma[TOGGLEIO_Q_IDX].State == HAL_DMA_STATE_BUSY) && (__HAL_DMA_GET_IT_SOURCE(&hdma[TOGGLEIO_Q_IDX], DMA_IT_TC) == 0U))
{
if (HAL_DMA_PollForTransfer(&hdma[TOGGLEIO_Q_IDX], HAL_DMA_FULL_TRANSFER, DMA_TIMEOUT_DURATION) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN WriteIO_WriteSeq_Stop */
/* Start PWM generation */
if (HAL_LPTIM_PWM_Stop(&hlptim1, LPTIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE END WriteIO_WriteSeq_Stop */
}
?点击魔术棒设置RAM的运行区域0x28000000,大小0x4000。
?最后对工程进行编译与下载。