Does using a software delay() function have greater power consumption than using a System Timer interrupt?
Being curious myself I've made some simple measurements on a 32L152CDISCOVERY board. My test program consists of 4 tests, each displaying the elapsed seconds on the LCD. The difference between the test is what they do until a second elapses.


The first test does nothing inside the loop. It's a pure "busy loop", spinning until a variable changes.
The second loop has a single NOP instruction inside.
The third loop executes 1000 NOP instructions in a row.
The fourth loop executes a WFI instruction, sleeping until an interrupt occurs.


Pressing the blue button advances to the next test.

There are two compile-time parameters.


Defining SLOWTICK changes the SysTick interrupt frequency from 1 kHz to 1 Hz.
Defining ALIGN_OFF inserts a NOP before each test loop, changing their alignment.


The code:

#define STM32L152xC
#include "stm32l1xx.h"
#include "lcd.h"

//#define SLOWTICK
//#define ALIGN_OFF

volatile int tick_s;
void SysTick_Handler() {
#ifdef SLOWTICK
    tick_s += 1;
#else
    static int tick_ms;
    tick_ms += 1;
    if(tick_ms == 1000) {
        tick_ms = 0;
        tick_s += 1;
    }
#endif
}

void hw_init() {
    // use the 16MHz internal HSI as clock source, no PLL
    RCC-&gt;CR |= RCC_CR_HSION;
    while(!(RCC-&gt;CR &amp; RCC_CR_HSIRDY))
        ;
    RCC-&gt;CFGR |= RCC_CFGR_SW_HSI;
    while((RCC-&gt;CFGR &amp; RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
        ;
    SystemCoreClockUpdate();

    // enable GPIOs for the LCD and the pushbutton
    RCC-&gt;AHBENR = RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN;
    __ISB(); // wait a bit, see STM32L1 errata on RCC
    lcd_init();
#ifdef SLOWTICK
    SysTick_Config(SystemCoreClock);
#else
    SysTick_Config(SystemCoreClock / 1000);
#endif
}

int last_s = -1;

void display_s() {
    int d1 = (last_s / 10) % 10;
    int d2 = last_s % 10;
    lcd_displaychar(d1 + '0', 0, 0, 5);
    lcd_displaychar(d2 + '0', 0, 0, 6);
    lcd_update();
}

// repeats an instruction 10 times
#define TEN(x) ({ ({ x; }); ({ x; }); ({ x; }); ({ x; }); ({ x; }); \
                  ({ x; }); ({ x; }); ({ x; }); ({ x; }); ({ x; }); })

int button_pressed() {
    return GPIOA-&gt;IDR &amp; 1;
}

int main() {
    hw_init();
    int temp_s;
    while(1) {
        lcd_displaytext("0NOP");
        asm volatile(".align 4");
#ifdef ALIGN_OFF
        asm volatile("nop");
#endif
        while(1) {
            while(1) {
                temp_s = tick_s;
                if(temp_s != last_s)
                    break;
            }
            last_s = temp_s;
            display_s();
            if(button_pressed())
                break;
        }
        while(button_pressed())
            ;

        lcd_displaytext("1NOP");
        asm volatile(".align 4");
#ifdef ALIGN_OFF
        asm volatile("nop");
#endif
        while(1) {
            while(1) {
                temp_s = tick_s;
                if(temp_s != last_s)
                    break;
                asm volatile("nop");
            }
            last_s = temp_s;
            display_s();
            if(button_pressed())
                break;
        }
        while(button_pressed())
            ;

        lcd_displaytext("xNOP");
        asm volatile(".align 4");
#ifdef ALIGN_OFF
        asm volatile("nop");
#endif
        while(1) {
            while(1) {
                temp_s = tick_s;
                if(temp_s != last_s)
                    break;
                // triple nesting repeats 10*10*10 times
                TEN(TEN(TEN(asm volatile("nop"))));
            }
            last_s = temp_s;
            display_s();
            if(button_pressed())
                break;
        }
        while(button_pressed())
            ;

        lcd_displaytext("WFI");
        asm volatile(".align 4");
#ifdef ALIGN_OFF
        asm volatile("nop");
#endif
        while(1) {
            while(1) {
                temp_s = tick_s;
                if(temp_s != last_s)
                    break;
                asm volatile("wfi");
            }
            last_s = temp_s;
            display_s();
            if(button_pressed())
                break;
        }
        while(button_pressed())
            ;
    }
}


Power consumption of the MCU was measured by connecting an ammeter between pins 1 and 2 of JP1. The debugger war disconnected by removing the jumper caps from CN3.

                      +--------+--------+--------+--------+
                      | Test 1 | Test 2 | Test 3 | Test 4 |
                      | 0NOP   | 1NOP   | xNOP   | WFI    |
+---------------------+--------+--------+--------+--------+
| //#define SLOWTICK  |        |        |        |        |
| //#define ALIGN_OFF | 4.3 mA | 4.7 mA | 2.8 mA | 1.4 mA |
+---------------------+--------+--------+--------+--------+
| //#define SLOWTICK  |        |        |        |        |
| #define ALIGN_OFF   | 5.0 mA | 4.8 mA | 2.8 mA | 1.4 mA |
+---------------------+--------+--------+--------+--------+
| #define SLOWTICK    |        |        |        |        |
| //#define ALIGN_OFF | 4.3 mA | 4.7 mA | 2.8 mA | 1.4 mA |
+---------------------+--------+--------+--------+--------+
| #define SLOWTICK    |        |        |        |        |
| #define ALIGN_OFF   | 4.9 mA | 4.8 mA | 2.8 mA | 1.4 mA |
+---------------------+--------+--------+--------+--------+


Conclusions:


Changing code alignment can significatly affect consumption.
Executing lots of NOP instructions reduces consumption, but it can be tricky to generate the exact number of instructions needed for a particular delay. Not to mention the memory requirement.
Putting the controller to sleep is the real power saver.