From 34e43c7ee9700249dc6e5b333b7c264d45d6b530 Mon Sep 17 00:00:00 2001
From: Damien George <damien.p.george@gmail.com>
Date: Mon, 25 Aug 2014 18:12:44 +0100
Subject: [PATCH] stmhal: Improve efficiency of SysTick IRQ and HAL_Delay.

SysTick IRQ now increases millisecond counter directly (ie without
calling HAL_IncTick).  Provide our own version of HAL_Delay that does a
wfi while waiting.  This more than halves power consumption when running
a loop containing a pyb.delay call.  It used to be like this, but new
version of HAL library regressed this feature.
---
 stmhal/hal/src/stm32f4xx_hal.c |  2 +-
 stmhal/stm32f4xx_it.c          |  6 +++++-
 stmhal/systick.c               | 12 ++++++++++++
 3 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/stmhal/hal/src/stm32f4xx_hal.c b/stmhal/hal/src/stm32f4xx_hal.c
index 6c076c358..0040658a0 100644
--- a/stmhal/hal/src/stm32f4xx_hal.c
+++ b/stmhal/hal/src/stm32f4xx_hal.c
@@ -93,7 +93,7 @@
 #define CMPCR_CMP_PD_BB           (PERIPH_BB_BASE + (CMPCR_OFFSET * 32) + (CMP_PD_BitNumber * 4))
 /* Private macro -------------------------------------------------------------*/
 /* Private variables ---------------------------------------------------------*/
-static __IO uint32_t uwTick;
+__IO uint32_t uwTick;
 
 /* Private function prototypes -----------------------------------------------*/
 /* Private functions ---------------------------------------------------------*/
diff --git a/stmhal/stm32f4xx_it.c b/stmhal/stm32f4xx_it.c
index 4bd13c05c..74fdf53d1 100644
--- a/stmhal/stm32f4xx_it.c
+++ b/stmhal/stm32f4xx_it.c
@@ -173,7 +173,11 @@ void PendSV_Handler(void) {
   * @retval None
   */
 void SysTick_Handler(void) {
-    HAL_IncTick();
+    // Instead of calling HAL_IncTick we do the increment here of the counter.
+    // This is purely for efficiency, since SysTick is called 1000 times per
+    // second at the highest interrupt priority.
+    extern __IO uint32_t uwTick;
+    uwTick += 1;
 
     // Read the systick control regster. This has the side effect of clearing
     // the COUNTFLAG bit, which makes the logic in sys_tick_get_microseconds
diff --git a/stmhal/systick.c b/stmhal/systick.c
index b2381d08e..b4dd68ffe 100644
--- a/stmhal/systick.c
+++ b/stmhal/systick.c
@@ -33,6 +33,18 @@
 #include "irq.h"
 #include "systick.h"
 
+// We provide our own version of HAL_Delay that calls __WFI while waiting, in
+// order to reduce power consumption.
+void HAL_Delay(uint32_t Delay) {
+    extern __IO uint32_t uwTick;
+    uint32_t start = uwTick;
+    // Wraparound of tick is taken care of by 2's complement arithmetic.
+    while (uwTick - start < Delay) {
+        // Enter sleep mode, waiting for (at least) the SysTick interrupt.
+        __WFI();
+    }
+}
+
 bool sys_tick_has_passed(uint32_t start_tick, uint32_t delay_ms) {
     return HAL_GetTick() - start_tick >= delay_ms;
 }
-- 
GitLab