BlueNRG-LP有时候进不了低功耗
<p>大佬们,BlueNRG-LP有时候进不了低功耗,求助求助!。</p><p>本来是要进入POWER_SAVE_LEVEL_STOP_NOTIMER,但有时候会直接变成POWER_SAVE_LEVEL_RUNNING这个模式。调试了一下感觉是有时候进低功耗时,协议栈仍处在活跃状态,现在我进低功耗之前,都有调用这个aci_gap_set_advertising_enable(0, 0, Advertising_Set_Parameters)函数接口,当还是会出现图片这种情况,想问一下有没有什么函数接口可以完全关闭协议栈的,,或者可以能够确保进入低功耗的操作。 </p>
<p>试过Power Save Modes这个例程没?</p>
<p> </p>
<p></p>
<p> </p>
<pre>
<code class="language-cpp">
/******************** (C) COPYRIGHT 2019 STMicroelectronics ********************
* File Name : Micro_PowerSave_main.c
* Author : RF Application Team
* Version : V1.0.0
* Date : 25-March-2019
* Description : Code demonstrating Power Save with BlueNRG-LP
********************************************************************************
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include "bluenrg_lp_it.h"
#include "bluenrg_lp_evb_com.h"
#include "bluenrg_lp_evb_led.h"
#include "bluenrg_lp_ll_rcc.h"
#include "bluenrg_lp_ll_rtc.h"
#include "hal_miscutil.h"
#include "bluenrg_lp_hal_power_manager.h"
#include "bluenrg_lp_hal_vtimer.h"
/** @addtogroup BlueNRGLP_StdPeriph_Examples BlueNRG-LP Peripheral Examples
* @{
*/
/** @addtogroup Micro_Examples Micro Examples
* @{
*/
/** @addtogroup Micro_PowerManagerMicro Power Manager Example
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#if defined CONFIG_HW_LS_RO
/* Sleep clock accuracy. */
#define SLEEP_CLOCK_ACCURACY 500
/* Calibration must be done */
#define INITIAL_CALIBRATION TRUE
#define CALIBRATION_INTERVAL 1000
#elif defined CONFIG_HW_LS_XTAL
/* Sleep clock accuracy. */
#define SLEEP_CLOCK_ACCURACY 100
/* No Calibration */
#define INITIAL_CALIBRATION FALSE
#define CALIBRATION_INTERVAL 0
#endif
/* High Speed start up time */
#define HS_STARTUP_TIME 328 // 800 us
#define WAKEUP_TIMEOUT 5000
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static VTIMER_HandleType timerHandle;
/* Private function prototypes -----------------------------------------------*/
void help(void);
void PrintNegotiatedLevel(uint8_t stopLevel);
void PrintWakeupSource(uint32_t wakeupSources);
/* Private functions ---------------------------------------------------------*/
/**
* @brief Display the help functions.
* @paramNone
* @retval None
*/
void help(void)
{
printf("POWER MANAGER help commands:\r\n");
printf("s: SHUTDOWN LEVEL : the only wakeup source is a low pulse on the RSTN pad\r\n");
printf("t: POWER_SAVE_LEVEL_STOP_WITH_TIMER : wake on uart (PA8)/timeout 5 sec (VTIMER)/button PUSH1 (PA10)\r\n");
printf("z: POWER_SAVE_LEVEL_STOP_WITH_TIMER : wake on uart (PA8)/timeout 5 sec (RTC)/button PUSH1 (PA10)\r\n");
printf("n: POWER_SAVE_LEVEL_NOTIMER : wake on uart (PA8)/button PUSH1 (PA10)\r\n");
printf("c: POWER_SAVE_LEVEL_CPU_HALT : wake on button PUSH1 (PA10)\r\n");
printf("l: Toggle led LED1\r\n");
printf("p: Print Hello World message\r\n");
printf("r: Reset the BlueNRG-LP\r\n");
printf("?: Display this help menu\r\n");
printf("\r\n> ");
}
/**
* @briefDisplay the Stop Level negotiated.
* @paramstopLevel negotiated Stop level
* @retval None
*/
void PrintNegotiatedLevel(uint8_t stopLevel)
{
printf("Power save level negotiated: ");
switch (stopLevel)
{
case POWER_SAVE_LEVEL_RUNNING:
printf ("RUNNING\r\n");
break;
case POWER_SAVE_LEVEL_CPU_HALT:
printf ("CPU_HALT\r\n");
break;
case POWER_SAVE_LEVEL_STOP_WITH_TIMER:
printf ("STOP_WITH_TIMER\r\n");
break;
case POWER_SAVE_LEVEL_STOP_NOTIMER:
printf ("STOP_NOTIMER\r\n");
break;
}
}
/**
* @briefDisplay the Wakeup Source.
* @paramwakeupSource Wakeup Sources
* @retval None
*/
void PrintWakeupSource(uint32_t wakeupSources)
{
printf("Wakeup Source : ");
switch (wakeupSources)
{
case WAKEUP_RTC:
printf("WAKEUP_RTC ");
break;
case WAKEUP_BLE_HOST_TIMER:
printf("WAKEUP_BLE_HOST_TIMER ");
break;
case WAKEUP_BLE:
printf("WAKEUP_BLE ");
break;
case WAKEUP_PA11:
printf("WAKEUP_PA11 ");
break;
case WAKEUP_PA10:
printf("WAKEUP_PA10 ");
break;
case WAKEUP_PA9:
printf("WAKEUP_PA9 ");
break;
case WAKEUP_PA8:
printf("WAKEUP_PA8 ");
break;
case WAKEUP_PB7:
printf("WAKEUP_PB7 ");
break;
case WAKEUP_PB6:
printf("WAKEUP_PB6 ");
break;
case WAKEUP_PB5:
printf("WAKEUP_PB5 ");
break;
case WAKEUP_PB4:
printf("WAKEUP_PB4 ");
break;
case WAKEUP_PB3:
printf("WAKEUP_PB3 ");
break;
case WAKEUP_PB2:
printf("WAKEUP_PB2 ");
break;
case WAKEUP_PB1:
printf("WAKEUP_PB1 ");
break;
case WAKEUP_PB0:
printf("WAKEUP_PB0 ");
break;
default:
printf("0x%08x ", wakeupSources);
}
printf("\r\n");
}
void RTC_WakeupInit(void)
{
/* Enable Peripheral Clock */
LL_APB0_EnableClock(LL_APB0_PERIPH_RTC);
for (volatile int i=0; i<0xFFFF; i++);
/* Disable the write protection for RTC registers */
LL_RTC_DisableWriteProtection(RTC);
/* Init mode setup */
LL_RTC_EnableInitMode(RTC);
/* Wait till the Init mode is active */
while(LL_RTC_IsActiveFlag_INIT(RTC) == RESET);
/* Configure Hour Format */
LL_RTC_SetHourFormat(RTC, LL_RTC_HOURFORMAT_24HOUR);
/* Output disabled */
LL_RTC_SetAlarmOutEvent(RTC, LL_RTC_ALARMOUT_DISABLE);
/* Output polarity */
LL_RTC_SetOutputPolarity(RTC, LL_RTC_OUTPUTPOLARITY_PIN_HIGH);
/* Set Synchronous prescaler factor */
LL_RTC_SetSynchPrescaler(RTC, 31);
/* Set Asynchronous prescaler factor */
LL_RTC_SetAsynchPrescaler(RTC, 0);
/* Exit Initialization mode */
LL_RTC_DisableInitMode(RTC);
/* Enable write protection */
LL_RTC_EnableWriteProtection(RTC);
}
void SetRTC_WakeupTimeout(uint32_t time)
{
/* Disable write protection */
LL_RTC_DisableWriteProtection(RTC);
/* Disable Wake-up Timer */
LL_RTC_WAKEUP_Disable(RTC);
/* In case of interrupt mode is used, the interrupt source must disabled */
LL_RTC_DisableIT_WUT(RTC);
/* Wait till RTC WUTWF flag is set*/
while(LL_RTC_IsActiveFlag_WUTW(RTC) == 0);
/* Clear PWR wake up Flag */
LL_PWR_ClearWakeupSource(LL_PWR_EWS_INT);
/* Clear RTC Wake Up timer Flag */
LL_RTC_ClearFlag_WUT(RTC);
/* Configure the Wake-up Timer counter */
LL_RTC_WAKEUP_SetAutoReload(RTC, time);
/* Configure the clock source */
LL_RTC_WAKEUP_SetClock(RTC, LL_RTC_WAKEUPCLOCK_CKSPRE);
/* Configure the Interrupt in the RTC_CR register */
LL_RTC_EnableIT_WUT(RTC);
/* Enable the Wake-up Timer */
LL_RTC_WAKEUP_Enable(RTC);
/* Enable write protection */
LL_RTC_EnableWriteProtection(RTC);
/* Configure NVIC for RTC */
NVIC_SetPriority(RTC_IRQn, IRQ_LOW_PRIORITY);
NVIC_EnableIRQ(RTC_IRQn);
/* Clear RTC Wake Up timer Flag */
LL_RTC_ClearFlag_WUT(RTC);
}
void DisableRTC_WakeupTimeout(void)
{
/* Disable write protection */
LL_RTC_DisableWriteProtection(RTC);
/* Enable the Wake-up Timer */
LL_RTC_WAKEUP_Disable(RTC);
/* Enable write protection */
LL_RTC_EnableWriteProtection(RTC);
}
/**
* @briefTimeout callback.
* @paramTimer handle
* @retval None
*/
void TimeoutCallback(void *timerHandle)
{
/* Add app code to execute @ Stop timeout */
printf("Vtimer Timeout!!!!!\r\n");
}
/**
* @briefMain program.
* @paramNone
* @retval None
*/
int main(void)
{
uint8_t data, ret_val, tmp;
PartInfoType partInfo;
WakeupSourceConfig_TypeDef wakeupIO;
uint32_t wakeupSources;
PowerSaveLevels stopLevel;
HAL_VTIMER_InitType VTIMER_InitStruct;
/* System initialization function */
if (SystemInit(SYSCLK_32M, BLE_SYSCLK_16M) != SUCCESS) {
/* Error during system clock configuration take appropriate action */
while(1);
}
/* Configure IOs for pwer save modes */
BSP_IO_Init();
/* Init the UART peripheral */
BSP_COM_Init(BSP_COM_RxDataUserCb);
/* Init LED1 */
BSP_LED_Init(BSP_LED1);
/* Init BUTTON 1 */
BSP_PB_Init(BSP_PUSH1, BUTTON_MODE_EXTI);
/* VTimer module Init */
VTIMER_InitStruct.XTAL_StartupTime = HS_STARTUP_TIME;
VTIMER_InitStruct.EnableInitialCalibration = INITIAL_CALIBRATION;
VTIMER_InitStruct. PeriodicCalibrationInterval = CALIBRATION_INTERVAL;
HAL_VTIMER_Init(&VTIMER_InitStruct);
timerHandle.callback = TimeoutCallback;
/* RTC Wakeup Peripheral Init */
RTC_WakeupInit();
printf("Power Manager FW demo!\r\nDigit ? for help command\r\n");
while(1) {
/* To run the VTIMER state machine */
HAL_VTIMER_Tick();
if (BSP_COM_Read(&data)) {
switch(data)
{
case 's':
{
/* SHUTDOWN LEVEL : the only wakeup source is a low pulse on the RSTN pad */
printf("Enable Power Save Request : SHUTDOWN\r\n");
while(BSP_COM_UARTBusy());
if (HAL_PWR_MNGR_ShutdownRequest(TRUE) != SUCCESS)
printf("ERORR during the SHUTDOWN Request!\r\n");
}
break;
case 't':
{
/* POWER_SAVE_LEVEL_STOP_WITH_TIMER : wake on UART (PA8)/timeout 5 sec (VTIMER)/button PUSH1 (PA10) */
printf("Enable Power Save Request : STOP_WITH_TIMER (VTIMER)\r\n");
while(BSP_COM_UARTBusy());
wakeupIO.IO_Mask_High_polarity = WAKEUP_PA10;
wakeupIO.IO_Mask_Low_polarity = WAKEUP_PA8;
wakeupIO.RTC_enable = 0;
ret_val = HAL_VTIMER_StartTimerMs(&timerHandle, WAKEUP_TIMEOUT);
if (ret_val != SUCCESS) {
printf("HAL_VTIMER_StartTimerMs() error 0x%02x\r\n", ret_val);
while(1);
}
ret_val = HAL_PWR_MNGR_Request(POWER_SAVE_LEVEL_STOP_WITH_TIMER, wakeupIO, &stopLevel);
if (ret_val != SUCCESS)
printf("Error during clock config 0x%2x\r\n", ret_val);
PrintNegotiatedLevel(stopLevel);
if (stopLevel >= POWER_SAVE_LEVEL_STOP_WITH_TIMER) {
wakeupSources = HAL_PWR_MNGR_WakeupSource();
PrintWakeupSource(wakeupSources);
}
}
break;
case 'z':
{
/* POWER_SAVE_LEVEL_STOP_WITH_TIMER : wake on UART (PA8)/timeout 5 sec (RTC)/button PUSH1 (PA10) */
printf("Enable Power Save Request : STOP_WITH_TIMER (RTC)\r\n");
while(BSP_COM_UARTBusy());
wakeupIO.IO_Mask_High_polarity = WAKEUP_PA10;
wakeupIO.IO_Mask_Low_polarity = WAKEUP_PA8;
wakeupIO.RTC_enable = 1;
SetRTC_WakeupTimeout(WAKEUP_TIMEOUT);
ret_val = HAL_PWR_MNGR_Request(POWER_SAVE_LEVEL_STOP_WITH_TIMER, wakeupIO, &stopLevel);
if (ret_val != SUCCESS)
printf("Error during clock config 0x%2x\r\n", ret_val);
PrintNegotiatedLevel(stopLevel);
if (stopLevel >= POWER_SAVE_LEVEL_STOP_WITH_TIMER) {
wakeupSources = HAL_PWR_MNGR_WakeupSource();
PrintWakeupSource(wakeupSources);
}
DisableRTC_WakeupTimeout();
}
break;
case 'n':
{
/* POWER_SAVE_LEVEL_NOTIMER : wake on uart (PA8)/button PUSH1 (PA10) */
printf("Enable Power Save Request : STOP_NOTIMER\r\n");
while(BSP_COM_UARTBusy());
wakeupIO.IO_Mask_High_polarity = WAKEUP_PA10;
wakeupIO.IO_Mask_Low_polarity = WAKEUP_PA8;
wakeupIO.RTC_enable = 0;
ret_val = HAL_PWR_MNGR_Request(POWER_SAVE_LEVEL_STOP_NOTIMER, wakeupIO, &stopLevel);
if (ret_val != SUCCESS)
printf("Error during clock config 0x%2x\r\n", ret_val);
PrintNegotiatedLevel(stopLevel);
if (stopLevel >= POWER_SAVE_LEVEL_STOP_WITH_TIMER) {
wakeupSources = HAL_PWR_MNGR_WakeupSource();
PrintWakeupSource(wakeupSources);
}
}
break;
case 'c':
{
/* POWER_SAVE_LEVEL_CPU_HALT : wake on button PUSH1 (PA10) */
printf("Enable Power Save Request : CPU_HALT\r\n");
while(BSP_COM_UARTBusy());
__WFI();
printf("Exit from WFI cortex instruction with interrupt\r\n");
/* Empty the USART buffer */
while(BSP_COM_Read(&tmp));
}
break;
case 'l':
{
/* Toggle led LED1 */
BSP_LED_Toggle(BSP_LED1);
}
break;
case 'p':
{
HAL_GetPartInfo(&partInfo);
printf("Hello World: BlueNRG-LP (%d.%d) is here!\r\n",
partInfo.die_major,
partInfo.die_cut);
}
break;
case 'r':
{
/* Reset BlueNRG-LP */
NVIC_SystemReset();
}
break;
case '?':
{
/* Help command */
help();
}
break;
default:
printf("UNKNWON COMMAND! Press ? for command list\r\n");
}
}
}
}
#ifdefUSE_FULL_ASSERT
/**
* @briefReports the name of the source file and the source line number
* where the assert_param error has occurred.
* @paramfile: pointer to the source file name
* @paramline: assert_param error line source number
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
</code></pre>
<p> </p>
<p>https://www.st.com/resource/en/programming_manual/dm00698052-bluetooth-le-stack-v3x-programming-guidelines-stmicroelectronics.pdf</p>
<p>第38页</p>
<p> </p>
<p> </p>
<p> </p>
littleshrimp 发表于 2021-7-9 16:53
试过Power Save Modes这个例程没?
/******************** (C) COPYRIGHT...
<p>有试过这个例程,进sleep模式是没问题。我当前这个程序也能进sleep模式,但反复几次进sleep模式然后唤醒,就会有一次进不了sleep模式,会返回run这个状态。</p>
littleshrimp 发表于 2021-7-9 17:11
https://www.st.com/resource/en/programming_manual/dm00698052-bluetooth-le-stack-v3x-programming-guid ...
<p>现在就是有点怀疑是被Ble资源唤醒的。刚接触蓝牙,对这些接口不太熟,我现在调用HAL_PWR_MNGR_Request(POWER_SAVE_LEVEL_STOP_NOTIMER, wakeupIO, &stopLevel)这个函数之前,都会调用一下aci_gap_set_advertising_enable(0, 0, Advertising_Set_Parameters)来关闭Ble广播,请问还有BLE部分还有什么要关闭的嘛,我先排查一下是不是BLE部分有时候未及时关闭导致的; </p>
本帖最后由 littleshrimp 于 2021-7-11 18:12 编辑
<div class="quote">
<blockquote><font size="2"><a href="forum.php?mod=redirect&goto=findpost&pid=3076770&ptid=1171810" target="_blank"><font color="#999999">乌鸦哥 发表于 2021-7-9 18:01</font></a></font> 现在就是有点怀疑是被Ble资源唤醒的。刚接触蓝牙,对这些接口不太熟,我现在调用HAL_PWR_MNGR_Request(PO ...</blockquote>
</div>
<p>上边文档的37页有段代码</p>
<p>代码粘贴有点问题</p>
<p></p>
<pre>
<code class="language-cpp">int main(void) { WakeupSourceConfig_TypeDef wakeupIO; PowerSaveLevels stopLevel; BLE_STACK_InitTypeDef BLE_STACK_InitParams = BLE_STACK_INIT_PARAMETERS; /* System initialization function */ if (SystemInit(SYSCLK_64M, BLE_SYSCLK_32M) != SUCCESS) { * Error during system clock configuration take appropriate action */ while(1); } /* Configure IOs for power save modes */ BSP_IO_Init(); /* Configure I/O communication channel */ BSP_COM_Init(BSP_COM_RxDataUserCb); /* Enable clock for PKA and RNG IPs used by BLE radio */ LL_AHB_EnableClock(LL_AHB_PERIPH_PKA|LL_AHB_PERIPH_RNG); ret = BLE_STACK_Init(&BLE_STACK_InitParams); if (ret != BLE_STATUS_SUCCESS) { printf("Error in BLE_STACK_Init() 0x%02x\r\n", ret); while(1); } BLECNTR_InitGlobal(); /* Init Virtual Timer module */ HAL_VTIMER_InitType VTIMER_InitStruct = {HS_STARTUP_TIME, INITIAL_CALIBRATION, CALIBRATION_INTERVAL}; HAL_VTIMER_Init(&VTIMER_InitStruct); /* Init NVM module */ BLEPLAT_Init(); if (PKAMGR_Init() == PKAMGR_ERROR) { while(1); } if (RNGMGR_Init() != RNGMGR_SUCCESS) { while(1); } /* Init the AES block */ AESMGR_Init(); /* Device Initialization: GATT and GAP Init APIs. It could add services and characteristics (if it is a GATT server) It could also initialize its state machine and other specific drivers ( i.e. leds, buttons, sensors, …) */ ret = DeviceInit(); if (ret != BLE_STATUS_SUCCESS) { while(1); } /* Set wakeup sources if needed through the wakeupIO. Variable */ /* No wakeup sources: */ wakeupIO.IO_Mask_High_polarity = 0; wakeupIO.IO_Mask_Low_polarity = 0; wakeupIO.RTC_enable = 0; wakeupIO.LPU_enable = 0; while(1) { /* Timer tick */ HAL_VTIMER_Tick(); /* BLE stack tick */ BLE_STACK_Tick(); /* NVM managertick */ NVMDB_Tick(); /* Application Tick: user application where application state machine is handled*/ APP_Tick(); /* Power Save management*/ /* It enables power save modes with wakeup on radio operating timings (adverting, connections intervals) */ HAL_PWR_MNGR_Request(POWER_SAVE_LEVEL_STOP_NOTIMER,wakeupIO, &stopLevel); }/* while (1) */ } /* end main() */</code></pre>
<p> </p>
<div class='shownolgin' data-isdigest='no'>littleshrimp 发表于 2021-7-11 18:11
乌鸦哥 发表于 2021-7-9 18:01 现在就是有点怀疑是被Ble资源唤醒的。刚接触蓝牙,对这些接口不太熟,我现 ...
<p>大虾哥,我就是这个框架写的。不过HAL_PWR_MNGR_Request(POWER_SAVE_LEVEL_STOP_NOTIMER,wakeupIO, &stopLevel)这个函数现在不是按照例程这样调用的。我现在是想长时间进入休眠状态,PA10z作为按键外部中断,每按五次就调用HAL_PWR_MNGR_Request进入休眠,第六次唤醒,如此反复,但现在不是每次都能进入休眠状态,有时候调用HAL_PWR_MNGR_Request(POWER_SAVE_LEVEL_STOP_NOTIMER,wakeupIO, &stopLevel),会返回一个RUNNING的状态。</p>
</div><script>showreplylogin();</script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script> <div class='shownolgin' data-isdigest='no'>乌鸦哥 发表于 2021-7-12 18:02
大虾哥,我就是这个框架写的。不过HAL_PWR_MNGR_Request(POWER_SAVE_LEVEL_STOP_NOTIMER,wakeupIO, &st ...
<p>循环调用HAL_PWR_MNGR_Request函数,然后判断stopLevel,看看需要多少次能不返回POWER_SAVE_LEVEL_RUNNING</p>
<p>还有一个文档可以参考下</p>
<p>https://www.st.com/content/ccc/resource/technical/document/application_note/group1/7a/e9/f2/d9/8c/b2/4f/b1/DM00691849/files/DM00691849.pdf/jcr:content/translations/en.DM00691849.pdf</p>
</div><script>showreplylogin();</script>
页:
[1]