From eef62bb93dd0775d5871cc69de0ddba085c8df4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Sim=C3=B5es?= Date: Thu, 3 Jan 2019 10:36:32 +0000 Subject: [PATCH] Improvements on STM32 low power MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix some registers set/reset. - Remove void from nanoHAL_Uninitialize_C calls. - Add missing configurations to wake from pin (STM32F7 series only). - Remove setting code from CPU_SetPowerMode to pin and rtc blocks. - Add code to SetPowerMode to freeze IWDG on STDBY (STM32F7 only). Signed-off-by: José Simões --- ...ive_nanoFramework_Hardware_Stm32_Power.cpp | 57 ++++++++++++++-- ...ative_nanoFramework_Hardware_Stm32_RTC.cpp | 21 +++++- .../CMSIS-OS/ChibiOS/nanoCLR/targetHAL.cpp | 2 +- .../ChibiOS/nanoCLR/targetHAL_Power.c | 66 +++++++++++++++++-- .../hal/ports/STM32/LLD/FLASHv2/flash_lld.h | 7 +- .../ESP32_DevKitC/nanoCLR/targetHAL.cpp | 2 +- 6 files changed, 140 insertions(+), 15 deletions(-) diff --git a/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Power.cpp b/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Power.cpp index 6ad4f2d542..219a523710 100644 --- a/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Power.cpp +++ b/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Power.cpp @@ -97,39 +97,85 @@ HRESULT Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Power::Ena switch((WakeupPin)stack.Arg0().NumericByRef().u4) { #if defined(PWR_CSR_EWUP) + case WakeupPin_Pin1: wakeUpPin = PWR_CSR_EWUP; + + // need to config the respective EXTI line (PA0) + EXTI->IMR |= EXTI_IMR_IM0; + EXTI->RTSR |= EXTI_RTSR_TR0; + break; + #elif defined(PWR_CSR_EWUP1) + case WakeupPin_Pin1: wakeUpPin = PWR_CSR_EWUP1; + // need to config the respective EXTI line (PA0) + EXTI->IMR |= EXTI_IMR_IM0; + EXTI->RTSR |= EXTI_RTSR_TR0; break; + #elif defined(PWR_CSR2_EWUP1) + case WakeupPin_Pin1: wakeUpPin = PWR_CSR2_EWUP1; + + // need to config the respective EXTI line (PA0) + EXTI->IMR |= EXTI_IMR_IM0; + EXTI->RTSR |= EXTI_RTSR_TR0; + break; + #else #error "missing include for STM32 target PAL" #endif #if defined(PWR_CSR_EWUP2) + case WakeupPin_Pin2: wakeUpPin = PWR_CSR_EWUP2; + + // need to config the respective EXTI line (PA2) + EXTI->IMR |= EXTI_IMR_IM2; + EXTI->RTSR |= EXTI_RTSR_TR2; break; + #elif defined(PWR_CSR2_EWUP2) + case WakeupPin_Pin2: wakeUpPin = PWR_CSR2_EWUP2; + + // need to config the respective EXTI line (PA2) + EXTI->IMR |= EXTI_IMR_IM2; + EXTI->RTSR |= EXTI_RTSR_TR2; + break; + #endif #if defined(PWR_CSR_EWUP3) + case WakeupPin_Pin3: wakeUpPin = PWR_CSR_EWUP3; + + // need to config the respective EXTI line (PC1) + EXTI->IMR |= EXTI_IMR_IM1; + EXTI->RTSR |= EXTI_RTSR_TR1; + break; + #elif defined(PWR_CSR2_EWUP3) + case WakeupPin_Pin3: wakeUpPin = PWR_CSR2_EWUP3; + + // need to config the respective EXTI line (PC1) + EXTI->IMR |= EXTI_IMR_IM1; + EXTI->RTSR |= EXTI_RTSR_TR1; + break; + #endif default: @@ -141,6 +187,8 @@ HRESULT Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Power::Ena #if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F2XX) || \ defined(STM32F3XX) ||defined(STM32F4XX) || defined(STM32L0XX) || defined(STM32L1XX) + // clear PWR wake up Flag + PWR->CR |= PWR_CSR_WUF; // disable the wake up pin CLEAR_BIT(PWR->CSR, wakeUpPin); @@ -151,15 +199,16 @@ HRESULT Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Power::Ena #endif #if defined(STM32F7XX) || defined(STM32H7XX) || defined(STM32L4XX) + // clear PWR wake up Flag + PWR->CR1 |= PWR_CR1_CSBF; // disable the wake up pin - CLEAR_BIT(PWR->CSR1, wakeUpPin); + CLEAR_BIT(PWR->CSR2, wakeUpPin); // enable the wake up pin - SET_BIT(PWR->CSR1, wakeUpPin); - - #endif + SET_BIT(PWR->CSR2, wakeUpPin); + #endif NANOCLR_NOCLEANUP(); } diff --git a/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_RTC.cpp b/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_RTC.cpp index 168032c7f2..9f27fda79a 100644 --- a/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_RTC.cpp +++ b/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_RTC.cpp @@ -65,9 +65,24 @@ HRESULT Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_RTC::Nativ alarmTime.alrmr = alarmRegister; - #else - #error "Setting an alarm for this series in not supported. Care to look into it and submit a PR?" - #endif + #else + #error "Setting an alarm for this series in not supported. Care to look into it and submit a PR?" + #endif + + #if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F2XX) || \ + defined(STM32F3XX) ||defined(STM32F4XX) || defined(STM32L0XX) || defined(STM32L1XX) + // clear PWR wake up Flag + PWR->CR |= PWR_CSR_WUF; + #endif + + #if defined(STM32F7XX) || defined(STM32H7XX) || defined(STM32L4XX) + // clear PWR wake up Flag + PWR->CR1 |= PWR_CR1_CSBF; + + EXTI->EMR |= EXTI_IMR_IM17; + EXTI->RTSR |= EXTI_RTSR_TR17; + + #endif rtcSetAlarm(&RTCD1, ALARM_ID, &alarmTime); diff --git a/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL.cpp b/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL.cpp index 46d954ada4..06fa721c29 100644 --- a/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL.cpp +++ b/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL.cpp @@ -22,7 +22,7 @@ extern "C" { void nanoHAL_Uninitialize_C() { - void nanoHAL_Uninitialize(); + nanoHAL_Uninitialize(); } } diff --git a/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL_Power.c b/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL_Power.c index 9ca2cc3b0a..365ba2414e 100644 --- a/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL_Power.c +++ b/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL_Power.c @@ -19,6 +19,9 @@ inline void CPU_Sleep(SLEEP_LEVEL_type level, uint64_t wakeEvents) { (void)level void CPU_SetPowerMode(PowerLevel_type powerLevel) { + // default to false + bool success = false; + switch(powerLevel) { case PowerLevel__Off: @@ -30,18 +33,71 @@ void CPU_SetPowerMode(PowerLevel_type powerLevel) chSysDisable(); - // set power controll register to power down deep sleep + ///////////////////////////////////////////////////////////////////////// + // stop the idependent watchdog, for series where the option is available + #if defined(STM32L4XX) + + (void)success; + // TODO FIXME this code needs to follow the same workflow as the STM32F7 + CLEAR_BIT(FLASH->OPTR, FLASH_OPTR_IWDG_STDBY); + + #elif defined(STM32F7XX) + + // only need to change this option bit if not already done + if(!(FLASH->OPTCR & ~FLASH_OPTCR_IWDG_STDBY)) + { + // developer notes: + // follow workflow recommended @ 3.4.2 Option bytes programming (from programming manual) + // Authorizes the Option Byte register programming + FLASH->OPTKEYR = FLASH_OPT_KEY1; + FLASH->OPTKEYR = FLASH_OPT_KEY2; + + // wait 500ms for any flash operation to be completed + success = FLASH_WaitForLastOperation(500); + + if(success) + { + // write option value (clear the FLASH_OPTCR_IWDG_STDBY) + CLEAR_BIT(FLASH->OPTCR, FLASH_OPTCR_IWDG_STDBY); + + // set the option start bit + FLASH->OPTCR |= FLASH_OPTCR_OPTSTRT; + + // Data synchronous Barrier, forcing the CPU to respect the sequence of instruction without optimization + __DSB(); + + // wait 100ms for the flash operation to be completed + success = FLASH_WaitForLastOperation(100); + } + + // Set the OPTLOCK Bit to lock the FLASH Option Byte Registers access + FLASH->OPTCR |= FLASH_OPTCR_OPTLOCK; + } + + #elif defined(STM32H7XX) + + (void)success; + // TODO FIXME this code needs to follow the same workflow as the STM32F7 + CLEAR_BIT(FLASH->OPTSR, FLASH_OPTSR_FZ_IWDG_SDBY); + + #else + (void)success; + #endif + + /////////////////////////////////////////////////////// + // set power control register to: power down deep sleep #if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F2XX) || \ defined(STM32F3XX) ||defined(STM32F4XX) || defined(STM32L0XX) || defined(STM32L1XX) - SET_BIT(PWR->CR, PWR_CR_PDDS); - #endif - #if defined(STM32F7XX) || defined(STM32H7XX) || defined(STM32L4XX) - + #if defined(STM32F7XX) + CLEAR_BIT(PWR->CSR1, PWR_CSR1_WUIF); SET_BIT(PWR->CR1, PWR_CR1_PDDS); + #endif + #if defined(STM32H7XX) + SET_BIT(PWR->CR1, PWR_CR1_PDDS); #endif // set SLEEPDEEP bit of Cortex SCR diff --git a/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv2/flash_lld.h b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv2/flash_lld.h index ace4606a8e..4cb24142ce 100644 --- a/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv2/flash_lld.h +++ b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv2/flash_lld.h @@ -46,6 +46,8 @@ typedef struct SMT32FlashDriver { #define HAL_IS_BIT_SET(REG, BIT) (((REG) & (BIT)) != RESET) #define FLASH_KEY1 ((uint32_t)0x45670123U) #define FLASH_KEY2 ((uint32_t)0xCDEF89ABU) +#define FLASH_OPT_KEY1 ((uint32_t)0x08192A3BU) +#define FLASH_OPT_KEY2 ((uint32_t)0x4C5D6E7FU) #define SECTOR_MASK ((uint32_t)0xFFFFFF07) // FLASH_Error_Code FLASH Error Code @@ -426,7 +428,10 @@ SMT32FlashDriver STM32FLASH; #ifdef __cplusplus extern "C" { #endif - + bool HAL_FLASH_Unlock(void); + void HAL_FLASH_Lock(void); + bool FLASH_WaitForLastOperation(uint32_t timeout); + void flash_lld_init(); void flash_lld_readBytes(uint32_t startAddress, uint32_t length, uint8_t* buffer); int flash_lld_write(uint32_t startAddress, uint32_t length, const uint8_t* buffer); diff --git a/targets/FreeRTOS/ESP32_DevKitC/nanoCLR/targetHAL.cpp b/targets/FreeRTOS/ESP32_DevKitC/nanoCLR/targetHAL.cpp index 62d57324d4..1501728f90 100644 --- a/targets/FreeRTOS/ESP32_DevKitC/nanoCLR/targetHAL.cpp +++ b/targets/FreeRTOS/ESP32_DevKitC/nanoCLR/targetHAL.cpp @@ -42,7 +42,7 @@ extern "C" { void nanoHAL_Uninitialize_C() { - void nanoHAL_Uninitialize(); + nanoHAL_Uninitialize(); } }