01、背景
客户在 STM32U575 的研发过程中发现了一个奇怪的问题,无法通过 LPTIM3 将 MCU 从 STOP2 模式唤醒。
02、问题分析
2.1. 查找芯片的资料
2.1.1. 查找芯片参考手册
找到芯片的参考手册 RM0456,查看 LPTIM3 是否可以将 MCU 从 STOP2 唤醒。如下图。
▲ 图1. STM32U575/585 LPTIM 特性
从图中可以看到除了 LPTIM2 不能将 MCU 从 STOP2 唤醒,其余 LPTIM1/3/4 均可将 MCU 从 STOP2 唤醒。由此看来,客户提到的问题有可能是客户的设计问题。
2.1.2. 硬件检查
对照 AN5373 ( Getting started with STM32U5 MCU hardware development ) 检查客户的原理图和 PCB 设计并未发现问题。
2.1.3. 软件检查
在与客户交流中了解到,他们的代码是从其他项目中移植过来的,在之前的项目中已经批量生产了几年了。客户怀疑是芯片的 BUG。
查找芯片的勘误手册 ES0499 ( STM32U575xx and STM32U585xx device errata ), 并未找到相关的信息。
03、复现客户的问题
3.1. 软件配置如下图
3.1.1. LPTIM3 配置如下
static void MX_LPTIM3_Init(void) { /* USER CODE BEGIN LPTIM3_Init 0 */ /* USER CODE END LPTIM3_Init 0 */ /* USER CODE BEGIN LPTIM3_Init 1 */ /* USER CODE END LPTIM3_Init 1 */ hlptim3.Instance = LPTIM3; hlptim3.Init.Clock.Source = LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC; hlptim3.Init.Clock.Prescaler = LPTIM_PRESCALER_DIV1; hlptim3.Init.Trigger.Source = LPTIM_TRIGSOURCE_SOFTWARE; hlptim3.Init.Period = 99; hlptim3.Init.UpdateMode = LPTIM_UPDATE_IMMEDIATE; hlptim3.Init.CounterSource = LPTIM_COUNTERSOURCE_INTERNAL; hlptim3.Init.Input1Source = LPTIM_INPUT1SOURCE_GPIO; hlptim3.Init.Input2Source = LPTIM_INPUT2SOURCE_GPIO; hlptim3.Init.RepetitionCounter = 0; if (HAL_LPTIM_Init(&hlptim3) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN LPTIM3_Init 2 */ /* USER CODE END LPTIM3_Init 2 */ }
启动 LPTIM3 :
if (HAL_LPTIM_TimeOut_Start_IT(&hlptim3, TIMEOUT) != HAL_OK) { Error_Handler(); }
在主循环中重复进入 STOP2 模式,由 LPTIM3 周期唤醒,这里需要注意一点的是在进入之前需 要先把滴答定时器关掉,否则有可能无法进入 STOP2 模式。
/* Suspend Tick */ HAL_SuspendTick(); /* Enter in Stop mode */ HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
3.1.2. 配置电源模式输出引脚
为了方便低功耗调试,STM32U5 提供了电源模式输出 pin 脚用于指示 MCU 所处的低功耗模式,具体引脚分别是 PA5/PA6/PA7。
/*Configure GPIO pin : PA5 */ GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF0_CSLEEP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /*Configure GPIO pin : PA6 */ GPIO_InitStruct.Pin = GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF0_CSTOP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /*Configure GPIO pin : PA7 */ GPIO_InitStruct.Pin = GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF0_SRDSTOP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
▲ 图2. 电源模式输出状态
3.2. 测试
3.2.1. 波形图
▲ 图3. 测试波形图
从图中看出 CSLEEP,CDSTOP,SRDSTOP 一直为高也就是 1,1,1 参照图 2 状态信息,可以看出 MCU 一直处于 STOP2 模式,无法通过 LPTIM3 唤醒,也就复现了客户所描述的问题。
查看参考手册 RM0456 REV2 的 50.4.20 Autonomous mode 小节的内容。当 LPTIM 使用振荡器提供的时钟时(参见 RCC),LPTIM 可以在自主模式下运行,能够在 停止模式下保持完全功能,其中 APB 时钟已停止。
查看 RCC 章节 11.4.20 Peripherals clock gating and autonomous mode 找到了更多的信息 。
▲ 图4. Autonomous 外设
看到下面的注意事项,对于 Autonomous 外设,若不能通过 EXTI 且想在 Stop 模式具有产生中断的能力需要将 AMEN 设置为 1。这就找到了问题的所在。也就是说在开发中 如果不注意这一点,对于其它的 SRD 域的外设也有可能无法将 MCU 从 STOP2 唤醒。
▲ 图5. Autonomous 外设使用注意事项
继续追查,查找相应的寄存器。对于 LPTIM3 我们可以看到,其中 LPTIM3EN,LPTIM3SMEN,LPTIM3AMEN 均需要设置为 1:
▲ 图6. LPTIM3 外设寄存器描述
在启动 LPTIM3 之前使能 Autonomous mode,添加如下代码。
/* Enable LPTIM3 Sleep Clock */ __HAL_RCC_LPTIM3_CLK_SLEEP_ENABLE(); /* Enable LPTIM3 Autonomous Mode */ __HAL_RCC_LPTIM3_CLKAM_ENABLE();
再次测试,波形如下图所示:
▲ 图7. 添加代码后测试波形图
波形正确,正是我们的设置,循环进入 STOP2 模式。
04、小结
MCU 变得越来越复杂,外设功能丰富度不断提高,同一个外设在不同型号的 MCU 上可能大致相同,可能会有一些细节不是太一样。这就要求我们不断的刷新自己的认知,不能困在自己的固有思维中。
来源:STM32
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。